Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

self._addDefaultMeta is not a function error still occurs with 3.2.1 #1591

Closed
1 of 2 tasks
papandreou opened this issue Jan 31, 2019 · 13 comments
Closed
1 of 2 tasks

Comments

@papandreou
Copy link

Please tell us about your environment:

  • winston version?
    • winston@2
    • winston@3
  • node -v outputs: 11.6.0
  • Operating System? OSX
  • Language? ES6/7

What is the problem?

Seems like #1579 did not fully fix the _addDefaultMeta bug. After upgrading to winston 3.2.1 I still get this error in my app at

self._addDefaultMeta(info);

Full stack trace:

TypeError: self._addDefaultMeta is not a function
  at Object.DerivedLogger.(anonymous function) [as log] (/path/to/project/node_modules/winston/lib/winston/create-logger.js:80:14)
  at module.exports.<anonymous> (/path/to/project/node_modules/sequelize-fixtures/lib/writer.js:39:16)
  at module.exports.tryCatcher (/path/to/project/node_modules/bluebird/js/release/util.js:16:23)
  at module.exports.writeFile (/path/to/project/node_modules/bluebird/js/release/method.js:15:34)
  at updateReferences (/path/to/project/services/sample_data/index.js:919:6)
  at Object.import (/path/to/project/services/sample_data/index.js:961:13)

What do you expect to happen instead?

That my app does not crash with the above error

@kibertoad
Copy link
Contributor

Could you please provide reproduction code? Ideally a complete test that fails, e. g. based on https://github.com/winstonjs/winston/blob/master/test/logger.test.js

@papandreou
Copy link
Author

Yeah, I was going to try to narrow it down and follow up with that, but wanted to raise the issue as fast as possible in case someone could figure it out :)

@papandreou
Copy link
Author

Seems to boil down to:

const winston = require('winston');

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console()
  ]
});

const logHelper = {
  log: logger.info
};

logHelper.log('Hello');

Works in 3.1.0, but fails in 3.2.1 with:

TypeError: self._addDefaultMeta is not a function
    at Object.DerivedLogger.(anonymous function) [as log] (/Users/andreaslind/work/api/node_modules/winston/lib/winston/create-logger.js:80:14)

It feels like a misuse of the API as it's not really fair game to pick out a method and call it on another object. Still, it used to work, so gray area :)

@indexzero
Copy link
Member

Thanks for reporting this bug, but yes: the failure is by design. If you would like to create another object with it's own properties that is still a logger, use Object.create (logger, extraProps)

@tizmagik
Copy link

Another way I found that works is to bind:

const logHelper = {
  log: logger.info.bind(logger)
};

@vongohren
Copy link

@indexzero I dont understand how I can create a log helper like wished for here with the sentence you provided?
What @tizmagik did mention, works, but I want to avoid binding stuff

@abilash1104
Copy link

`const winston = require('winston');

const logger = winston.createLogger({
transports: [
new winston.transports.Console()
]
});

const logHelper = {
log: logger.info.bind(logger)
};

module.exports.log = {
custom:logHelper,
inspect:false,
level: process.env.SAILS_LOG_LEVEL || 'debug'

};`
I am trying to configure sails.log in config/log.js using the above code.
But it's not logging out anything.
Can someone please guide on the above problem.
@indexzero @tizmagik @vongohren

@vongohren
Copy link

So this logger.info.bind(logger) works for me. But I cannot say why.
Can anyone tell me why this is not documented anywhere or why.
Is this bad design by us developers who end up doing bind?
Or @indexzero

@kibertoad
Copy link
Contributor

@vongohren see https://stackoverflow.com/questions/45910018/how-to-bind-methods-when-destructuring-an-object-in-javascript

@ionizer
Copy link

ionizer commented Apr 27, 2020

Binding somehow solved my issues with maximum call stack. Would love a good explanation on why this works or an actual solution... but thanks!

@vongohren
Copy link

@ionizer me too, just didnt get the stackoverflow posted earlier. maybe @indexzero can chime in?

@ionizer
Copy link

ionizer commented May 8, 2020

@vongohren I think I get it now, though it's a bit hard for me to explain. In some cases where we wrap the logger in an object like so:

const logHelper = {
  log: logger.info
};

...the logger.info function is almost like it's scope is being isolated inside the logHelper object because it's not bound.

The exact explanation according to the SO answer is that outside the logHelper object, logHelper.log() fails because logger.info's context is lost outside of the wrapping object. So binding works because it binds the wrapped logger's context in a way that it's also available outside the object.

EDIT: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
I feel my explanation is somewhat correct, but not exactly accurate. So what happens in the MDN example is that the reference to this is lost when a function that refers to this is being called outside of the object.

@vongohren
Copy link

@ionizer ah ok! Did not now the context inside the object dissapeard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants