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: 'daniel.duuch@greatmail.com',
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 daniel.duuch@greatmail.com
Logfile output (prettified by hand, see comment in the transport file format):
{
message: 'Register Daniel Duuch with email daniel.duuch@greatmail.com',
level: 'debug',
timestamp: '2019-05-11 17:05:45',
label: 'index.js',
metadata: {
name: 'Daniel Duuch',
email: 'daniel.duuch@greatmail.com',
password: 'myGreatPassword',
action: 'register'
}
}
Hope this solves your issue.
Important note: as noted by @Xetera in the comments, "you should make sure you're not actually logging people's passwords anywhere"