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

如何在NestJS的AppModule中访问自定义Logger实例?

解决NestJS AppModule中无法获取自定义Logger实例的问题

问题原因

你在bootstrap中传入的自定义Logger是给Nest框架内部使用的实例,但这个实例并没有自动注册到DI容器中。其他模块能正常注入是因为CustomLoggerModule正确提供了Logger实例,而AppModule要么没正确导入该模块,要么尝试通过ModuleRef获取时,DI容器中还没有注册自定义Logger的token,导致拿到了Nest默认的Logger实例。

解决方案

方案1:确保CustomLoggerModule全局化并直接注入

  1. 修改CustomLoggerModule,将其设为全局模块并导出自定义Logger:
import { Module, Global, LoggerService } from '@nestjs/common';
import { CustomLogger } from './custom.logger';

@Global()
@Module({
  providers: [
    CustomLogger,
    // 同时注册为LoggerService抽象,兼容Nest的Logger注入
    {
      provide: LoggerService,
      useClass: CustomLogger,
    },
  ],
  exports: [CustomLogger, LoggerService],
})
export class CustomLoggerModule {
  static createLogger() {
    return new CustomLogger();
  }
}
  1. 在AppModule中直接注入CustomLogger,无需使用ModuleRef:
import { Module, OnModuleInit } from '@nestjs/common';
import { CustomLogger } from './custom.logger';

@Module({
  // 因为是全局模块,这里可以不用导入,但显式导入更清晰
  imports: [CustomLoggerModule],
})
export class AppModule implements OnModuleInit {
  constructor(private readonly customLogger: CustomLogger) {}

  onModuleInit() {
    // 这里可以正常调用initMiddleware方法
    this.customLogger.initMiddleware();
  }
}

方案2:让bootstrap和DI使用同一个Logger实例

如果需要保证启动阶段和DI中的Logger是同一个实例,可以修改CustomLoggerModule复用实例:

import { Module, Global, LoggerService, DynamicModule } from '@nestjs/common';
import { CustomLogger } from './custom.logger';

@Global()
@Module({})
export class CustomLoggerModule {
  private static loggerInstance: CustomLogger;

  static createLogger(): CustomLogger {
    if (!this.loggerInstance) {
      this.loggerInstance = new CustomLogger();
    }
    return this.loggerInstance;
  }

  static forRoot(): DynamicModule {
    return {
      module: CustomLoggerModule,
      providers: [
        {
          provide: CustomLogger,
          useValue: this.loggerInstance,
        },
        {
          provide: LoggerService,
          useValue: this.loggerInstance,
        },
      ],
      exports: [CustomLogger, LoggerService],
    };
  }
}

然后在bootstrap和AppModule中配合使用:

// bootstrap.ts
async function bootstrap() {
  // 创建全局唯一的Logger实例
  const logger = CustomLoggerModule.createLogger();
  // 传入NestFactory
  const app = await NestFactory.create(AppModule, { logger });
  await app.listen(3000);
}

// AppModule.ts
@Module({
  imports: [CustomLoggerModule.forRoot()],
})
export class AppModule implements OnModuleInit {
  constructor(private readonly customLogger: CustomLogger) {}

  onModuleInit() {
    this.customLogger.initMiddleware();
  }
}

方案3:检查ModuleRef的使用方式

如果一定要用ModuleRef,需要确保在模块初始化完成后获取,比如在OnModuleInit生命周期钩子中,并且指定正确的token:

import { Module, OnModuleInit, ModuleRef } from '@nestjs/common';
import { CustomLogger } from './custom.logger';
import { CustomLoggerModule } from './custom-logger.module';

@Module({
  imports: [CustomLoggerModule],
})
export class AppModule implements OnModuleInit {
  constructor(private readonly moduleRef: ModuleRef) {}

  async onModuleInit() {
    // 明确指定获取CustomLogger类型的实例
    const customLogger = this.moduleRef.get(CustomLogger);
    customLogger.initMiddleware();
  }
}

关键注意点

  • 不要混淆Nest框架内部使用的Logger和DI容器中的Logger:前者是通过NestFactory.create传入的,后者需要在模块中显式注册。
  • 确保CustomLoggerModule的导出和导入逻辑正确,DI容器才能找到自定义Logger的实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 02:35:25