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

Nest.js集成Winston后部分日志无法推送至Loki的问题求助

解决Nest.js定时任务日志无法推送至Loki的问题

你的定时任务日志只在控制台显示、无法推送到Loki的核心原因是:定时任务中使用的是Nest默认的ConsoleLogger,而非你配置的Winston Logger实例。下面是具体的问题分析和解决方案:

问题根源

当你通过NestFactory.create传入logger: WinstonModule.createLogger({ instance: winstonInstance })时,仅替换了Nest应用的全局Logger,但:

  • 手动new Logger(...)创建的实例默认会使用Nest自带的ConsoleLogger,不会自动关联到你的Winston实例
  • 直接注入Logger类时,默认提供的也是ConsoleLogger实例,而非Winston的

而你的HTTP拦截器日志能正常推送到Loki,大概率是因为拦截器是全局绑定的(比如通过APP_INTERCEPTOR),执行上下文自动关联了应用的全局Winston Logger;但定时任务是独立的提供者,默认使用的是ConsoleLogger,所以日志不会经过LokiTransport。

解决方案

方法1:依赖注入LoggerService(推荐)

这种方式能确保你使用的是配置好的Winston Logger实例:

  1. 在AppModule中注册Winston为全局LoggerService
    如果你还没使用WinstonModule.forRoot,可以用它自动注册全局Logger:

    import { Module } from '@nestjs/common';
    import { WinstonModule } from 'nest-winston';
    import { loggerConfig } from './logger.config';
    import { TemCleanerJob } from './tem-cleaner.job';
    import { APP_INTERCEPTOR } from '@nestjs/core';
    import { LoggerInterceptor } from './logger.interceptor';
    
    @Module({
      imports: [WinstonModule.forRoot(loggerConfig)], // 自动将Winston实例注册为LoggerService
      providers: [
        TemCleanerJob,
        {
          provide: APP_INTERCEPTOR,
          useClass: LoggerInterceptor,
        },
      ],
    })
    export class AppModule {}
    

    如果你坚持手动创建Winston实例,也可以手动绑定:

    import { Module, LoggerService } from '@nestjs/common';
    import { createLogger } from 'winston';
    import { loggerConfig } from './logger.config';
    
    const winstonInstance = createLogger(loggerConfig);
    
    @Module({
      providers: [
        {
          provide: LoggerService,
          useValue: winstonInstance,
        },
        TemCleanerJob,
      ],
    })
    export class AppModule {}
    
  2. 在定时任务中注入LoggerService
    替换手动创建Logger的方式,直接注入LoggerService:

    import { Injectable, LoggerService } from '@nestjs/common';
    import { Cron, CronExpression } from '@nestjs/schedule';
    
    @Injectable()
    export class TemCleanerJob {
      private readonly tempDir = './uploads/temp';
      private readonly maxAgeHours = 12;
    
      constructor(
        private readonly logger: LoggerService, // 注入Winston实例
        private readonly s3Service: S3Service,
      ) {}
    
      @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');
      }
    }
    

方法2:手动关联Winston实例到Logger类

如果你需要保留Logger类的上下文名称功能,可以在构造时传入全局Winston实例:

import { Inject, Injectable, Logger, LoggerService } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';

@Injectable()
export class TemCleanerJob {
  private readonly logger: Logger;
  private readonly tempDir = './uploads/temp';
  private readonly maxAgeHours = 12;

  constructor(
    @Inject(LoggerService) private readonly loggerService: LoggerService,
    private readonly s3Service: S3Service,
  ) {
    // 创建Logger时指定使用Winston实例
    this.logger = new Logger(TemCleanerJob.name, { 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');
  }
}

验证

完成配置后,运行定时任务,检查Grafana Loki是否能收到日志。此时所有日志都会经过Winston的两个Transport(Console和Loki),同时符合Loki要求的JSON格式。

内容的提问来源于stack exchange,提问作者Jorge Montejo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 10:07:31