Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Winston logging object

Tags:

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

like image 350
coinhndp Avatar asked May 11 '19 13:05

coinhndp


2 Answers

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

like image 162
Pierre C. Avatar answered Sep 18 '22 06:09

Pierre C.


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); 
like image 45
Anton Pastukhov Avatar answered Sep 21 '22 06:09

Anton Pastukhov