NestJS 日志系统初探
1. NestJS 自带日志
NestJS 内置了基于 ConsoleLogger 的日志系统,支持以下级别:
typescript
import { Logger } from '@nestjs/common';
const logger = new Logger('AppContext');
logger.log('普通日志');
logger.error('错误日志');
logger.warn('警告日志');
logger.debug('调试日志');
logger.verbose('详细日志');2. 自定义日志器
继承 ConsoleLogger 并覆盖方法:
typescript
// my-logger.service.ts
import { ConsoleLogger } from '@nestjs/common';
export class MyLogger extends ConsoleLogger {
log(message: any, context?: string) {
// 自定义逻辑
super.log(message, context);
}
error(message: any, stack?: string, context?: string) {
super.error(message, stack, context);
}
warn(message: any, context?: string) {
super.warn(message, context);
}
debug(message: any, context?: string) {
super.debug(message, context);
}
verbose(message: any, context?: string) {
super.verbose(message, context);
}
}3. 创建 LoggerModule
typescript
// my-logger.module.ts
import { Module, Global } from '@nestjs/common';
import { MyLogger } from './my-logger.service';
@Global() // 全局模块,其他模块无需显式导入
@Module({
providers: [MyLogger],
exports: [MyLogger],
})
export class LoggerModule {}4. 让 Nest 框架使用自定义日志器
在 main.ts 中设置:
typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MyLogger } from './my-logger/my-logger.service';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
bufferLogs: true, // 缓冲日志,直到自定义日志器就绪
});
// 关键:让 Nest 框架本身使用 MyLogger
app.useLogger(app.get(MyLogger));
await app.listen(3000);
}| 配置 | 作用 |
|---|---|
bufferLogs: true | 启动期间缓冲日志,避免丢失 |
app.useLogger() | 让框架日志(路由、异常等)使用自定义 logger |
5. 业务模块使用依赖注入
在 AppModule 中导入 LoggerModule(必须,用于初始化):
typescript
// app.module.ts
import { LoggerModule } from './my-logger/my-logger.module';
@Module({
imports: [LoggerModule], // 必须导入
// ...
})
export class AppModule {}在任何 Service/Ctorller 中注入使用:
typescript
// app.service.ts
import { Injectable } from '@nestjs/common';
import { MyLogger } from './my-logger/my-logger.service';
@Injectable()
export class AppService {
constructor(private readonly myLogger: MyLogger) {}
getHello() {
this.myLogger.log('getHello called');
return 'Hello World';
}
}6. 架构关系图
┌─────────────────────────────────────────────────────────────┐
│ NestJS 应用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ main.ts: app.useLogger(app.get(MyLogger)) ←── 框架日志 │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ LoggerModule (@Global) │ │
│ │ ├── providers: [MyLogger] │ │
│ │ └── exports: [MyLogger] │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ MyLogger │ │
│ │ extends ConsoleLogger │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ AppService │ │ UserService │ │
│ │ 注入使用 │ │ 注入使用 │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘7. 关键要点
| 概念 | 说明 |
|---|---|
@Global() | 标记后,其他模块无需 imports 即可使用 |
bufferLogs: true | 启动期间缓冲日志,确保不丢失 |
app.useLogger() | 必须,让框架日志也走自定义 logger |
AppModule 导入 | 即使是全局模块,也需在某处导入来初始化 |
| 依赖注入 | 推荐,优于手动 new MyLogger() |
8. 日志级别
| 级别 | 用途 |
|---|---|
log | 一般信息 |
error | 错误 |
warn | 警告 |
debug | 调试(开发用) |
verbose | 详细追踪(最底层) |