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.
+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"}]
Most helpful comment
Seriously, this seems like a downgrade. With Winston 2, I could just replace all
console.X
withwinston.X
. Why suddenly the ugly format tags?