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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:30:53