Winston: self._addDefaultMeta is not a function error still occurs with 3.2.1

Created on 31 Jan 2019  路  13Comments  路  Source: winstonjs/winston

Please tell us about your environment:

  • _winston version?_

    • [ ] winston@2

    • [x] 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 https://github.com/winstonjs/winston/blob/efd7baf65da13edaba7829aa4339757eed4322eb/lib/winston/create-logger.js#L80

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

Most helpful comment

Another way I found that works is to bind:

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

All 13 comments

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

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 :)

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 :)

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)

Another way I found that works is to bind:

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

@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

`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

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

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

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

@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.

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JaehyunLee-B2LiNK picture JaehyunLee-B2LiNK  路  3Comments

alditis picture alditis  路  3Comments

Infinitay picture Infinitay  路  3Comments

bertolo1988 picture bertolo1988  路  3Comments

xungwoo picture xungwoo  路  3Comments