使用Winston时Logger.info()始终返回undefined的问题排查
Winston日志调用返回undefined问题排查
我基于Winston和DailyRotateFile编写了logger.ts日志文件,通过LoggerFactory创建日志实例,但调用logger.info('Hello, world!')时始终返回undefined,在路由中调用该日志方法也存在同样问题。console.log显示logger是DerivedLogger实例,请问这是什么原因?
日志工具代码(logger.ts)
import winston from 'winston' import path from 'path' import DailyRotateFile from 'winston-daily-rotate-file' const loggerInstances = new Map<string, winston.Logger>() export const LoggerFactory: (label: string) => winston.Logger = ( label: string ) => { let logger = loggerInstances.get(label) if (logger != null) { return logger } // 若不存在对应label的logger,则创建、缓存并返回新实例 logger = getLogger(label) loggerInstances.set(label, logger) return logger } const transport = new DailyRotateFile({ filename: './logs/app-%DATE%.log', // 使用相对路径而非绝对路径 datePattern: 'YYYY-MM-DD', zippedArchive: true, maxFiles: '15d', handleExceptions: true, }) function getLogger(label: string): winston.Logger { return winston.createLogger({ level: 'info', exitOnError: false, format: winston.format.combine( winston.format.timestamp(), winston.format.label({ label: label }), winston.format.splat() // winston.format.json() ), transports: [ transport, new winston.transports.Console() ], }) }
路由中的调用代码
import { LoggerFactory } from '../../libs/logger' const logger = LoggerFactory('test.ts') router.get('/', async (req: Request, res: Response) => { console.log("logger", logger) try { logger.info('Hello, world!'); res.send('Hello, world!'); } catch (err) { logger.error(`An error occurred: ${err}`); res.status(500).send('Internal server error'); } });
控制台输出的logger实例
logger <ref *1> DerivedLogger { [1] _readableState: ReadableState { [1] flowing: true, [1] ended: false, [1] endEmitted: false, [1] reading: true, [1] sync: false, [1] needReadable: true, [1] emittedReadable: false, [1] readableListening: false, [1] resumeScheduled: false, [1] paused: false, [1] emitClose: true, [1] autoDestroy: false, [1] destroyed: false, [1] defaultEncoding: 'utf8', .............
问题原因与解决方案
1. 核心原因:Winston日志方法设计为无返回值
Winston的info/error等日志方法本身就没有返回值,调用后返回undefined是正常行为,并非代码bug。判断日志功能是否正常,应该看日志是否成功输出到控制台和指定的日志文件,而非方法的返回值。
2. 潜在风险:共享Transport实例
你将DailyRotateFile transport定义为全局单例,所有通过LoggerFactory创建的logger都会共享这个实例,可能引发日志交叉写入、资源竞争等问题。建议每个logger实例使用独立的transport。
修正后的代码(logger.ts)
import winston from 'winston' import DailyRotateFile from 'winston-daily-rotate-file' const loggerInstances = new Map<string, winston.Logger>() export const LoggerFactory: (label: string) => winston.Logger = ( label: string ) => { let logger = loggerInstances.get(label) if (logger != null) { return logger } logger = getLogger(label) loggerInstances.set(label, logger) return logger } function getLogger(label: string): winston.Logger { // 为每个logger实例创建独立的DailyRotateFile transport const transport = new DailyRotateFile({ filename: './logs/app-%DATE%.log', datePattern: 'YYYY-MM-DD', zippedArchive: true, maxFiles: '15d', handleExceptions: true, }) return winston.createLogger({ level: 'info', exitOnError: false, format: winston.format.combine( winston.format.timestamp(), winston.format.label({ label: label }), winston.format.splat(), // 自定义日志输出格式,确保日志内容清晰可见 winston.format.printf(({ timestamp, label, level, message }) => { return `${timestamp} [${label}] ${level}: ${message}` }) ), transports: [ transport, new winston.transports.Console() ], }) }
补充说明
- 开启日志格式配置:你之前注释了
winston.format.json()且未配置其他输出格式,会导致日志内容无法正常显示。添加自定义printf格式后,控制台和日志文件会输出结构化的日志内容。 - 验证方式:检查
./logs目录下是否生成了对应日期的日志文件,同时观察控制台是否输出了目标日志内容,即可确认日志功能正常。
内容的提问来源于stack exchange,提问作者Newbie_developer
相关产品推荐
相关产品推荐

