在node.js中按ID跟踪请求流

时间:2016-12-29 11:55:56

标签: node.js asynchronous logging promise mdc

在我的node.js应用程序中,每当我收到请求时,我都希望"盖章"它具有一些唯一的ID,并能够通过此ID跟踪与此请求相关的所有活动(日志语句)。因此,当请求进入并且我将其传递给较低的应用程序层(服务,数据库调用等)时,我希望能够收集与给定请求ID匹配的所有日志,以便通过应用程序重建其旅程。

所以有了这张图片,我现在使用request-local模块,但它确实有一些重要的魔法让我失败了(来自多个请求的日志获得相同的ID)。

代码主要基于Promises(不是普通的旧节点回调),我使用更高阶函数来为我的实际函数提供依赖(在启动期间构建应用程序树)。

首先,非常明显的解决方案是将此请求ID传递给每个被调用的函数,但这是一场灾难,我不会这样做。

你如何(可靠地)进行这种请求跟踪,而没有明确地将这个id / context作为额外参数传递给所有级别的函数?

2 个答案:

答案 0 :(得分:3)

<强> EDITED

这个库完成这项工作。它是Winston库的包装,所以它以相同的方式配置,它为每个请求生成一个唯一的ID,并用每个日志打印它

https://github.com/davicente/express-logger-unique-req-id

===============

我提出了一种方法,其中id将根据请求是唯一的,并且您不需要在不同的调用和模块之间传递任何对象(req,id ...)。 它意味着使用一个库来创建唯一ID,我选择了node-uuid,另一个库在不同模块之间共享上下文变量(continuation-local-storage),但是按请求使用命名空间,以便保留所有的id电话(即使是异步电话)。 此外,我包装了Winston库,以便在每个日志中打印请求ID。有了这个,您将能够跟踪一个请求的所有日志。

我在这里用代码示例https://solidgeargroup.com/express-logging-global-unique-request-identificator-nodejs

写了一个完整的解释

答案 1 :(得分:0)

我相信你正在寻找的是一个逻辑流程id,它应该是唯一的,并且会在你的后端发出的每个新请求中生成。如果这个假设是正确的,我通常做的是在我的快速路由器上创建一个中间件来生成一个新的随机流ID(带randomstring)。为了确保此流ID是唯一的,我将时间戳添加到该ID。为了将此流ID传递给下一个中间件,我们应该将它存储在res.locals(here the documentation )下 您的中间件可能如下所示:

//middleware flow.js
var random = require('randomstring');

var generate = function(){
    var dt = new Date();
    return random.generate() + dt.toISOString();
}
module.exports.createID = function(req, res, next){
    //store flowid in res - this hold state over the request life time
    res.locals.flowid = generate();
    next();
}

现在我们可以使用以下方法在应用上注入此中间件:

var flowcontrol = require('flow.js');
var middleware = require('middleware.js');

app.use(flowcontrol.createID);

//route example
app.get('/api/awesomeresource', middlewares.first, middlewares.second);

使用这种方法,您将能够在每个中间件上记录相同的流ID:

//middleware.js
module.exports.first = function(req, res, next){
   console.log(res.locals.flowid + " - First i did this...");
   //your logic here
   next();
}
module.exports.second = function(req, res, next){
   console.log(res.locals.flowid + " - Second i did this...");
   //your logic here before the response
   res.sendStatus(200);
}

结果 GET /api/awesomeresource HTTP/1.1 将是以下控制台日志:

> R90A56nEmZWYK73NOEVbWv2RS6DolO4D2017-12-07T10:29:39.291Z - First i did
> this... 
> R90A56nEmZWYK73NOEVbWv2RS6DolO4D2017-12-07T10:29:39.291Z -
> Second i did this...

这意味着您可以通过此戳记跟踪某种日志文件,并在需要时调试后端逻辑。

干杯