{T}

NestJS内置日志模块使用学习笔记

核心知识点

1. NestJS 日志开关控制

1.1 关闭全局日志

main.tsNestFactory.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 日志输出颜色区分

不同日志等级在终端中显示不同的颜色,便于快速识别:

等级方法终端颜色用途
loglogger.log()绿色通用信息
warnlogger.warn()黄色警告提示
errorlogger.error()红色错误信息
debuglogger.debug()蓝色调试信息
verboselogger.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);

原因

  1. 每个模块/控制器的日志名称不同,需要独立配置
  2. Logger 模块是全局独立的,不依赖其他服务
  3. 直接实例化为私有属性,各模块互不干扰,更直观

相当于每个 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)
输出位置仅 ConsoleConsole + File + Database
日志持久化不支持支持
日志格式自定义有限完全自定义
日志文件管理不支持文件轮转、分割
传输通道仅终端多通道(文件、HTTP、数据库等)
适用场景开发调试生产环境

结论:如果没有将日志写入文件或数据库的需求,内置 Logger 已足够。生产环境推荐使用 Winston 等第三方库。


代码实战案例

需求描述

在 NestJS 项目的 main.tsUserController 中使用内置 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)

学习要点总结

  1. NestFactory.create()logger 参数:控制全局日志开关和等级,false 关闭,数组指定等级
  2. TypeScript 类型提示Cmd/Ctrl + Click 查看定义,快速了解可用的 LogLevel 类型
  3. Logger 使用方式new Logger(context) 直接实例化,不使用依赖注入,每个 Controller 持有私有实例
  4. 上下文名称的重要性:通过 new Logger(UserController.name) 标识日志来源,便于多模块区分
  5. 内置 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 级别日志