NodeJS Express - 全球唯一请求标识

问题描述:

是否可以定义每个日志语句中包含的唯一请求标识,而无需将记录器交给每个方法/函数调用?NodeJS Express - 全球唯一请求标识

技术在使用中:的NodeJS,快速,温斯顿

+0

如果您打算使用ES6,您可能需要使用'Symbol' – MayorMonty

+0

很想,但现在我被困在0.10.13 – smokedice

+0

@MayorMonty这会有帮助吗? – milan

我们在几个项目同样的问题,我不能为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.") 
}); 

希望这是有帮助的。

+0

这是当前实现的解决方案,但是请求Id在其他模块/函数/方法中不可变,而不修改每个相关定义以包含请求Id或记录器。 – smokedice

+0

难道你只是使用cookie,然后呢? – MayorMonty

+0

会不需要请求访问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(); });

+0

这种方法会将问题从记录器传递到每个对象,将请求交给每个对象。 – smokedice