Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to produce the same output with splat using winstonjs 3.2+

I've been postponing upgrading winstonjs from 3.1.0 to 3.2.x, because I can't manage to get it to handle the extra meta data the same way.

For example, I have log messages throughout the app that include meta data in strings and object form. In 3.1.0 this setup works well to create the output I'm looking for:

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, label, printf, colorize } = format;

const formatStr = printf(info => {
  return `[${info.timestamp}] ${info.level}\t ${info.label} ${info.message} ${JSON.stringify(info.meta)}`
});

let logger = createLogger({
  transports: [new transports.Console({ level: 'info' })],
  format: combine(
    colorize({message: true, level: true}),
    timestamp({format: 'MMM D, YYYY HH:mm'}),
    format.splat(),
    formatStr
  )
});

logger.info('any message',{extra: true});
logger.info('simple', "one", "two",{extra: true});

Where the output is like this:

[Jan 3, 2020 14:36] info     undefined any message {"extra":true}
[Jan 3, 2020 14:36] info     undefined simple ["one","two",{"extra":true}]

But in 3.2.1 the closest I can get to my ideal log format is:

[Jan 3, 2020 14:31] info     undefined any message {"extra":true,"timestamp":"Jan 3, 2020 14:31"}
[Jan 3, 2020 14:31] info     undefined simple {"0":"t","1":"w","2":"o","timestamp":"Jan 3, 2020 14:31","extra":true}

using the following code:

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, label, printf, colorize } = format;

// helper for stringifying all remaining properties
function rest(info) {
  return JSON.stringify(Object.assign({}, info, {
    level: undefined,
    message: undefined,
    splat: undefined,
    label: undefined
  }));
}

const formatStr = printf(info => {
  return `[${info.timestamp}] ${info.level}\t ${info.label} ${info.message} ${rest(info)}`
});

let logger = createLogger({
  transports: [new transports.Console({ level: 'info' })],
  format: combine(
    colorize({message: true, level: true}),
    timestamp({format: 'MMM D, YYYY HH:mm'}),
    format.splat(),
    formatStr
  )
});

logger.info('any message',{extra: true});
logger.info('simple', "one", "two",{extra: true});

With the removal of meta data in 3.2.0, https://github.com/winstonjs/winston/blob/master/CHANGELOG.md#new-splat-behavior, how am I suppose to make use of this with the existing logging structure that I have everywhere in my app?

like image 886
GrandVizier Avatar asked Nov 29 '25 20:11

GrandVizier


1 Answers

I've encountered a similar issue. I'm using winston 3.2.1.

I found a solution by not using the splat format and retrieving it from the metadata. Here is an example of how to get the output you're looking for.

const formatMeta = (meta) => {
  // You can format the splat yourself
  const splat = meta[Symbol.for('splat')];
  if (splat && splat.length) {
    return splat.length === 1 ? JSON.stringify(splat[0]) : JSON.stringify(splat);
  }
  return '';
};

const customFormat = winston.format.printf(({
  timestamp,
  level,
  message,
  label = '',
  ...meta
}) => `[${timestamp}] ${level}\t ${label} ${message} ${formatMeta(meta)}`);

const logger = createLogger({
  transports: [new transports.Console()],
  format: combine(
    format.colorize(),
    format.timestamp({format: 'MMM D, YYYY HH:mm'}),
    customFormat,
    // Do not use splat format
  )
});

logger.info('any message', { extra: true });
logger.info('simple', "one", "two", { extra: true });

The output:

[Mar 26, 2020 13:03] info     any message {"extra":true}
[Mar 26, 2020 13:03] info     simple ["one","two",{"extra":true}]
like image 142
Auxane Thouary Avatar answered Dec 01 '25 12:12

Auxane Thouary