将唯一会话 ID 传递给 Winston 记录器
Passing a unique session ID to Winston logger
我想弄清楚是否有一种方法可以在发出 HTTP 请求时在所有 winston 记录器调用中使用唯一的(每个请求)会话 ID。
对该问题的阐述:
假设每分钟有数百个请求访问一个网站,并且每个请求都通过不同的函数来注销各种消息。
我的目标是使用 winston 记录器记录包含每个请求的唯一会话 ID 的消息,直到发送响应。
我使用 express-session 库中的 app.use(session(...))
为请求生成一个唯一的会话 ID。
使用 morgan,HTTP 日志使用唯一的会话 ID 打印,如下所示:
logger = winston.createLogger(...);
const myStream = {
write: (text: string) => {
logger.info(text);
}
}
morgan.token('sessionid', function (req, res) { return req['sessionID'] });
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" ["SESSION_ID :sessionid"]', { stream: myStream }));
但是,我也想在其他记录器中使用相同的会话 ID。* 代码中其他地方的函数。我能够做到这一点,但随着同时请求的数量(使用 k6 负载测试)增加,会话 ID 会被另一个请求的新会话 ID 覆盖。
我在 winston 传输中使用请求中的会话 ID 的代码是:
public static initializeLogger(appInstance: express.Application) {
if (!appInstance) throw new Error(`Cannot initialize logger. Invalid express.Application instance passed. Logging may not be available`);
appInstance.use((req, res, next) => {
//this.m_sessionID = req["sessionID"];
this.m_logger.clear();
this.m_logger = winston.createLogger({
level: LOG_LEVEL,
levels: winston.config.syslog.levels,
format: winston.format.json(),
transports: [
new winston.transports.Console({ format: winston.format.simple() }),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'debug.log', level: 'debug' }),
new WinstonCloudWatch({
logGroupName: CLOUDWATCH_LOG_GROUP_NAME,
logStreamName: function () {
let date = new Date().toISOString().split('T')[0];
return 'k-server-logs-' + date;
},
awsRegion: AWS_REGION,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
retentionInDays: process.env.CLOUDWATCH_LOG_RETENTION_DAYS ? Number(process.env.CLOUDWATCH_LOG_RETENTION_DAYS) : 30,
messageFormatter: (log) => {
return `${JSON.stringify({
message: log.message,
sessionID: req["sessionID"],
level: log.level
})}`
}
})
],
});
next();
});
}
我希望将 winston 记录器放在 app.use(...)
中间件中,从而为 winston 记录器设置 cloudwatch 传输,并在每个请求进入时使用 req.sessionID。
但是,此设置不起作用。如果我同时发送 10 个请求,此代码将中断并且 sessionID 被错误地标记在记录器上。* 消息 and/or 在多条消息中重复。
我查看了其他实现,例如 https://solidgeargroup.com/en/express-logging-global-unique-request-identificator-nodejs/,但无法使其正常工作。
希望得到一些建议 - 我确定我的设置已关闭。
提前谢谢你。
来自https://solidgeargroup.com/en/express-logging-global-unique-request-identificator-nodejs/
的关键提示
使用具有设置和获取功能的 express-http-context 可确保唯一会话 ID 在整个代码中可用。
import httpContext from 'express-http-context';
...
...
logger.add(new WinstonCloudWatch({
level:LOG_LEVEL,
logGroupName: CLOUDWATCH_LOG_GROUP_NAME,
logStreamName: function () {
let date = new Date().toISOString().split('T')[0];
return `${process.env.CLOUDWATCH_LOG_FILE_NAMEPREFIX}-logs-${date}`;
},
awsRegion: AWS_REGION,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
retentionInDays: process.env.CLOUDWATCH_LOG_RETENTION_DAYS ? Number(process.env.CLOUDWATCH_LOG_RETENTION_DAYS) : 30,
messageFormatter: (log) => {
return `${JSON.stringify({
message: log.message,
**sessionID: httpContext.get('reqId')**,
level: log.level
})}`
}
}));
我想弄清楚是否有一种方法可以在发出 HTTP 请求时在所有 winston 记录器调用中使用唯一的(每个请求)会话 ID。
对该问题的阐述:
假设每分钟有数百个请求访问一个网站,并且每个请求都通过不同的函数来注销各种消息。
我的目标是使用 winston 记录器记录包含每个请求的唯一会话 ID 的消息,直到发送响应。
我使用 express-session 库中的 app.use(session(...))
为请求生成一个唯一的会话 ID。
使用 morgan,HTTP 日志使用唯一的会话 ID 打印,如下所示:
logger = winston.createLogger(...);
const myStream = {
write: (text: string) => {
logger.info(text);
}
}
morgan.token('sessionid', function (req, res) { return req['sessionID'] });
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent" ["SESSION_ID :sessionid"]', { stream: myStream }));
但是,我也想在其他记录器中使用相同的会话 ID。* 代码中其他地方的函数。我能够做到这一点,但随着同时请求的数量(使用 k6 负载测试)增加,会话 ID 会被另一个请求的新会话 ID 覆盖。
我在 winston 传输中使用请求中的会话 ID 的代码是:
public static initializeLogger(appInstance: express.Application) {
if (!appInstance) throw new Error(`Cannot initialize logger. Invalid express.Application instance passed. Logging may not be available`);
appInstance.use((req, res, next) => {
//this.m_sessionID = req["sessionID"];
this.m_logger.clear();
this.m_logger = winston.createLogger({
level: LOG_LEVEL,
levels: winston.config.syslog.levels,
format: winston.format.json(),
transports: [
new winston.transports.Console({ format: winston.format.simple() }),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'debug.log', level: 'debug' }),
new WinstonCloudWatch({
logGroupName: CLOUDWATCH_LOG_GROUP_NAME,
logStreamName: function () {
let date = new Date().toISOString().split('T')[0];
return 'k-server-logs-' + date;
},
awsRegion: AWS_REGION,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
retentionInDays: process.env.CLOUDWATCH_LOG_RETENTION_DAYS ? Number(process.env.CLOUDWATCH_LOG_RETENTION_DAYS) : 30,
messageFormatter: (log) => {
return `${JSON.stringify({
message: log.message,
sessionID: req["sessionID"],
level: log.level
})}`
}
})
],
});
next();
});
}
我希望将 winston 记录器放在 app.use(...)
中间件中,从而为 winston 记录器设置 cloudwatch 传输,并在每个请求进入时使用 req.sessionID。
但是,此设置不起作用。如果我同时发送 10 个请求,此代码将中断并且 sessionID 被错误地标记在记录器上。* 消息 and/or 在多条消息中重复。
我查看了其他实现,例如 https://solidgeargroup.com/en/express-logging-global-unique-request-identificator-nodejs/,但无法使其正常工作。
希望得到一些建议 - 我确定我的设置已关闭。
提前谢谢你。
来自https://solidgeargroup.com/en/express-logging-global-unique-request-identificator-nodejs/
的关键提示使用具有设置和获取功能的 express-http-context 可确保唯一会话 ID 在整个代码中可用。
import httpContext from 'express-http-context';
...
...
logger.add(new WinstonCloudWatch({
level:LOG_LEVEL,
logGroupName: CLOUDWATCH_LOG_GROUP_NAME,
logStreamName: function () {
let date = new Date().toISOString().split('T')[0];
return `${process.env.CLOUDWATCH_LOG_FILE_NAMEPREFIX}-logs-${date}`;
},
awsRegion: AWS_REGION,
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
retentionInDays: process.env.CLOUDWATCH_LOG_RETENTION_DAYS ? Number(process.env.CLOUDWATCH_LOG_RETENTION_DAYS) : 30,
messageFormatter: (log) => {
return `${JSON.stringify({
message: log.message,
**sessionID: httpContext.get('reqId')**,
level: log.level
})}`
}
}));