How do I change my node winston JSON output to be single line

zayquan picture zayquan · Aug 21, 2015 · Viewed 25k times · Source

When I create a nodejs winston console logger and set json:true, it always output JSON logs in multiline format. If I pipe these to a file and try to grep that file, my grep hits only include part of the log line. I want winston to output my log lines in JSON format, but not to pretty print the JSON

Here is my config (coffeescript, apologies):

winston = require 'winston'
logger = new (winston.Logger)(
  transports: [
    new winston.transports.Console({
     json: true
    })
  ]
)

And some sample output:

{
  "name": "User4",
  "level": "info",
  "message": "multi line whyyyyy"
}

Answer

jmarceli picture jmarceli · Jul 20, 2017

winston 3.x (current version)

Default formatter

const winston = require('winston');
const logger = winston.createLogger({
  format: winston.format.json(),
  transports: [
    new winston.transports.Console()
  ]
});

Example

const test = { t: 'test', array: [1, 2, 3] };
logger.info('your message', test);
// logger output:
// {"t":"test","array":[1,2,3],"level":"info","message":"your message"}

Custom formatter

const winston = require('winston');

const { splat, combine, timestamp, printf } = winston.format;

// meta param is ensured by splat()
const myFormat = printf(({ timestamp, level, message, meta }) => {
  return `${timestamp};${level};${message};${meta? JSON.stringify(meta) : ''}`;
});

const logger = winston.createLogger({
  format: combine(
    timestamp(),
    splat(),
    myFormat
  ),
  transports: [
    new winston.transports.Console()
  ]
});

Example:

const test = { t: 'test', array: [1, 2, 3] };
// NOTE: wrapping object name in `{...}` ensures that JSON.stringify will never 
// return an empty string e.g. if `test = 0` you won't get any info if 
// you pass `test` instead of `{ test }` to the logger.info(...)
logger.info('your message', { test });
// logger output:
// 2018-09-18T20:21:10.899Z;info;your message;{"test": {"t":"test","array":[1,2,3]}}

winston 2.x (legacy version)

It seems that the accepted answer is outdated. Here is how to do this for current winston version (2.3.1):

var winston = require('winston');
var logger = new (winston.Logger)({
  transports: [
    new (winston.transports.Console)({
     json: true,
     stringify: (obj) => JSON.stringify(obj),
    })
  ]
})

Note the parenthesis around winston.transports.Console.