Winston / Morgan logging avoiding duplicate entrie

2020-02-14 07:24发布

I just implemented Winston Logging and it works as expected but i came accross a few issues which i cant find answer for.

The way winston works as far as i can tell, the set log level and anything below as far as priority gets used, like on error it will also include info logs etc. Is there a way to create a specific log level lets call it HTTP or db where i only log http or db events to and they don't end up in the combined file or console ?

2条回答
做自己的国王
2楼-- · 2020-02-14 08:07

A better solution is to use a single logger with a format function as a "level filter" to specify which transport logs which specific level. Here is the solution (note, levelFilter could easily be extended to take an array of acceptable levels).

The key insight is that if no info object is returned from the formatter chain, nothing gets logged.

const { createLogger, format, transports } = require('winston');

const levelFilter = (level) =>
  format((info, opts) => {
     if (info.level != level) { return false; }
      return info;
  })();

const logger = createLogger({
  transports: [
    new transports.Console({
        format: format.combine(
          levelFilter("info"),
          format.json()
        )
    }),
    new transports.File({
        filename: "test.log",
        format: format.combine(
          levelFilter("error"),
          format.json()
        )
    }),
  ]
});

// ONLY is logged to test.log
logger.log({
  level: 'error',
  message: 'abcd'
});

// ONLY is logged to console
logger.log({
  level: 'info',
  message: '1234'
});
查看更多
混吃等死
3楼-- · 2020-02-14 08:25

I can init a winston with a parameter, in your case filename. I use similar setup for logging separated cron tasks (I use type parameter instead filename, which is used as a prefix in log, so I can identify problems in multiple cron tasks in one log file). I hope you are familiar with ES6 syntax.

utils/winston.js

const { createLogger, transports } = require('winston');

const infoLogger = filename => createLogger({
    transports: [
        new transports.File({
            filename: 'info-' + filename,
            level: 'info'
        }),
        new transports.Console(),
    ],
        exitOnError: false
    });

const errorLogger = filename => createLogger({
    transports: [
        new transports.File({
            filename: 'error-' + filename,
            level: 'error'
        }),
        new transports.Console(),
    ],
        exitOnError: false
    });

export default filename => ({
    errorLogger: errorLogger(filename).error,
    infoLogger: infoLogger(filename).info
});

So in a your code you can import custom winston setup from utils and initialize it with a filename. Be careful, I basically export only error function from winston errorLogger(filename).error, You can modify it in way acceptable for you

main.js

import logger from './utils/winston';
const { errorLogger, infoLogger } = logger('http.log');
errorLogger('some http fail'); // destination file => error-http.log
infoLogger('some http info'); // destination file => info-http.log
查看更多
登录 后发表回答