【问题标题】:How to log request & transaction id in each log line using winston for Node JS?如何使用 Winston for Node JS 在每个日志行中记录请求和事务 ID?
【发布时间】:2015-09-14 05:43:28
【问题描述】:

我已经使用 Express 构建了一个 Node JS REST 服务。登陆此服务的每个请求都有像“X-org-ReqId”和“X-org-Tid”这样的标题,我需要登录在执行此请求期间写入的所有日志行。基本上,我需要在每个日志行中记录一些上下文信息,以帮助我通过多个服务进行事务/请求跟踪。

我正在使用这样初始化的winston logger:

var winston = require('winston');
var appLogger = new(winston.Logger)({
  transports: [
    new(winston.transports.Console)({
        level: 'info', //TODO: Should be changed to Error in prod
        colorize: true
    }),
    new(winston.transports.DailyRotateFile)({
        filename: '/var/log/org/my-service.log',
        datePattern: '.yyyy-MM-dd',
        tailable: true,
        // handleExceptions: true,
        json: true,
        logstash: true
    })
  ],
  exitOnError: false
});

appLogger.on('error', function(err) {
  console.error("Logger in error", err);
});

module.exports.logger = function() {
  return appLogger;
};

在我想使用它的各个类中,我喜欢这样:

var logger = require('../config/logger').logger();

myObject.on("error", function (err) {
                logger.error("Error connecting bucket=" + bucketId , err);
});

这将产生如下日志:

{"level":"info","message":"Error connecting bucket=2.....","timestamp":"2015-06-10T06:44:48.690Z"}

Winston 默认为该日志语句添加时间戳,但我也想记录 req.headers['X-org-ReqId'] 和 req.headers['X-org-Tid'] 之类的内容,以便我知道哪个交易失败,错误是什么。

我想要这样的日志:

{"level":"info","message":"Error connecting bucket=2....","timestamp":"2015-06-10T06:44:48.690Z", "tid":"a3e8b380-1caf-11e5-9a21-1697f925ec7b", "reqid":"aad28806-1caf-11e5-9a21-1697f925ec7b"}

在 java 世界中我们曾经有 NDC,在 Node JS 世界中是否有等价物?

【问题讨论】:

    标签: node.js logging express winston ndc


    【解决方案1】:

    我遇到了和你一样的问题。这可能不是最好的做事方式,因为您必须传播“req”对象,但它可以工作。

    我愿意得到任何改进:)

    首先我会在我的“log.js”中覆盖 winston 日志记录方法:

    // MyLogger definition
    function MyLogger() {
        this.__proto__.__proto__.constructor.apply(this, arguments);
    }
    
    // Inheritance
    MyLogger.prototype.__proto__ = winston.Logger.prototype;
    
    // Overwriting methods
    MyLogger.prototype.log = function() {
        var args = [];
        // Copying arguments not to modify them
        for (var i = 0; i < arguments.length; i++) {
            args[i] = arguments[i];
        }
    
        // Adding information in logs
        var lastArg = args[arguments.length - 1];
        if (typeof lastArg === 'object'
            && lastArg.headers) {
            args[arguments.length - 1] = {
                // Liste des infos ajoutées dans les logs
                requestId: lastArg.headers['x-request-id'] ? lastArg.headers['x-request-id'] : arguments[arguments.length - 1].id,
                host: arguments[arguments.length - 1].headers.host,
                pId: process.pid
            };
        }
    
        // Calling super
        this.__proto__.__proto__.log.apply(this, args);
    }
    
    MyLogger.prototype.error = function() {
        var args = ["error"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    MyLogger.prototype.warn = function() {
        var args = ["warn"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    MyLogger.prototype.info = function() {
        var args = ["info"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    MyLogger.prototype.verbose = function() {
        var args = ["verbose"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    MyLogger.prototype.debug = function() {
        var args = ["debug"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    MyLogger.prototype.silly = function() {
        var args = ["silly"];
        for (var i = 0; i < arguments.length; i++) {
            args[i + 1] = arguments[i];
        }
        this.__proto__.log.apply(this, args);
    }
    
    var logger = new MyLogger({
        transports: [
            new winston.transports.File({
                level: config.LOG_LEVEL,
                filename: config.LOG_FILE,
                handleExceptions: true,
                json: true,
                maxsize: 5242880, //5MB
                maxFiles: 5,
                colorize: false
            }),
            new winston.transports.Console({
                level: config.LOG_LEVEL,
                handleExceptions: true,
                json: false,
                colorize: true
            })
        ],
         exitOnError: false
    });
    
    module.exports                  = logger;
    

    然后在每个需要记录的模块中:

    var logger          = require("../log.js");
    
    ...
    
    logger.debug("My message", req);
    

    生成一个登录控制台和一个 JSON 登录日志文件,其中包含跟踪流所需的所有信息。

    我的下一步是不必传播“req”并从上下文或会话中获取所需的信息。

    希望有所帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 2017-07-14
      • 2018-06-20
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 2022-12-04
      相关资源
      最近更新 更多