winston@3 does not allow to mutate metadata

Created on 11 Nov 2017  路  2Comments  路  Source: winstonjs/winston

Before winston@3, the rewriter offered a possibility to mutate the metadata. @indexzero explained that the name comes from this possibility.

Mutating metadata is helpful for adding a request/correlation id to all logs of a given request without changing the logger statements.

I understand from the migration guide that rewriters are replaced by custom formats in winston@3.

We can write something like this:

import cls from 'cls-hooked';
import winston from 'winston';
import Koa from 'koa';
import Router from 'koa-router';
import uuid from 'uuid';

const addContext = winston.format.printf(info => {
  const ns = cls.getNamespace('foobar');
  const correlationId = ns.get('correlationId');
  info.message = `${correlationId ? `cor=${correlationId} ` : ''}${info.message}`;
  return info;
});

winston.configure({
  transports: [new winston.transports.Console()],
  format: winston.format.combine(
    addContext,
    winston.format.json(),
    ),
});

const app = new Koa();

const ns = cls.createNamespace('foobar');
app.use(async (ctx, next) => {
  await ns.runAndReturn(async () => {
    const correlationId = uuid.v4();
    cls.getNamespace('foobar').set('correlationId', correlationId);
    await next();
  });
});

const router = new Router();
app.use(router.routes());
router.get('/', async ctx => {
  winston.info('Hello World');
  ctx.body = 'Hello World';
});

app.listen(3000);

The log displayed in the console is:

{"message":"cor=cfec0c42-3890-4c44-b5f9-00a1df7ed529 Hello World","level":"info"}

Before winston@3, with a rewriter it was possible to mutate the metadata to obtain this:

{"message":"Hello World","level":"info", "correlation_id": "cfec0c42-3890-4c44-b5f9-00a1df7ed529"}

With winston@3, the only way to achieve this seems to wrap the winston module for the level methods (info(), ...) and to add the metadata in parameter of those methods. Am I right ?

Is it an intentional decision of the winston@3 design to remove the possibility to mutate the metadata ?

faq

Most helpful comment

+1 I was disappointed to see that this was removed and am considering downgrading to get that functionality back

All 2 comments

+1 I was disappointed to see that this was removed and am considering downgrading to get that functionality back

@ThierryAbalea @shmendo info objects are considered mutable in [email protected]. Another way to look at it is that we _combined formatters and rewriters into a single, new concept:_ formats.

To get the behavior you are seeking simply set it as a property on the info object in the format. Consider the classic credit card masking example that's been in the README.md of winston for ages, but upgraded to [email protected].

/*
 * Simple string mask. For example purposes only.
 */
function maskCardNumbers(num) {
  const str = num.toString();
  const { length } = str;

  return Array.from(str, (n, i) => {
    return i < length - 4 ? '*' : n;
  }).join('');
}

// Define the format
const maskFormat = winston.format(info => {
  // You can CHANGE existing property values
  if (info.creditCard) {
    info.creditCard = maskCardNumbers(info.creditCard);
  }

  // You can also ADD NEW properties if you wish
  info.hasCreditCard = !!info.creditCard;

  return info;
});

// Then combine the format with other formats and make a logger
const logger = winston.createLogger({
  format: winston.format.combine(
    //
    // Order is important here, the formats are called in the
    // order they are passed to combine.
    //
    maskFormat(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console()
  ]
});

logger.info('transaction ok', { creditCard: 123456789012345 });

Or in your code sample:

const addContext = winston.format.printf(info => {
  const ns = cls.getNamespace('foobar');
  const correlationId = ns.get('correlationId');

  // Do not mutate the message
  // info.message = `${correlationId ? `cor=${correlationId} ` : ''}${info.message}`;

  // Just MUTATE the info by adding a correlationId property if it exists
  if (correlationId) {
    info.correlationId = correlationId;
  }

  return info;
});

Thank you for opening this issue. Mutability of info within formats is a core concept for winston@3. To help make upgrading easier and less frightening for long time users we committed to not releasing 3.0.0 out of RC until the Upgrad Guide was complete.

In triaging this issue I was able to make a final draft of the upgrade guide in https://github.com/winstonjs/winston/pull/1278. Any additional upgrade feedback you have would be awesome!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  4Comments

anks333 picture anks333  路  3Comments

Buzut picture Buzut  路  3Comments

exortech picture exortech  路  3Comments

alditis picture alditis  路  3Comments