You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中使用log4js在每条日志语句中打印req.user.id

给Express的log4js日志自动添加req.user.id的解决方案

嘿,我来帮你搞定这个需求!先梳理下你当前的使用方式:

你现有的代码结构

路由文件中的用法

var log = require('log4jslogger.js').LOG;
log.info('this is log statement');

log4jslogger.js文件内容

var log4js = require('log4js');
log4js.configure(__base + "log4jsconfig.json");
var logger = log4js.getLogger('default');
Object.defineProperty(exports, "LOG", { value : logger, });

log4jsconfig.json配置(补全了缺失的必要部分)

{ 
  "appenders": { 
    "out": { "type": "stdout" }, 
    "default": { 
      "type": "dateFile", 
      "filename": "logs/default", 
      "pattern": "-yyyy-MM-dd.log" 
    } 
  },
  "categories": {
    "default": { "appenders": ["out", "default"], "level": "info" }
  }
}

接下来给你两个实用的方案,按需选择:

方案一:自定义Logger包装器(简单安全)

这个方法不需要修改log4js的全局配置,而是给每个请求创建一个带用户ID的logger实例,完全不用担心请求间的上下文污染。

修改你的log4jslogger.js:

var log4js = require('log4js');
log4js.configure(__base + "log4jsconfig.json");
var baseLogger = log4js.getLogger('default');

// 封装一个创建logger的函数,自动注入当前请求的user id
const createLogger = (req) => {
  // 处理user不存在的情况,给个默认值避免报错
  const userId = req?.user?.id || 'unknown-user';
  
  return {
    info: (message) => baseLogger.info(`[User: ${userId}] ${message}`),
    warn: (message) => baseLogger.warn(`[User: ${userId}] ${message}`),
    error: (message) => baseLogger.error(`[User: ${userId}] ${message}`),
    debug: (message) => baseLogger.debug(`[User: ${userId}] ${message}`)
    // 如果你用其他日志级别,比如trace、fatal,按需添加即可
  };
};

// 保留原有的LOG导出,兼容旧代码
exports.LOG = baseLogger;
// 导出新的创建函数供路由使用
exports.createLogger = createLogger;

然后在路由里这样使用:

const { createLogger } = require('./log4jslogger.js');

router.get('/your-path', (req, res) => {
  const log = createLogger(req);
  log.info('this is log statement');
  // 最终日志输出会是:[User: 123] this is log statement(假设req.user.id是123)
  res.send('success');
});

方案二:利用log4js上下文(优雅无侵入)

这个方法可以让你完全保留原来的日志写法,通过log4js的上下文功能自动在日志中添加用户ID,适合不想修改现有路由代码的场景。

步骤1:添加Express中间件设置上下文

在你的Express入口文件(比如app.js)里添加一个全局中间件,把当前请求的user id存入log4js的上下文:

const log4js = require('log4js');

// 确保这个中间件在你的认证中间件之后执行,这样req.user才会存在
app.use((req, res, next) => {
  const userId = req?.user?.id || 'unknown-user';
  // 给log4js添加上下文变量userId
  log4js.addContext('userId', userId);
  next();
});

步骤2:修改log4js配置文件

更新log4jsconfig.json,在布局pattern中加入%X{userId}来打印上下文里的用户ID:

{ 
  "appenders": { 
    "out": { 
      "type": "stdout",
      "layout": {
        "type": "pattern",
        "pattern": "%d [%p] [User: %X{userId}] %m%n"
      }
    }, 
    "default": { 
      "type": "dateFile", 
      "filename": "logs/default", 
      "pattern": "-yyyy-MM-dd.log",
      "layout": {
        "type": "pattern",
        "pattern": "%d [%p] [User: %X{userId}] %m%n"
      }
    } 
  },
  "categories": {
    "default": { "appenders": ["out", "default"], "level": "info" }
  }
}

步骤3:继续用原来的方式打日志

不需要修改任何路由代码,直接像以前一样使用:

var log = require('log4jslogger.js').LOG;
log.info('this is log statement');
// 日志会自动输出类似:2024-05-20 14:30:00 [INFO] [User: 123] this is log statement

注意点

  • 这个方案依赖log4js的异步上下文支持,确保你的log4js版本在2.x及以上(Node.js版本建议8.x+),否则在高并发场景下可能出现用户ID串号的问题。如果担心这个,方案一更稳妥。

内容的提问来源于stack exchange,提问作者Yogesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:16:04