Session 将唯一会话ID传递给Winston logger

Session 将唯一会话ID传递给Winston logger,session,winston,morgan,Session,Winston,Morgan,我试图弄清楚,当发出HTTP请求时,是否有办法在所有winston logger调用中使用唯一的(每个请求)会话ID 关于这个问题的详细说明: 假设每分钟有几百个请求访问一个网站,每个请求都通过不同的函数,这些函数会注销不同的消息 我的目标是使用logger记录包含每个请求的唯一会话ID的消息,直到发送响应为止 我使用app.use(session(…)从express session库为请求生成唯一的会话ID 使用morgan,HTTP日志会打印一个唯一的会话ID,如下所示: logger =

我试图弄清楚,当发出HTTP请求时,是否有办法在所有winston logger调用中使用唯一的(每个请求)会话ID

关于这个问题的详细说明:

假设每分钟有几百个请求访问一个网站,每个请求都通过不同的函数,这些函数会注销不同的消息

我的目标是使用logger记录包含每个请求的唯一会话ID的消息,直到发送响应为止

我使用
app.use(session(…)
express 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 }));
但是,我还希望在代码其他地方的其他logger.*函数中使用相同的会话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 logger放入
app.use(…)
中间件将为winston logger设置cloudwatch传输,同时在每个请求传入时使用req.sessionID

但是,此设置不起作用。如果我同时发送10个请求,此代码将中断,并且sessionID错误地印在logger.*消息上和/或在多条消息中重复

我查看了其他实现,如,但无法使其正常工作

希望得到一些建议-我确信我的设置已关闭

提前感谢您。

来自的关键提示

使用express http context,它有一个set and get函数,可以确保在整个代码中都可以使用唯一的会话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
                    })}`
                }
}));