How to identify request (by ID) through middleware

2019-02-09 08:07发布

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条回答
该账号已被封号
2楼-- · 2019-02-09 08:24

You can use req object that does comes with every request in express.
So the first route you would do in your application would be:

var logIdIterator = 0;

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

And then anywhere within express, you can access that id in req object: req.log.id;
You will still need to pass some data into functions that do want to create some logs. In fact you might have logging function within req.log object, so that way it will be guaranteed that logging will happen only when there is access to req.log object.

查看更多
乱世女痞
3楼-- · 2019-02-09 08:29

If you auto-increment, your later log analytics won't be able to uniquely identify requests, because different instances will generate colliding IDs, and restarting the app will automatically cause ID collisions.

Here's another possible solution.

Install cuid:

npm install --save cuid

Then in your main app file:

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);

Now you'll get a friendly request ID that is unlikely to collide, and you'll be able to uniquely identify your requests for your log analytics and debugging, even across multiple instances, and server restarts.

查看更多
Melony?
4楼-- · 2019-02-09 08:29

I was struggling search for a solution for this problem. The thing I didn't like it about solutions suggested here was that they imply to share the req object among all the functions along the project. I found out a solution mixing your approach (creating an uuid per request) and with a library (continuation-local-storage) that allows sharing namespaces among modules.

You can find the explanation in this other answer: https://stackoverflow.com/a/47261545/5710581

If you want more info, I wrote down all these ideas and all the code in a post, in order to explain everything in one place: Express.js: Logging info with global unique request ID – Node.js

查看更多
你好瞎i
5楼-- · 2019-02-09 08:41

You shouldn't be using Global Variables.

What I like to do is to populate a META object before each request.

I use a UUID generator (https://github.com/kelektiv/node-uuid) to ID a request

Here's an example

  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();
  })
查看更多
登录 后发表回答