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

In 3.0.0 I cannot log objects without using JSON.stringify #1217

Closed
eyp opened this issue Feb 22, 2018 · 19 comments
Closed

In 3.0.0 I cannot log objects without using JSON.stringify #1217

eyp opened this issue Feb 22, 2018 · 19 comments

Comments

@eyp
Copy link

eyp commented Feb 22, 2018

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.

@gravitycode
Copy link

+1

@mingchuno
Copy link

mingchuno commented Mar 7, 2018

@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

@eyp
Copy link
Author

eyp commented Mar 9, 2018

%o

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

Thank you!

@eyp eyp closed this as completed Mar 9, 2018
@frenzymind
Copy link

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 ?

@eponymz
Copy link

eponymz commented Oct 30, 2018

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.

@eponymz
Copy link

eponymz commented Oct 30, 2018

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)

@eponymz
Copy link

eponymz commented Oct 30, 2018

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

@frenzymind
Copy link

frenzymind commented Oct 30, 2018

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.

@eponymz
Copy link

eponymz commented Oct 30, 2018

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.

@frenzymind
Copy link

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?

@ariestav
Copy link

ariestav commented Nov 5, 2018

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

@atripes
Copy link

atripes commented Nov 27, 2018

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

@cpury
Copy link

cpury commented Nov 29, 2018

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?

@jnystrom
Copy link

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

@apmcodes
Copy link

Yes!

@smyth64
Copy link

smyth64 commented Jun 30, 2019

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"

@vschoener
Copy link

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?

@tlgman
Copy link

tlgman commented Apr 26, 2020

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"}]

@Steen3S
Copy link

Steen3S commented Jan 22, 2023

winston-pretty will solve this issue in a robust and versatile way. It's a standalone program that takes winston json log as input and outputs human readable log lines. It also pretty prints json and errors.

npm install -g winston-pretty

npm run <your-project> | winston-pretty

https://www.npmjs.com/package/winston-pretty

full-disclosure: I'm the author of winston-pretty

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