Node.js中Pino全局log变量初始化后其他文件未定义的解决办法
全局Pino日志对象初始化时机问题解决方案
问题说明
使用Pino创建可自定义的全局日志对象,已通过global.d.ts声明全局变量log,在initiateLoggerService.ts中设置global.log后能正常打印日志,但在index.ts模块顶部声明const log = global.log后,调用函数时log为undefined,报错Cannot read properties of undefined (reading 'info')。核心原因是模块加载时全局日志对象尚未完成初始化,且希望避免在每个方法中手动导入日志对象。
解决方案
方案1:通过Getter函数延迟获取全局日志
避免在模块顶部直接赋值全局变量,改用函数每次调用时动态获取最新的global.log,绕开初始化时机问题:
修改index.ts:
const getLog = () => global.log; export const testFunction1 = () => { getLog().info('testFunction starts here'); } export const testFunction2 = () => { getLog().info('testFunction starts here'); }
方案2:封装日志为单例模块
创建单例日志模块,统一管理初始化状态,其他文件直接导入该模块的导出,既保证全局复用,又能明确控制初始化流程:
- 新建
singletonLogger.ts:
import pino from 'pino' import pretty from 'pino-pretty' let logger: pino.Logger | undefined; export const initLogger = (job_name: any) => { const streams = [ { stream: pino.destination('myDetails.log') }, { stream: pretty({ colorize: true, sync: true, messageFormat: `{"job_name":${job_name}, "message":{msg}}` }) } ] logger = pino({level: 'info', timestamp: pino.stdTimeFunctions.isoTime}, pino.multistream(streams)); logger.info('日志对象初始化完成'); } export const getLogger = () => { if (!logger) { throw new Error('日志对象未初始化,请先调用initLogger'); } return logger; }
- 修改
initiateLoggerService.ts:
import { initLogger } from './singletonLogger'; export const setLogObject = (job_name: any) => { initLogger(job_name); }
- 修改
index.ts:
import { getLogger } from './singletonLogger'; export const testFunction1 = () => { getLogger().info('testFunction starts here'); } export const testFunction2 = () => { getLogger().info('testFunction starts here'); }
方案3:调整模块加载顺序确保先初始化日志
在项目入口文件中,先执行日志初始化逻辑,再导入其他依赖日志的模块,确保global.log在其他模块加载前已完成赋值:
修改项目入口文件(如app.ts):
import { setLogObject } from './initiateLoggerService'; // 优先初始化全局日志 setLogObject('your-job-name'); // 再导入需要使用日志的模块 import { testFunction1, testFunction2 } from './index'; // 后续业务逻辑 testFunction1(); testFunction2();
内容的提问来源于stack exchange,提问作者Pavan Kumar
相关产品推荐
相关产品推荐

