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

logger.error() should support single raw error object for custom formatting #1642

Open
ajmas opened this issue May 7, 2019 · 7 comments
Open

Comments

@ajmas
Copy link

ajmas commented May 7, 2019

Please tell us about your environment:

  • winston version? winston@3.21
  • node -v outputs: v10.15.3
  • Operating System? macOS 10.14.4
  • Language? typescript@2.9.2

What is the problem?

If I call logger.error(error) and then use a custom formatter then the message is undefined and so is the stack. On the other hand logger.error(error.message, error) works (though this results in the message text duplicating the error title).

const err = new Error('an error');
// no error passed to custom formatter 
logger.error(err);
// needing to pass a dummy empty message
logger.error('', err);

Formatter that was being used:

const customFormat = printf((options) => {
    const {level, message, label, timestamp, error, stack} = options;
    return `${timestamp} [${label}] ${level.toUpperCase()}: ${message}`;
});

What do you expect to happen instead?

It would be useful for both error() and warn() type to support having a raw error object passed, such that:

function (message, error) {
   if (message instanceof Error) {
      error = message;
   }
  // ... do the normal stuff
}

Allowing me to simply do:

logger.error(new Error('an error'));

Other information

@ajmas ajmas changed the title logger.error() should support raw error object for custom formatting logger.error() should support single raw error object for custom formatting May 7, 2019
@newtykip
Copy link

I second this - I usually use winston-error to combat this, but it has stopped working as of winston@3.2.1.

@gaastonsr
Copy link

I thought this was fixed in #1562 :(

@bdharrington7
Copy link

I've come across this issue as well, but the problem I found is in the logform module.

@ajmas did you find this when you're setting the formatter on a transport? For example, this works (and there's a test for it):

const logger = createLogger({
  transports: [
    new transports.Console()
  ],
  format: combine(
    timestamp(),
    printf((options) => {
      const {level, message, timestamp, error, stack} = options;
      return `${timestamp} ${level.toUpperCase()}: ${message}`
    })
  )

})
const err = new Error('Something bad happened')
logger.error(err)  // outputs "2019-06-17T05:37:36.251Z ERROR: Something bad happened"

but this does not:

const logger = createLogger({
  transports: [
    new transports.Console({
      format: combine(
        timestamp(),
        printf((options) => {
          const {level, message, timestamp, error, stack} = options;
          return `${timestamp} ${level.toUpperCase()}: ${message}`
        })
      )
    })
  ],
})
const err = new Error('Something bad happened')
logger.error(err)  // outputs "2019-06-17T05:39:32.601Z ERROR: undefined"

I think it's related to this issue: winstonjs/logform#87 which has an open PR that might fix it.

This is supposedly a supported feature, but a test for this scenario must have been missed.

@ajmas
Copy link
Author

ajmas commented Jun 17, 2019

Very subtle difference, that didn’t jump out at me on first read. I am guessing I wouldn’t be alone there, especially since they should both be valid?

For my exact code I will need to wait until I have computer access (on my mobile here).

@greenj5
Copy link

greenj5 commented Aug 16, 2019

I am also having this issue and tracked the root cause down to winston-transport here:
https://github.com/winstonjs/winston-transport/blob/master/index.js#L91
The "info" is the error object, so the Object.assign call is not copying over the prototype fields - message, stack, etc.

@cesarjhony
Copy link

cesarjhony commented Aug 21, 2019

I made a very simple work around, using the proxy way.

let geralLogger = configuredWinstonLogger;
const error_handler = {
            apply: function (target, thisArg, argumentsList) {
                if (argumentsList.length >= 2 || argumentsList.length <= 0 || (typeof argumentsList[0] === 'string' || argumentsList[0] instanceof String)){//sem argumentos
                    target.apply(geralLogger, argumentsList);//argumentsList to parameter LIST
                }else{//se tiver apenas 1 argumento, forçar 2 argumentos pra ser interpretado corretamente pelo winston, é um BUG do próprio logger
                    let possivelErro = argumentsList[0];
                    target.apply(geralLogger, ['MSG: ', possivelErro]);
                }
            }
        }
        geralLogger.debug = new Proxy(geralLogger.debug, error_handler);
        geralLogger.info = new Proxy(geralLogger.info, error_handler);
        geralLogger.warn = new Proxy(geralLogger.warn, error_handler);
        geralLogger.error = new Proxy(geralLogger.error, error_handler);

I hope this helps someone.

@cjbarth
Copy link

cjbarth commented Oct 2, 2019

This is related to the discussion in #1338.

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