Express.js在路由之外的每个请求的唯一var

时间:2021-08-23 02:33:05

In my express application I have a module called helpers thats is required in almost all my routes and modules. This module has a logger method that logs to fluentd (but that's unimportant). While building the data to log I'd like to add a unique identifier of the request, so that all the logs written for the same request have the same unique ID. Using a global var in the app entry point app.use doesn't work because this var would be overwritten every time a new request hits, so the global uuid will change would obviously change in case of high load or long running tasks. The res.locals is not available outside routing, so I can't use it for this matter. Is there a way to create a var that would be unique per request and available in every module or maybe a way to access the res.locals data outside routing? Thank you

在我的快速应用程序中,我有一个名为helpers的模块,几乎所有的路由和模块都需要这个模块。这个模块有一个记录器方法,可以记录流利(但这并不重要)。在构建要记录的数据时,我想添加请求的唯一标识符,以便为同一请求编写的所有日志具有相同的唯一ID。在应用程序入口点app.use中使用全局变量不起作用,因为每次新请求命中时都会覆盖此变量,因此在高负载或长时间运行的任务中,全局uuid将发生变化。 res.locals在路由之外是不可用的,所以我不能在这个问题上使用它。有没有办法创建一个var,每个请求都是唯一的,并且可以在每个模块中使用,或者可以在路由之外访问res.locals数据?谢谢

EDIT

编辑

Maybe an example will help understand better the question. Suppose I have a module called helpers.js like this:

也许一个例子将有助于更好地理解这个问题。假设我有一个名为helpers.js的模块,如下所示:

let helpers = {};
helpers.log = (logData, logName) => {
    fluentLogger.emit('', {
        name: logName,
        //uuid: the needed uuid,
        message: logData
    });
}
module.exports = helpers;

Now obviously I can do this in my app.js entry point:

现在很明显我可以在我的app.js入口点做到这一点:

app.use(function (req, res, next) {
    res.locals.uuid = uuid.v4();
    next();
});

and then in every loaded middleware module that requires helpers(adding a new param to the helpers.log method):

然后在每个需要帮助程序的加载中间件模块中(向helpers.log方法添加一个新的参数):

const helpers = require('helpers');
router.post('/', (req, res, next) => {
    helpers.log('my log message', 'myLogName', res.locals.uuid);
    next();
});

and this will normally work. But suppose a big or middle size project where there are hundreds of custom modules and models (not middlewares) and a module may require other modules that require other modules that require finally the helpers module. In this case I should pass the res.locals.uuid as a parameter to every method of every method so that I have it available in the logger method. Not a very good idea. Suppose I have a new module called dbmodel.js that is required in a middleware function:

这通常会奏效。但是假设一个大型或中型项目,其中有数百个自定义模块和模型(而不是中间件),并且模块可能需要其他模块,这些模块需要最终需要辅助模块的其他模块。在这种情况下,我应该将res.locals.uuid作为参数传递给每个方法的每个方法,以便我在logger方法中使用它。不是一个好主意。假设我在中间件函数中需要一个名为dbmodel.js的新模块:

const helpers = require('helpers');
let dbmodel = {};
dbmodel.getSomeData = (someParam) => {
    //some logic
    helpers.log('my log message', 'myLogName');
}
module.exports = dbmodel;

The dbmodel has no idea about the res.locals data if I don't pass it from the middleware, so the helpers.log method will also have no idea about this.

如果我没有从中间件传递resm.locals数据,dbmodel就不知道res.locals数据,所以helpers.log方法也不知道这个。

In PHP one would normally write a GLOBAL var in the application's entry point so a hypothetical logger function would have access to this global on every method request from whichever class of the application.

在PHP中,通常会在应用程序的入口点中编写一个GLOBAL var,因此假设的记录器函数可以在来自应用程序的任何类的每个方法请求*问此全局变量。

Hope this explanation will help :) Thank you

希望这个解释会有所帮助:)谢谢

EDIT 2

编辑2

The solution for this kind of problems is CLS. Thanks to @robertklep for the hint. A good slideshare explaining exactly the same problem (logger with unique ID) and explaining the CLS solutions can be found here: https://www.slideshare.net/isharabash/cls-and-asynclistener

这类问题的解决方案是CLS。感谢@robertklep提示。一个好的slidehare解释完全相同的问题(具有唯一ID的记录器)和解释CLS解决方案可以在这里找到:https://www.slideshare.net/isharabash/cls-and-asynclistener

2 个解决方案

#1


3  

I answered a very similar question here which will solve this problem. I used to solve the problem the libraries node-uuid and continuation-local-storage. Take a look to the answer of this question and see if it helps:

我在这里回答了一个非常类似的问题,它将解决这个问题。我曾经解决了library node-uuid和continuation-local-storage的问题。看看这个问题的答案,看看它是否有帮助:

NodeJS Express - Global Unique Request Id

NodeJS Express - 全球唯一请求ID

And you want a bigger explanation, take a look here:

你想要一个更大的解释,看看这里:

Express.js: Logging info with global unique request ID – Node.js

Express.js:使用全局唯一请求ID记录信息 - Node.js

#2


0  

Yes you can do so by one method .
Every request comes to his routes pass that request inside the middleware. Suppose you have

是的,您可以通过一种方法来实现。每个请求都到他的路由传递中间件内的请求。假设你有

app.get('/', function(req, res) {
    res.sendFile(path.join(public + "index.html"));
 });

a request.

一个要求。

Place Middleware in it .and edit req field coming , in this way you will get the unique variable values for each request

将中间件放入其中。并编辑req字段,这样您将获得每个请求的唯一变量值

check out this . https://expressjs.com/en/guide/writing-middleware.html

看看这个。 https://expressjs.com/en/guide/writing-middleware.html

Like this

喜欢这个

var requestTime = function (req, res, next) {
  req.requestTime = Date.now()
  next()
}

app.use(requestTime)

app.get('/', function (req, res) {
  var responseText = 'Hello World!<br>'
  responseText += '<small>Requested at: ' + req.requestTime + '</small>'
  res.send(responseText)
})

Here req.requestTime is unique for each request.

这里req.requestTime对于每个请求都是唯一的。

#1


3  

I answered a very similar question here which will solve this problem. I used to solve the problem the libraries node-uuid and continuation-local-storage. Take a look to the answer of this question and see if it helps:

我在这里回答了一个非常类似的问题,它将解决这个问题。我曾经解决了library node-uuid和continuation-local-storage的问题。看看这个问题的答案,看看它是否有帮助:

NodeJS Express - Global Unique Request Id

NodeJS Express - 全球唯一请求ID

And you want a bigger explanation, take a look here:

你想要一个更大的解释,看看这里:

Express.js: Logging info with global unique request ID – Node.js

Express.js:使用全局唯一请求ID记录信息 - Node.js

#2


0  

Yes you can do so by one method .
Every request comes to his routes pass that request inside the middleware. Suppose you have

是的,您可以通过一种方法来实现。每个请求都到他的路由传递中间件内的请求。假设你有

app.get('/', function(req, res) {
    res.sendFile(path.join(public + "index.html"));
 });

a request.

一个要求。

Place Middleware in it .and edit req field coming , in this way you will get the unique variable values for each request

将中间件放入其中。并编辑req字段,这样您将获得每个请求的唯一变量值

check out this . https://expressjs.com/en/guide/writing-middleware.html

看看这个。 https://expressjs.com/en/guide/writing-middleware.html

Like this

喜欢这个

var requestTime = function (req, res, next) {
  req.requestTime = Date.now()
  next()
}

app.use(requestTime)

app.get('/', function (req, res) {
  var responseText = 'Hello World!<br>'
  responseText += '<small>Requested at: ' + req.requestTime + '</small>'
  res.send(responseText)
})

Here req.requestTime is unique for each request.

这里req.requestTime对于每个请求都是唯一的。