Winston 3 + Loopback 问题:错误消息显示在access.log中
我之前在Loopback项目里用Winston 3.x的时候也踩过这个坑——错误日志莫名其妙跑到access.log里,折腾了一阵才找到问题根源,主要是Winston的级别过滤逻辑和Loopback日志集成这两方面的问题,给你分享下解决步骤:
1. 先检查Winston Transport的级别配置
从你贴的代码片段来看,应该是定义了多个文件传输(比如info对应access.log,error对应单独的错误日志文件)。Winston 3.x的日志级别是有层级的:error > warn > info > verbose > debug > silly,默认情况下,如果你给某个Transport设置level: 'info',它会把**info级别及所有更高优先级的日志(比如warn、error)**都输出进去,这就是错误日志混进access.log的核心原因。
解决方法很简单,给access.log对应的Transport添加过滤规则,只保留你想要的级别:
首先引入Winston的filter格式化工具:
const { colorize, combine, timestamp, printf, filter } = winston.format;
然后修改你的infoFile配置(也就是access.log对应的传输设置):
var options = { infoFile: { level: 'info', filename: `${appRoot}/logs/access.log`, handleExceptions: false, json: false, maxsize: 5242880, // 5MB maxFiles: 5, format: combine( // 只保留info级别的日志,排除error、warn filter(info => info.level === 'info'), timestamp(), timeStampFormat ) }, // 你的errorFile配置保持不变,确保它的level是'error' errorFile: { level: 'error', filename: `${appRoot}/logs/errors.log`, handleExceptions: true, // ...其他配置 }, // ...控制台传输配置 };
如果你需要把verbose、debug这些低于info的级别也打进access.log,就把过滤条件改成:
filter(info => ['info', 'verbose', 'debug', 'silly'].includes(info.level))
2. 正确集成Loopback的日志系统
Loopback本身自带日志输出,如果没有把它的日志钩子正确指向Winston的对应logger,可能会导致Loopback的错误日志被默认打到access.log里。
在你的项目server.js里,替换Loopback的默认日志组件:
const logger = require('./path/to/your/winston.js'); // 引入你的Winston配置文件 // 替换Loopback默认的logger,让它用Winston处理info级别的访问日志 app.use(loopback.logger(logger, { level: 'info' })); // 单独捕获Loopback的错误事件,用Winston的error级别输出 app.on('error', (err) => { logger.error(err.stack || err.message); }); // 确保Loopback本身的日志级别不会包含error,避免它自己把错误打进access.log loopback.logger.setLevel('info');
另外检查下server/config.json里的logLevel配置,确保是"info"而不是更高的级别:
{ "logLevel": "info" }
3. 验证Winston Logger的初始化
最后确认你的Winston Logger是正确初始化的,把不同的Transport对应到正确的级别:
const logger = winston.createLogger({ transports: [ new winston.transports.File(options.infoFile), new winston.transports.File(options.errorFile), new winston.transports.Console(options.console) ], exitOnError: false // 避免未捕获异常导致进程退出 }); module.exports = logger;
额外排查小技巧
- 检查项目里有没有手动写错日志级别的地方,比如在错误处理代码里不小心用了
logger.info(err)而不是logger.error(err); - 你用的是Winston 3.0.0rc5,这是候选版本,可能存在一些级别过滤的bug,要是上面的配置都没用,可以尝试升级到Winston 3.x的正式版,稳定性会更好。
内容的提问来源于stack exchange,提问作者xfscrypt

