NestJS内置日志模块使用学习笔记
核心知识点
1. NestJS 日志开关控制
1.1 关闭全局日志
在 main.ts 的 NestFactory.create() 第二个参数中,设置 logger: false 即可关闭所有日志输出:
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
logger: false, // 关闭 NestJS 全局日志
});
await app.listen(3000);
}
bootstrap();1.2 设置日志等级
通过 logger 参数传入一个日志等级数组,只输出指定等级的日志:
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
// 只输出 error 和 warn 级别的日志
logger: ['error', 'warn'],
});
await app.listen(3000);
}
bootstrap();1.3 如何知道可用的日志等级?
TypeScript 类型提示:按住
Cmd/Ctrl点击logger参数,跳转到类型定义即可看到所有可用值。
跳转到定义后可见:
typescript
// NestFactory.create 的第二个参数类型定义
interface NestApplicationOptions {
logger?: boolean | LogLevel[];
// ...
}
// LogLevel 类型定义
type LogLevel = 'log' | 'error' | 'warn' | 'debug' | 'verbose';如果输入了非法值(如
'123'),TypeScript 会立即报错提示,这正是 TS 的优势所在。
1.4 日志等级选项一览
| 设置方式 | 效果 |
|---|---|
logger: false | 关闭所有日志 |
logger: true | 开启所有日志(默认值) |
logger: ['error', 'warn'] | 只输出 error 和 warn |
logger: ['log'] | 只输出 log 通用日志 |
logger: ['error', 'warn', 'log'] | 输出 error、warn、log |
2. Logger 实例的创建与使用
2.1 导入 Logger
typescript
import { Logger } from '@nestjs/common';2.2 在 main.ts 中使用
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 创建 Logger 实例
const logger = new Logger('Bootstrap');
const port = 3000;
// 使用不同等级的日志方法
logger.log(`Application is running on: http://localhost:${port}`);
logger.warn(`Running in development mode`);
logger.error(`This is an error message`);
logger.debug(`Debugging information...`);
logger.verbose(`Verbose detailed information...`);
await app.listen(port);
}
bootstrap();2.3 日志输出颜色区分
不同日志等级在终端中显示不同的颜色,便于快速识别:
| 等级 | 方法 | 终端颜色 | 用途 |
|---|---|---|---|
log | logger.log() | 绿色 | 通用信息 |
warn | logger.warn() | 黄色 | 警告提示 |
error | logger.error() | 红色 | 错误信息 |
debug | logger.debug() | 蓝色 | 调试信息 |
verbose | logger.verbose() | 灰色 | 详细信息 |
3. 在 Controller 中使用 Logger
3.1 创建命名 Logger 实例
在 Controller 的 constructor 中创建私有的 Logger 实例,传入控制器名称作为上下文标识:
typescript
// user.controller.ts
import { Controller, Get } from '@nestjs/common';
import { Logger } from '@nestjs/common';
@Controller('user')
export class UserController {
// 创建私有 Logger 实例,传入控制器名称
private logger = new Logger(UserController.name);
constructor() {}
@Get()
getUsers() {
// 使用 Logger 打印日志
this.logger.log('请求 get users 成功');
this.logger.warn('This is a warning');
this.logger.error('This is an error');
return { users: [] };
}
}3.2 为什么要传入控制器名称?
Logger 构造函数的第一个参数为上下文名称(context),会打印在日志信息的前面,方便区分日志来源。
终端输出效果:
code
[Nest] 12345 - 03/30/2026, 8:00:00 AM LOG [UserController] 请求 get users 成功
[Nest] 12345 - 03/30/2026, 8:00:00 AM LOG [OrderController] 获取订单列表成功关键作用:当多个 Controller 都打印"请求成功"时,通过
[UserController]/[OrderController]前缀可以快速定位日志来源。
3.3 为什么不使用依赖注入?
typescript
// 不推荐依赖注入方式
constructor(private logger: Logger) {}
// 推荐:在 constructor 中直接实例化
private logger = new Logger(UserController.name);原因:
- 每个模块/控制器的日志名称不同,需要独立配置
- Logger 模块是全局独立的,不依赖其他服务
- 直接实例化为私有属性,各模块互不干扰,更直观
相当于每个 Controller 持有一个局部的、私有的日志实例,这种设计更符合直觉。
4. 关闭 TypeORM 日志(可选)
如果项目中使用了 TypeORM,它会自动输出大量 SQL 日志,可以通过配置关闭:
typescript
// app.module.ts
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '123456',
database: 'test',
// 关闭 TypeORM SQL 日志输出
logging: false,
// 或者只输出错误日志
// logging: ['error', 'warn'],
entities: [],
synchronize: true,
}),
],
})
export class AppModule {}5. 内置 Logger 的局限性
| 特性 | 内置 Logger | 第三方日志库(如 Winston) |
|---|---|---|
| 输出位置 | 仅 Console | Console + File + Database |
| 日志持久化 | 不支持 | 支持 |
| 日志格式自定义 | 有限 | 完全自定义 |
| 日志文件管理 | 不支持 | 文件轮转、分割 |
| 传输通道 | 仅终端 | 多通道(文件、HTTP、数据库等) |
| 适用场景 | 开发调试 | 生产环境 |
结论:如果没有将日志写入文件或数据库的需求,内置 Logger 已足够。生产环境推荐使用 Winston 等第三方库。
代码实战案例
需求描述
在 NestJS 项目的 main.ts 和 UserController 中使用内置 Logger,设置日志等级,体验不同等级的颜色输出。
完整实现
main.ts:
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { Logger, ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
// 设置日志等级:只输出 error、warn、log
logger: ['error', 'warn', 'log'],
});
// 创建命名 Logger
const logger = new Logger('Bootstrap');
// 全局管道
app.useGlobalPipes(new ValidationPipe());
const port = 3000;
await app.listen(port);
// 启动日志
logger.log(`Application is running on: http://localhost:${port}`);
logger.warn(`Environment: ${process.env.NODE_ENV || 'development'}`);
}
bootstrap();user.controller.ts:
typescript
// user.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Controller('user')
export class UserController {
// 传入 UserController.name 作为上下文名称
private logger = new Logger(UserController.name);
constructor(private configService: ConfigService) {}
@Get()
getUsers() {
this.logger.log('请求 get users 成功');
return { users: [] };
}
@Post()
createUser(@Body() body: any) {
this.logger.log(`创建用户: ${JSON.stringify(body)}`);
this.logger.warn('密码未加密存储');
return { success: true };
}
}终端输出效果:
code
[Nest] 12345 - 03/30/2026, 8:00:00 AM LOG [Bootstrap] Application is running on: http://localhost:3000
[Nest] 12345 - 03/30/2026, 8:00:00 AM LOG [Bootstrap] Environment: development
[Nest] 12345 - 03/30/2026, 8:01:00 AM LOG [UserController] 请求 get users 成功
[Nest] 12345 - 03/30/2026, 8:02:00 AM LOG [UserController] 创建用户: {"name":"test"}
[Nest] 12345 - 03/30/2026, 8:02:00 AM LOG [UserController] 密码未加密存储常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 日志没有输出 | logger: false 或日志等级不匹配 | 设置 logger: true 或确认等级在数组中 |
TypeScript 报错 logger 类型不对 | 传入了非 LogLevel 的值 | Cmd/Ctrl + Click 查看类型定义,只使用合法值 |
| 不知道日志来自哪个 Controller | 未传入上下文名称 | 使用 new Logger(ControllerName.name) |
| TypeORM SQL 日志太多 | TypeORM 默认开启 logging | 设置 logging: false |
| Logger 不是通过依赖注入的 | Logger 是独立模块,推荐直接实例化 | 使用 private logger = new Logger(name) |
学习要点总结
NestFactory.create()的logger参数:控制全局日志开关和等级,false关闭,数组指定等级- TypeScript 类型提示:
Cmd/Ctrl + Click查看定义,快速了解可用的LogLevel类型 - Logger 使用方式:
new Logger(context)直接实例化,不使用依赖注入,每个 Controller 持有私有实例 - 上下文名称的重要性:通过
new Logger(UserController.name)标识日志来源,便于多模块区分 - 内置 Logger 的定位:适用于开发调试,仅 Console 输出;生产环境需 Winston 等第三方库实现持久化
延伸学习资源
官方文档
后续课程预告
- Winston 日志库:功能强大的第三方日志库,支持多传输通道
- 日志持久化:将日志写入文件,实现文件轮转管理
- 自定义 Logger:重写内置 Logger 的方法,实现自定义格式
内置 Logger 最佳实践
code
推荐:
- 在 main.ts 中设置日志等级 logger: ['error', 'warn', 'log']
- 使用 new Logger(ControllerName.name) 创建命名实例
- 开发阶段:logger: true(全开)
- 调试完成:logger: ['error', 'warn'](只保留重要日志)
避免:
- 依赖注入方式使用 Logger
- 忘记传入上下文名称
- 生产环境打印 debug 和 verbose 级别日志