如何在Winston自定义Transport中为info对象添加自定义数据?
问题原因分析
- 递归栈错误:Winston中调用
callback(null, info)会将修改后的info重新注入日志流程,导致所有Transport(包括你的CustomTransport和ConsoleTransport)重复处理,形成递归循环。 - 自定义信息不显示:当前的
printf格式化函数没有包含event_id和custom_data字段,所以即使添加了也不会输出到控制台。
解决方案
1. 修复递归错误
不要在callback中传入修改后的info,先创建info的副本进行修改,仅将副本传给webhook,然后调用callback(null)结束当前Transport的处理:
class CustomTransport extends Transport { constructor(opts) { super(opts); } log(info, callback) { // 创建info副本,避免修改原始对象触发递归 const modifiedInfo = { ...info }; modifiedInfo.event_id = 'test'; modifiedInfo.custom_data = { key1: 'value1' }; webhook(modifiedInfo); // 仅调用callback(null),不返回info,避免触发重复处理 callback(null); } }
2. 让自定义信息显示在控制台
修改printf格式化函数,将event_id和custom_data添加到输出内容中:
const format = winston.format.combine( winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.printf((info) => { // 构建基础日志内容 let logStr = winston.format.colorize().colorize(info.level, `[${info.level}] ${info.timestamp} : ${info.message}`); // 追加自定义字段 if (info.event_id) { logStr += winston.format.colorize().colorize('info', ` | Event ID: ${info.event_id}`); } if (info.custom_data) { logStr += winston.format.colorize().colorize('info', ` | Custom Data: ${JSON.stringify(info.custom_data)}`); } // 追加栈信息(如果存在) if (info.stack) { logStr += `\n${winston.format.colorize().colorize('error', info.stack)}`; } return logStr; }), );
更优雅的方案:用Winston Format统一添加Metadata
如果希望自定义字段在所有Transport中都能访问,推荐使用Winston的format来添加,更符合框架设计流程,彻底避免递归问题:
// 自定义format:添加全局metadata const addCustomMetadata = winston.format((info) => { info.event_id = 'test'; info.custom_data = { key1: 'value1' }; return info; }); // 组合所有format const format = winston.format.combine( addCustomMetadata(), // 先添加自定义字段 winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.printf((info) => { let logStr = winston.format.colorize().colorize(info.level, `[${info.level}] ${info.timestamp} : ${info.message}`); if (info.event_id) { logStr += winston.format.colorize().colorize('info', ` | Event ID: ${info.event_id}`); } if (info.custom_data) { logStr += winston.format.colorize().colorize('info', ` | Custom Data: ${JSON.stringify(info.custom_data)}`); } if (info.stack) { logStr += `\n${winston.format.colorize().colorize('error', info.stack)}`; } return logStr; }), ); // 简化CustomTransport,直接使用已添加字段的info class CustomTransport extends Transport { constructor(opts) { super(opts); } log(info, callback) { webhook(info); callback(null); } }
以上修改后,既不会出现递归错误,自定义的event_id和custom_data也会显示在控制台日志中,同时webhook也能拿到包含自定义字段的日志数据。
内容的提问来源于stack exchange,提问作者FxllenCode
相关产品推荐
相关产品推荐

