如何使用 winston for Node JS 在每个日志行中记录请求和事务 ID?

Thi*_*oyd 6 logging ndc node.js express winston

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

我正在使用像这样初始化的 winston 记录器:

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;
};
Run Code Online (Sandbox Code Playgroud)

在我想使用它的个别课程中,我喜欢这样:

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

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

这将产生这样的日志:

{"level":"info","message":"Error connecting bucket=2.....","timestamp":"2015-06-10T06:44:48.690Z"}
Run Code Online (Sandbox Code Playgroud)

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"}
Run Code Online (Sandbox Code Playgroud)

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

小智 0

我遇到了和你一样的问题。这可能不是最好的处理方式,因为您必须传播“req”对象,但它确实有效。

\n\n

我愿意得到任何改进:)

\n\n

首先,我在“log.js”中覆盖温斯顿日志记录方法:

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

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

\n\n
var logger          = require("../log.js");\n\n...\n\nlogger.debug("My message", req);\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n

希望有帮助:)

\n