【问题标题】:Nodejs, Winston: Log entry getting duplicatedNodejs,Winston:日志条目重复
【发布时间】:2022-04-08 12:57:12
【问题描述】:

我正在使用 winston 保存日志,并将日志保存到文件中。

var winston = require('winston');
var moment = require('moment');
var logger = new (winston.Logger)({
transports: [
    new (winston.transports.File)({
        name: 'info-file',
        filename: 'console.log',
        timestamp : function() {return moment().utcOffset(330).format('DD-MM HH:mm'); },
        level: 'info'
    }),
    new (winston.transports.File)({
        name: 'debug-file',
        filename: 'console.log',
        timestamp : function() {return moment().utcOffset(330).format('DD-MM HH:mm'); },
        level: 'debug'
    }),
    new (winston.transports.File)({
        name: 'error-file',
        filename: 'console.log',
        timestamp : function() {return moment().utcOffset(330).format('DD-MM HH:mm'); },
        level: 'error'
    }),
    new (winston.transports.File)({
        name: 'unhandled-error-file',
        filename: 'console.log',
        timestamp : function() {return moment().utcOffset(330).format('DD-MM HH:mm'); },
        handleExceptions: true
    })
 ]
});

这是我正在运行的命令:

router.get('/exercise_excel_entry', function(req,res){
  logger.log('info', "info testing");
  logger.log('debug', "debug testing");
  logger.log('error', "error testing");
  res.render('exercise_excel_entry');
});

这是保存在文件中的输出:

{"level":"info","message":"info testing","timestamp":"04-02 11:51"}
{"level":"error","message":"error testing","timestamp":"04-02 11:51"}
{"level":"info","message":"info testing","timestamp":"04-02 11:51"}
{"level":"info","message":"info testing","timestamp":"04-02 11:51"}
{"level":"error","message":"error testing","timestamp":"04-02 11:51"}
{"level":"debug","message":"debug testing","timestamp":"04-02 11:51"}
{"level":"error","message":"error testing","timestamp":"04-02 11:51"}
{"level":"error","message":"error testing","timestamp":"04-02 11:51"}

我不明白为什么信息和错误标记的日志会重复

【问题讨论】:

    标签: node.js express winston


    【解决方案1】:

    根据温斯顿文档:

    winston 允许您在每个传输上定义一个级别属性,该属性 指定传输应记录的最大消息级别。

    这里的关键字是最大

    默认的日志记录级别是:

    { error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }
    

    所以在你的情况下:

    • info-file 将记录级别为 'info' 或更高级别的消息(错误 & 警告)。
    • debug-file 将记录级别为“调试”或更高级别的消息 (错误、警告、信息和详细)。
    • error-file 将记录消息 级别“错误”或更高(除未处理的异常之外的所有内容)。
    • unhandled-error-file 将记录级别为“未处理错误”的消息 仅限。

    并且您已将文件名 console.log 用于所有传输。

    所以日志的顺序如下:

    logger.log('info', "info testing");    // both info-file & debug-file transport logs it
    logger.log('debug', "debug testing");  // only debug-file transport logs it
    logger.log('error', "error testing");  // info-file, debug-file and error-file transports logs it
    

    这就解释了日志文件中infoerror 消息的多个条目。

    编辑

    不是最好的解决方案(因为这会为不记录的级别添加空行):

    new (winston.transports.File)({
        name: 'info-file',
        filename: 'console.log',
        timestamp : function() {return moment().utcOffset(330).format('DD-MM HH:mm'); },
        level: 'info',
        filters: [function (level, msg, meta) {
            return (level === 'info') ? msg : '';
        }],
        formatter: function(options) {
            return msg === '' ? '' : { level: options.level, timestamp: options.timestamp, message: options.message, meta: options.meta };
        }
    })
    

    【讨论】:

    • 哦...那么我怎样才能让消息仅发送该优先级的消息?
    • 目前我认为没有办法做到这一点。
    • 这东西只会让我的日志不必要地膨胀……所以没有办法在这些类别下获得单个日志条目?
    • 您可以使用filters & rewriterscustom log format 让每个传输仅在消息级别与传输器级别匹配时通过,否则只返回空白消息。
    • 我已经编辑了我的回复,为您提供了一个示例代码,说明如何为一次传输执行此操作。您可以为其他人重复它。但我必须说它可能会减慢您的记录器。
    【解决方案2】:

    如果您定义自己的自定义“格式”,则可以忽略特定类型的消息

    const {
      createLogger,
      format,
      transports
    } = require('winston');
    
    // Ignore log messages if they have specific log type
    const ignoreInfo = format((info, opts) => {
      if (info.level === 'info') {
        return false;
      }
      return info;
    });
    
    const logger = createLogger({
      format: format.combine(
        ignoreInfo(),
        format.json()
      ),
      transports: [new transports.Console()]
    });
    
    // Outputs: {"level":"error","message":"Public error to share"}
    logger.log({
      level: 'error',
      message: 'Public error to share'
    });
    
    // Messages with level info will not be written when logged.
    logger.log({
      level: 'info',
      message: 'This is super secret - hide it.'
    });
    

    【讨论】:

      猜你喜欢
      • 2019-06-15
      • 1970-01-01
      • 2015-01-18
      • 2021-04-26
      • 2013-08-31
      • 1970-01-01
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      相关资源
      最近更新 更多