winstonjs / winston

A logger for just about everything.
http://github.com/winstonjs/winston
MIT License
22.78k stars 1.81k forks source link

String interpolation causes inconsistent behaviour #1201

Open mrt123 opened 6 years ago

mrt123 commented 6 years ago

This api uses string interpolation: logger.log('info', 'test message %s', 'my string'); // info: test message my string

And this uses meta data: logger.info(`npm version patch -m "Upgrade to %s"`, {status: 'OK'}) // info: npm version patch -m "Upgrade to [object Object]"

Both rely on value of the 2nd argument. In 2nd case we are using metadata feature to pass status = OK, as well as we are using npm's interpolation for making a new git commit with new upgraded version.

There is no conflict between npm's interpolation and winston... however 2nd argument to info() will be treated as string to interpolate and metadata will receive empty object. This is a very inconsistent behaviour, especially if you are using your own custom formatter relying on metadata.

Is there a way to bypass this besides sanitising strings before calling log methods?

Disabling string interpolation would be a half measure, ideally api should be more cohesive so that this problem would be avoided all together.

subashthirumaran commented 6 years ago

I am also facing a similar issue. Any suggestions for this?

indexzero commented 6 years ago

@mrt123 this is not a winston bug, but I am going to leave it open so that we can better document how splats work within winston.

Under the covers the splat format from logform uses the core util.format method in Node.js. This method is behaving as expected for %s:

node -pe 'util.format(`npm version patch -m "Upgrade to %s"`, {status: "OK"})'
npm version patch -m "Upgrade to [object Object]"

What you want to use is %j:

node -pe 'util.format(`npm version patch -m "Upgrade to %j"`, {status: "OK"})'
npm version patch -m "Upgrade to {"status":"OK"}"

See the util.format docs for more details. I have confirmed this with this example:

const { createLogger, format, transports } = winston;

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

logger.info(`npm version patch -m "Upgrade to %j"`, { status: 'OK' })