Winston 日志级别过滤器

Winston log level filter

我正在尝试使用多种传输方式。我还希望能够在传输上仅记录一个或多个特定级别,其中 Winston 从给定级别和所有更严重的级别记录,因此默认情况下我不能像我想的那样有选择性.

我目前有 3 个运输工具。一个将所有内容记录到控制台,一个将所有内容记录到文件,第三个我只想将级别 HTTP_SEND 和 HTTP_RECV 记录到另一个文件。

这是我遇到问题的第三个。当我断点函数 levelFilter 时,我从未看到 info.level != 'info'.

我做错了什么?注意我的代码很大程度上基于 .

的答案
const winston = require('winston');

// Custom logging levels. We use all of those from https://datatracker.ietf.org/doc/html/rfc5424, although we change the values.
// We also add some custom levels of our own, which are commented with "".
const logLevels = {
    none: 0,                    // no error logging - don't log with this, set it in process.env.LOG_LEVEL to turn off logging
                                // Could also be achieved by silent=true in winston.createLogger, from process.env, but this is simplest
    emergency : 1,              // system is unusable
    alert: 2,                   // action must be taken immediately
    critical: 3,                // critical conditions
    unhandledException: 4,      // unhandled exception
    error: 5,                   // error conditions
    coding_bug: 6,              // hard bug. E.g switch stemante hits default, etc
    warning: 7,                 // warning conditions
    notice: 8,                  // normal but significant condition
    info: 9,                    // informational messages
    debug: 10,                  // debug-level messages
    HTTP_SEND: 11,              // HTTP request sent
    HTTP_RECV: 12,              // HTTP request sent
    called: 13,                 // function called
    returns: 14,                // function returns
    log_everything: 15,         // always the lowest level, so that we can log everything
  };

  const options = {
    everythingToDailyLogFile: {
      level: process.env.LOG_LEVEL || 'log_everything',
      filename: `./logs/everything.log`,
      handleExceptions: true,
      json: true,
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      colorize: false,
    },
    httpActivityToLogFile: {
      level: process.env.LOG_LEVEL || 'log_everything',
      filename: `./logs/http_activity.log`,
      handleExceptions: true,
      json: true,
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      colorize: false,
    },
    everythingToConsole: {
      level: process.env.LOG_LEVEL || 'log_everything',
      handleExceptions: true,
      json: false,
      colorize: true,
    },
  };  

  const myFormat = winston.format.printf( ({ level, message, timestamp , ...metadata}) => {
    let formattedMessage = `${timestamp} [${level}] : ${message} `  
    if(metadata) {
    formattedMessage += JSON.stringify(metadata)
    }
    return formattedMessage
  });  

  const levelFilter = (levelToFilterOn) =>
  winston.format((info, _options) => {
      // If no info object is returned from the formatter chain, nothing gets logged
      if (toString.call(info.level) === "[object Array]")
      {
        if (info.level.includes(levelToFilterOn)) { return info; }
        return false;
      }
      
      if (info.level != levelToFilterOn) { return false; }
        return info;
})(); 

module.exports = winston.createLogger({
  levels: logLevels,
  transports: [
      new winston.transports.Console({
          format: winston.format.combine(
            levelFilter(process.env.LOG_LEVEL || 'log_everything'),
            winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), 
            myFormat
          )
      }),
      new winston.transports.File({
        filename: "./logs/bet_squad.log",
        format: winston.format.combine(
          levelFilter(process.env.LOG_LEVEL || 'log_everything'),
          winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), 
          myFormat
      )
    }),
    new winston.transports.File({
      filename: "./logs/http_activity.log",
      format: winston.format.combine(
        levelFilter(process.env.LOG_LEVEL || ['HTTP_SEND', 'HTTP_RECV']),
        winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), 
        myFormat
      )
    }),
  ]
});

我试过你的代码并设法使第三次传输工作。你的问题不清楚,你是什么意思:

I never see info.level != 'info'.

无论如何,如果您希望第三种传输工作,您必须配置一个与您在代码中定义的信息级别相匹配的环境变量

如果您希望您的信息级别为 info,您必须定义一个环境变量,因为您定义了传递给 levelFilter 函数的参数。
levelFilter(process.env.LOG_LEVEL || ['HTTP_SEND', 'HTTP_RECV']),
为了使用那个 process.env.LOG_LEVEL,你需要使用 dotenv package 允许你从 .env 文件加载环境变量。

继续并安装该软件包:

npm install dotenv

在项目的根目录下创建一个 .env 文件并用以下代码填充它:

LOG_LEVEL=info

在您的 winston 导入后添加此行:

const winston = require('winston');
const dotenv= require('dotenv').config();

感谢 dotenv 包,您在 .env 文件中定义的环境变量被填充到 process.env 对象中。
现在,如果您尝试 logger.log('info', 'test message %s', 'my string');,您应该能够看到出现的日志以及填充的 http_activity.log 文件。