9

I am developping a RESTful server in node.js, using Express as framework, and Winston, for the moment, as logger module. This server will handle a big amount of simultaneous request, and it would be very useful to me to be able to track the log entries for each specific request, using something like a 'request ID'. The straight solution is just to add this ID as another piece of logging information each time I want to make a log entry, but it will mean to pass the 'request ID' to each method used by the server.

I would like to know if there is any node.js/javascript module or technique that would allow me to do this in an easier way, without carrying around the request ID for each specific request.

4

5 回答 5

17

如果你自增,你以后的日志分析将无法唯一识别请求,因为不同的实例会产生冲突的 ID,重启应用会自动导致 ID 冲突。

这是另一种可能的解决方案。

安装cuid:

npm install --save cuid

然后在您的主应用程序文件中:

var cuid = require('cuid');
var requestId = function requestId(req, res, next) {
  req.requestId = cuid();
  next();
};

// Then, at the top of your middleware:
app.use(requestId);

现在,您将获得一个不太可能发生冲突的友好请求 ID,并且您将能够唯一标识您的日志分析和调试请求,即使跨多个实例和服务器重新启动也是如此。

于 2013-09-22T22:14:57.640 回答
4

您可以使用reqexpress 中每个请求都附带的对象。
因此,您在应用程序中执行的第一条路线是:

var logIdIterator = 0;

app.all('*', function(req, res, next) {
  req.log = {
    id: ++logIdIterator
  }
  return next();
});

然后在 express 中的任何位置,您都可以idreqobject:req.log.id中访问它:
您仍然需要将一些数据传递给确实想要创建一些日志的函数。实际上,您可能在req.log对象中具有日志记录功能,因此可以保证只有在可以访问req.log对象时才会发生日志记录。

于 2013-07-17T15:09:04.287 回答
3

我一直在努力寻找解决这个问题的方法。我不喜欢这里建议的解决方案的一点是,它们暗示在项目中的所有函数之间共享 req 对象。我发现了一个混合您的方法(为每个请求创建一个 uuid)和一个允许在模块之间共享命名空间的库(continuation-local-storage)的解决方案。

您可以在其他答案中找到解释:https ://stackoverflow.com/a/47261545/5710581

如果您想了解更多信息,我在一篇文章中写下了所有这些想法和所有代码,以便在一个地方解释所有内容: Express.js:使用全局唯一请求 ID 记录信息 – Node.js

于 2017-11-17T09:32:57.770 回答
0

您不应该使用全局变量。

我喜欢做的是在每个请求之前填充一个 META 对象。

我使用 UUID 生成器 ( https://github.com/kelektiv/node-uuid ) 来识别请求

这是一个例子

  app.all('*', function(req, res, next) {
    req.meta = {
      ip: req.headers['x-forwarded-for'] || req.connection.remoteAddress,
      timestamp: uuid(),
      user_agent: req.headers['user-agent'],
      body: req.body,
    }
    return next();
  })
于 2017-02-08T10:16:33.267 回答
0

正如@moka 所说,在每个请求中使用请求 ID 是解决问题的关键。抽象所有这些的另一种方法是使用http-contextuuid

因此,在所有中间件之前在 httpContext 中设置一个 UUID(设置为应用程序中间件而不是路由器中间件)。现在您可以在代码中的任何位置获取 uuid 并记录它。

这是我使用的示例实现

您可以在此处获取完整的参考uuid in request

const uuid = require('node-uuid');
const httpContext = require('express-http-context');
....
 this.expressApp.use(httpContext.middleware);
        this.expressApp.use((req, res, next) => {
            httpContext.set('reqId', uuid.v4());
            next();
        });

现在我在我的自定义 pino 记录器中使用了这里设置的 reqId

public infoLogService (fileName): pino.Logger {
        return pino({
            level: 'info',
            name: this.appService.getApp_name(),    

            messageKey: 'XXX-Logs',
            base: {pid: process.pid, hostname: os.hostname,
                timestamp: this.getTimeStamp(),
                appName: this.appService.getApp_name(),
                fileName: fileName,
                request_id: **isNullOrUndefined(httpContext.get('reqId'))** ? 'Not an actual request ' : httpContext.get('reqId')
            },
            enabled: true,
            useLevelLabels: true,


        });
    }

如果 reqId 为 null,则表示记录器已插入到启动 express 应用程序之前使用的代码中。希望您可以将其用作替代解决方案

于 2019-08-19T08:35:47.053 回答