I use Winston for my backend logging I cannot log the object without using JSON.stringify
which is annoying
logger.debug(`Register ${JSON.stringify(req.body)}`)
const logger: Logger = createLogger({ // change level if in dev environment versus production level: env === 'production' ? 'info' : 'debug', format: format.combine( format.label({label: path.basename(process.mainModule.filename)}), format.timestamp({format: 'YYYY-MM-DD HH:mm:ss'}), format.prettyPrint() ), transports: [ new transports.Console({ format: format.combine(format.colorize(), logFormat), }), new transports.File({ filename, format: format.combine(format.json()), }), ], exitOnError: false, })
Could you show me the way to log object with Winston. I am using version 3.2.1
You are trying to insert a JSON object directly into the string, so it will print [Object Object]
without the JSON.stringify
.
This is not fixable by configuring Winston, as this problem happens while the string is generated (before the logger.debug
function actually reads it), so a console.log
call would print the same thing.
The first parameter of the logger.*
functions is the message (string), then you can pass a metadata object (JSON).
To use the metadata in your logFormat
function, update your Logger instantiation as follow:
const winston = require('winston') const { format, transports } = winston const path = require('path') const logFormat = format.printf(info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`) const logger = winston.createLogger({ level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', format: format.combine( format.label({ label: path.basename(process.mainModule.filename) }), format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // Format the metadata object format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }) ), transports: [ new transports.Console({ format: format.combine( format.colorize(), logFormat ) }), new transports.File({ filename: 'logs/combined.log', format: format.combine( // Render in one line in your log file. // If you use prettyPrint() here it will be really // difficult to exploit your logs files afterwards. format.json() ) }) ], exitOnError: false })
Usage:
const req = { body: { name: 'Daniel Duuch', email: '[email protected]', password: 'myGreatPassword' } } logger.debug(`Register ${req.body.name} with email ${req.body.email}`, { ...req.body, action: 'register' })
Console output:
2019-05-11 17:05:45 debug [index.js]: Register Daniel Duuch with email [email protected]
Logfile output (prettified by hand, see comment in the transport file format):
{ message: 'Register Daniel Duuch with email [email protected]', level: 'debug', timestamp: '2019-05-11 17:05:45', label: 'index.js', metadata: { name: 'Daniel Duuch', email: '[email protected]', password: 'myGreatPassword', action: 'register' } }
Hope this solves your issue.
Code for this answer
You can use format.splat()
in your logger config:
const logger = createLogger({ format: combine( ... format.splat(), // <-- ... ), ... });
...and log object using string interpolation:
let myObj = { /* ... */ }; logger.info('This message will include a complete object: %O', myObj);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With