NodeJS Express - 全球唯一请求标识
我们在几个项目同样的问题,我不能为FINDE这个问题的任何完整的解决方案。我们使用相同的技术(Node.js,Express.js和Winston的日志) 我找到了一个解决方案,它使用了一对库并包装了Winston库: - node-uuid用于为每个请求创建唯一标识符 - 继续本地存储,用于在不同模块之间共享此ID,而无需在所有呼叫中发送req对象。
首先我需要创建并设置每个请求的唯一标识符。我这样做是在中间件:
var uuid = require('node-uuid');
var createNamespace = require('continuation-local-storage').createNamespace;
var myRequest = createNamespace('my request');
// Run the context for each request. Assign a unique identifier to each request
app.use(function(req, res, next) {
myRequest.run(function() {
myRequest.set('reqId', uuid.v1());
next();
});
});
之后,我不得不换温斯顿库,恢复从上下文ID和添加到日志的消息:
var winston = require('winston');
var getNamespace = require('continuation-local-storage').getNamespace;
// Wrap Winston logger to print reqId in each log
var formatMessage = function(message) {
var myRequest = getNamespace('my request');
message = myRequest && myRequest.get('reqId') ? message + " reqId: " + myRequest.get('reqId') : message;
return message;
};
var logger = {
log: function(level, message) {
winstonLogger.log(level, formatMessage(message));
},
error: function(message) {
winstonLogger.error(formatMessage(message));
},
warn: function(message) {
winstonLogger.warn(formatMessage(message));
},
verbose: function(message) {
winstonLogger.verbose(formatMessage(message));
},
info: function(message) {
winstonLogger.info(formatMessage(message));
},
debug: function(message) {
winstonLogger.debug(formatMessage(message));
},
silly: function(message) {
winstonLogger.silly(formatMessage(message));
}
};
module.exports = logger;
我认为这是一个有点复杂,所以我决定在一篇文章中写下来。你可以从那里得到更多的信息:Express.js: Logging info with global unique request ID – Node.js
我希望这可以帮助你的问题。
在你的请求处理一开始就加入类似以下(或把它放在它自己的文件):
var makeID = (function() {
var index = 0;
return function() {
return index++;
}
})();
app.use(function(req, res, next) {
req.id = makeID()
next()
})
这会给每个请求都有一个唯一(顺序)的ID。 不要让人们认同它,只能在内部使用!
当温斯顿登录,就可以进入的元数据,该消息之后显示(形式${name}=${value}
),它看起来像这样
app.use(function(req, res) {
winston.log('info', 'Test Log Message', { id: req.id });
res.end("Done.")
});
希望这是有帮助的。
这是当前实现的解决方案,但是请求Id在其他模块/函数/方法中不可变,而不修改每个相关定义以包含请求Id或记录器。 – smokedice
难道你只是使用cookie,然后呢? – MayorMonty
会不需要请求访问z cookies? – smokedice
The first answer有一个问题:每次重新启动节点进程时计数器都会回到0。原来,这是相当简单的与标签使用uuid叫每个请求明确中间件做:
const uuid = require('uuid'); const app = express(); app.use(function (req, next) { req.id = uuid.v4(); next(); });
这种方法会将问题从记录器传递到每个对象,将请求交给每个对象。 – smokedice
如果您打算使用ES6,您可能需要使用'Symbol' – MayorMonty
很想,但现在我被困在0.10.13 – smokedice
@MayorMonty这会有帮助吗? – milan