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

Created on 22 Feb 2018  ·  18Comments  ·  Source: winstonjs/winston

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.

Most helpful comment

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?

All 18 comments

+1

@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

%o

works like a charm, I didn't know winston used the same formatting params than util.format.

Thank you!

winston 3.1.0
I try this as write here:
const debugConsole = new winston.transports.Console({
level: 'debug',
format: winston.format.combine(winston.format.simple()),
handleExceptions: true
})
logger.add(debugConsole)

In code I use: logger.debug('%o', req.query)
I see json object, but I also see "%o" before, console log below:
debug: %o {"offset":"73000","count":"3","timestamp":"2018-10-29 15:02:08"}
what am I do worng ?

Generally %o is called by util.format() where you specify the object you want in there. From the output it looks like you don't even need %o because the object is being displayed.

Just use this instead, logger.debug(req.query) and it should work. Or you can store it in a variable with util.format like this
const queryFormatted = util.format('%o', req.query)
logger.debug(queryFormatted)

@frenzymind Or try the work around that was posted to the original issue by @mingchuno.

Just use this instead, logger.debug(req.query) and it should work

@eponymz In this case there is: debug: [object Object] {"timestamp":"2018-10-30 11:14:04"}

const queryFormatted = util.format('%o', req.query)

It is works, but noisy.

Is the output from the second what you were wanting? By that i mean, if you wanted the query in the logs, is it showing. If not try the workaround that was mentioned before that mingchuno posted.

Yes, the second way works as I want. I see json object data.
If I understand right, mingchuno adviced to use %o in string, becouse winston use util "under the hood". I try it and that works, but %o is printed too in my case. I also add splat() format to my debug level, but nothing is change. Am I miss something?

Yes, I'm seeing %o pre-pended to the object inspection. I suppose that's some kind of bug?

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

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?

So the fix is to append the %o to every logging statement that I want to print out an object?

Yes!

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 :D Just awful if we always had two use "%o"

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 :D 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?

Just for information, it's better to use
```javascript
typeof info.message === 'object'
````
instead of

```javascript
info.message.constructor === Object
````
It avoid errors when message is null or undefined and arrays will be displayed properly
(ex: [{hi: "456"}]

Was this page helpful?
0 / 5 - 0 ratings