Winston DailyRotateFile日志写入含转义字符问题求助
问题描述
用Winston搭建日志系统,采用DailyRotateFile传输器实现日志按天轮转。控制台日志显示正常,但写入文件的日志包含颜色控制转义字符(如[32m、[39m这类)。
初始配置代码:
const winstonLogFormat = winston.format.combine( winston.format.colorize({ all: true }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS', }), winston.format.align(), winston.format.printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) ) const fileRotateTransport = new winston.transports.DailyRotateFile({ filename: '%DATE%-app-log.log', dirname: 'logs', datePattern: 'YYYY-MM-DD', maxFiles: '28d', zippedArchive: true, json: false, }); const logger = winston.createLogger({ level: logLevel, format: winstonLogFormat, transports: [ fileRotateTransport, new winston.transports.Console() ] });
调用logger.info('Connected to: ' + target);后,日志文件内容:
[2024-01-11 10:50:46.160] [32minfo[39m: [32mConnected to: Home[39m
(Notepad++中每个[前显示黑色ESC标识)
控制台显示正常:
[2024-01-11 10:50:46.160] info: Connected to: Home
排查发现问题与winston.format.colorize({ all: true })相关,移除后文件日志正常,但控制台日志失去颜色。尝试为DailyRotateFile单独配置无颜色格式但未成功,需要实现控制台日志带颜色、文件日志无转义字符的需求。
尝试过的无效代码:
const winstonLogFormat = winston.format.combine( winston.format.colorize({ all: true }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS', }), winston.format.align(), winston.format.printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) ) const winstonLogFormatForFile = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS', }), winston.format.align(), winston.format.printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) ) const fileRotateTransport = new winston.transports.DailyRotateFile({ filename: '%DATE%-app-log.log', dirname: 'logs', datePattern: 'YYYY-MM-DD', maxFiles: '28d', zippedArchive: true, json: false, format: winstonLogFormatForFile }); const logger = winston.createLogger({ level: logLevel, format: winstonLogFormat, transports: [ fileRotateTransport, new winston.transports.Console() ] });
解决方案
问题核心是Winston会优先应用Logger全局配置的format,之后再应用Transport的format,所以全局的带颜色格式会先给日志添加转义字符,后续Transport的无颜色格式无法清除这些已存在的字符。
这里提供两种可行方案:
方案1:拆分格式,为每个Transport单独配置
定义基础无颜色格式,给控制台Transport叠加颜色格式,文件Transport直接使用基础格式,Logger不设置全局format:
// 基础无颜色格式,包含时间戳、对齐、输出模板 const baseLogFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS', }), winston.format.align(), winston.format.printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) ); // 控制台专用格式:在基础格式上叠加颜色 const consoleLogFormat = winston.format.combine( winston.format.colorize({ all: true }), baseLogFormat ); const fileRotateTransport = new winston.transports.DailyRotateFile({ filename: '%DATE%-app-log.log', dirname: 'logs', datePattern: 'YYYY-MM-DD', maxFiles: '28d', zippedArchive: true, json: false, format: baseLogFormat // 文件使用无颜色基础格式 }); const logger = winston.createLogger({ level: logLevel, // 不设置全局format,让每个Transport使用自己的格式配置 transports: [ fileRotateTransport, new winston.transports.Console({ format: consoleLogFormat // 控制台使用带颜色的格式 }) ] });
方案2:使用uncolorize()清除文件日志的转义字符
如果需要保留全局格式配置,可以在文件Transport中叠加uncolorize()格式,清除已添加的颜色控制字符:
const winstonLogFormat = winston.format.combine( winston.format.colorize({ all: true }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS', }), winston.format.align(), winston.format.printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) ); const fileRotateTransport = new winston.transports.DailyRotateFile({ filename: '%DATE%-app-log.log', dirname: 'logs', datePattern: 'YYYY-MM-DD', maxFiles: '28d', zippedArchive: true, json: false, // 在全局格式后叠加uncolorize,清除颜色转义字符 format: winston.format.combine( winstonLogFormat, winston.format.uncolorize() ) }); const logger = winston.createLogger({ level: logLevel, format: winstonLogFormat, transports: [ fileRotateTransport, new winston.transports.Console() ] });
方案1逻辑更清晰,避免不必要的颜色处理;方案2适合已有全局格式的场景,快速修正问题。
内容的提问来源于stack exchange,提问作者sirzento
相关产品推荐
相关产品推荐

