winston: In 3.0.0 I cannot log objects without using JSON.stringify

I’m on version 3, but since I’ve upgraded the only way to log objects is by stringify first the object. But with errors is even worse because I cannot log the error at all, I need to use error.message or directly the console.

This is my configuration for the development environment:

`` const { createLogger, format, transports } = require(‘winston’); const { combine, timestamp, label, printf } = format;

const environment = process.env.NODE_ENV;
const timestampFormat = 'YYYY-MM-DD HH:mm:SS';

const loggerFormat = printf((info) => {
    return `[${info.label}] ${info.message}`;
});
logger = createLogger({
    format: combine(
        label({ label: 'immoliste' }),
        format.colorize({ all: true }),
        format.splat(),
        format.simple(),
        loggerFormat
    ),
    transports: [
        new transports.Console({
            level: 'debug',
            colorized: true
        })
    ]
});

Doing this:

logger.error('Error sending contact message:', JSON.stringify(err));

I got only:

[mylabel] Error sending contact message:

But is a pain in the ass having to stringify everything, and doind that for errors. What am I doing wrong?, because in previous versions it was straightforward.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 29
  • Comments: 19

Most upvoted comments

Seriously, this seems like a downgrade. With Winston 2, I could just replace all console.X with winston.X. Why suddenly the ugly format tags?

Couldn’t accept that I have tot use %o always and made this simple solution:

const prettyJson = format.printf(info => {
  if (info.message.constructor === Object) {
    info.message = JSON.stringify(info.message, null, 4)
  }
  return `${info.level}: ${info.message}`
})

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.colorize(),
    format.prettyPrint(),
    format.splat(),
    format.simple(),
    prettyJson,
  ),
  transports: [
    new transports.Console({})
  ],
})

So this logger…

  logger.info({ hi: 123 })

…transforms to this in the console

info: {
    "hi": 123
}

Hope I can help you guys 😄 Just awful if we always had two use “%o”

@eyp can you try this?

logger.error('Error sending contact message:%o', {foo: "bar"});

The underlying source is here:

https://github.com/winstonjs/logform/blob/master/splat.js

which you can see it use util.format from node

https://nodejs.org/api/util.html#util_util_format_format_args

so %o, %O and %j does the job

Yes!

Just for information, it’s better to use

typeof info.message === 'object'

instead of

info.message.constructor === Object

It avoid errors when message is null or undefined and arrays will be displayed properly (ex: [{hi: “456”}]

Is that a deliberate design choice? It deviates from the standard quite a bit (and took me a good hour to find) instead of

console.log('Log me plz: ', {'ok': 'logged'});

having to (winston 3.x) change all logging calls to

logger.info('Log me plz: %o', {'ok':'logged'});

Sorry, am I right? I am confused…

Couldn’t accept that I have tot use %o always and made this simple solution:

const prettyJson = format.printf(info => {
  if (info.message.constructor === Object) {
    info.message = JSON.stringify(info.message, null, 4)
  }
  return `${info.level}: ${info.message}`
})

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.colorize(),
    format.prettyPrint(),
    format.splat(),
    format.simple(),
    prettyJson,
  ),
  transports: [
    new transports.Console({})
  ],
})

So this logger…

  logger.info({ hi: 123 })

…transforms to this in the console

info: {
    "hi": 123
}

Hope I can help you guys 😄 Just awful if we always had two use “%o”

Nice one, but it’s weird, do I need to do it for all my logger level?