Nest.js集成Winston后部分日志无法发送至Loki的排查求助
解决Nest.js中定时任务类日志无法发送到Loki的问题
我帮你排查下这个问题——核心原因是你在定时任务类里用的日志实例,和全局配置的Winston日志不是同一个。拦截器里的日志能正常到Loki,是因为Nest应用全局已经切换成了Winston日志,但定时任务里要么是手动new了默认的控制台日志,要么注入的还是原生Nest Logger,没绑定Winston。
具体问题拆解
你在AppModule的providers里直接加Logger,相当于注册了Nest原生的ConsoleLogger,不是你配置的Winston实例。而定时任务里如果直接new Logger(),创建的也是默认控制台日志,自然不会把日志发去Loki。
一步步解决
1. 改用WinstonModule全局注册日志
先把日志配置迁移到模块导入里,让整个应用都用同一个Winston实例:
修改你的AppModule:
import { Module } from '@nestjs/common'; import { WinstonModule } from 'nest-winston'; import { loggerConfig } from './path-to-your-logger-config'; // 替换成你的配置路径 @Module({ imports: [ WinstonModule.forRoot(loggerConfig), // 全局注册Winston日志模块 ], // 删掉providers里的Logger,别让它覆盖Winston实例 }) export class AppModule {}
2. 调整bootstrap方法,用全局Winston日志
不用再手动创建Winston实例了,直接用模块提供的:
async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: WinstonModule.createLogger(), // 用全局注册的Winston日志 }); // 你的其他应用配置(比如CORS、管道之类的) await app.listen(3000); } bootstrap();
3. 定时任务类注入LoggerService(别再new Logger了)
把定时任务里的日志改成依赖注入的方式,确保拿到的是Winston实例:
import { Injectable, LoggerService } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; @Injectable() export class TemCleanerJob { // 注入LoggerService,不要手动new Logger constructor( private readonly s3Service: S3Service, private readonly logger: LoggerService, ) {} @Cron(CronExpression.EVERY_MINUTE) idk() { this.logger.log('log template'); this.logger.warn('warn log template'); this.logger.error('error log template'); throw new Error('asdfasd'); } }
如果你不想用WinstonModule.forRoot(备选方案)
要是你坚持手动创建Winston实例,那得把这个实例注册成Nest的Logger提供者:
首先在bootstrap里导出实例:
import { createLogger } from 'winston'; import { loggerConfig } from './path-to-your-logger-config'; export const winstonInstance = createLogger(loggerConfig); async function bootstrap() { const app = await NestFactory.create(AppModule, { logger: WinstonModule.createLogger({ instance: winstonInstance }), }); await app.listen(3000); } bootstrap();
然后修改AppModule:
import { Module } from '@nestjs/common'; import { winstonInstance } from './bootstrap'; import { Logger } from '@nestjs/common'; @Module({ providers: [ { provide: Logger, useValue: winstonInstance, // 把Winston实例注册成Logger的实现 }, TemCleanerJob, // 你的其他服务 ], }) export class AppModule {}
之后在定时任务里注入Logger就行。
验证一下
重启应用,等定时任务触发,然后去Grafana里查Loki,应该就能看到这些日志了。
内容的提问来源于stack exchange,提问作者Jorge Montejo
相关产品推荐
相关产品推荐

