NestJS第三方日志模块Pino学习笔记
NestJS第三方日志模块Pino学习笔记
核心知识点
1. NestJS 第三方日志库推荐
NestJS 内置 Logger 仅支持 Console 输出,生产环境需要更强大的第三方日志库:
| 日志库 | 说明 | 特点 |
|---|---|---|
| Pino | 本节重点 | 性能最高,NestJS 官方推荐 |
| Winston | 另一主流选择 | 功能全面,社区活跃,传输通道丰富 |
Pino 以极高的性能著称,是 Node.js 生态中速度最快的日志库之一。
2. Pino 核心包介绍
2.1 包概览
bash
pnpm install pino-http pino-pretty pino-roll| 包名 | 作用 | 使用阶段 |
|---|---|---|
pino-http | HTTP 请求日志中间件,记录请求/响应信息 | 全部阶段 |
pino-pretty | 日志格式化,彩色输出,便于开发查看 | 开发阶段 |
pino-roll | 日志文件滚动(按时间/大小自动分割) | 生产阶段 |
2.2 三包关系图
code
pino-http(核心中间件)
│
├── 开发环境 → pino-pretty(美化输出到控制台)
│
└── 生产环境 → pino-roll(写入日志文件,自动滚动)3. 开发环境:pino-pretty 美化日志
3.1 基础配置
typescript
// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { LoggerModule } from 'nestjs-pino';
import pino from 'pino';
import { join } from 'path';
@Module({
imports: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(
pino-http({
transport: {
target: 'pino-pretty',
options: {
colorize: true, // 彩色输出
},
},
}),
).forRoutes('*');
}
}3.2 pino-pretty 输出效果
使用 pino-pretty 后,终端输出从压缩的单行 JSON 变为格式化的彩色日志:
code
// 不使用 pino-pretty(丑陋的压缩 JSON)
{"level":30,"time":1711756800000,"req":{"method":"GET","url":"/api/v1/user"},"res":{"statusCode":200},"responseTime":12}
// 使用 pino-pretty(美观的格式化输出)
[1711756800000] INFO (user): GET /api/v1/user
req: { method: "GET", url: "/api/v1/user", cookies: "..." }
res: { statusCode: 200 }
responseTime: 12ms3.3 根据环境切换输出方式
生产环境不使用 pino-pretty,因为它会降低性能。仅在开发环境使用美化输出。
typescript
// 根据环境动态决定 transport 目标
const transportTarget =
process.env.NODE_ENV === 'development'
? 'pino-pretty' // 开发:美化输出
: 'pino-roll'; // 生产:文件滚动记录4. 生产环境:pino-roll 文件滚动
4.1 pino-roll 简介
- 功能:自动按规则将日志写入文件,支持按时间周期或文件大小滚动分割
- 官网描述:"A pino transport that automatically rolls your log file"
- 使用场景:生产环境日志持久化
4.2 安装
bash
pnpm install pino-roll4.3 滚动方式:按时间周期(frequency)
typescript
pino-http({
transport: {
target: 'pino-roll',
options: {
file: join(__dirname, '..', 'logs', 'log.txt'),
frequency: 'daily', // 每天滚动一个文件
mkdir: true, // 自动创建 logs 目录
},
},
})frequency 可选值:
| 值 | 说明 | 生成文件示例 |
|---|---|---|
'daily' | 每天一个文件 | log.txt.2026-03-30 |
'hourly' | 每小时一个文件 | log.txt.2026-03-30T08 |
4.4 滚动方式:按文件大小(size)
typescript
pino-http({
transport: {
target: 'pino-roll',
options: {
file: join(__dirname, '..', 'logs', 'log.txt'),
size: '10M', // 每个文件最大 10MB
mkdir: true,
},
},
})size 格式:以
K或M结尾,如'0.1K'(测试用)、'10M'(生产推荐)。
4.5 两种滚动方式对比
| 方式 | 参数 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| 按时间 | frequency: 'daily' | 日志量稳定 | 按天查找方便 | 文件大小不固定 |
| 按大小 | size: '10M' | 日志量波动大 | 文件大小可控,便于打开 | 查找需跨文件 |
推荐:生产环境通常设置为
10M一个文件,10MB 的文本文件可以正常打开,便于排查问题。
5. targets 多目标输出
5.1 同时输出到控制台和文件
transport.targets 支持数组形式,同时配置多个输出目标:
typescript
pino-http({
transport: {
targets: [
// 目标一:控制台美化输出(开发环境)
{
target: 'pino-pretty',
options: {
colorize: true,
},
level: 'info',
},
// 目标二:文件滚动记录
{
target: 'pino-roll',
options: {
file: join(__dirname, '..', 'logs', 'log.txt'),
frequency: 'daily',
mkdir: true,
},
level: 'info',
},
],
},
})每个目标可以单独设置
level,实现不同目标输出不同等级的日志。
6. 全局注册中间件
6.1 放置位置选择
| 位置 | 效果 | 推荐 |
|---|---|---|
在某个 Module 的 configure() 中 | 仅该 Module 生效 | 不推荐 |
在 AppModule 的 configure() 中 | 全局所有路由生效 | 推荐 |
6.2 全局注册示例
typescript
// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { join } from 'path';
import pinoHttp from 'pino-http';
@Module({
imports: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
// 全局启用 pino-http 日志中间件
consumer.apply(
pinoHttp({
transport: {
targets: [
{
target: 'pino-pretty',
options: { colorize: true },
level: 'info',
},
{
target: 'pino-roll',
options: {
file: join(__dirname, '..', 'logs', 'log.txt'),
frequency: 'daily',
mkdir: true,
},
level: 'info',
},
],
},
}),
).forRoutes('*'); // 匹配所有路由
}
}代码实战案例
需求描述
在 NestJS 项目中集成 Pino 日志,开发环境使用 pino-pretty 美化输出,生产环境使用 pino-roll 文件滚动记录,全局生效。
完整实现
第一步:安装依赖
bash
pnpm install pino-http pino-pretty pino-roll第二步:配置 AppModule
typescript
// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { join } from 'path';
import pinoHttp from 'pino-http';
import { UserModule } from './user/user.module';
@Module({
imports: [UserModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(
pinoHttp({
transport: {
targets: [
// 目标一:控制台美化输出
{
target: 'pino-pretty',
options: {
colorize: true,
},
level: 'info',
},
// 目标二:日志文件滚动记录
{
target: 'pino-roll',
options: {
file: join(__dirname, '..', 'logs', 'log.txt'),
frequency: 'daily',
mkdir: true,
},
level: 'info',
},
],
},
}),
).forRoutes('*');
}
}第三步:启动并测试
bash
pnpm start:dev第四步:发送请求,查看日志
bash
# GET 请求
curl http://localhost:3000/api/v1/user
# POST 请求
curl -X POST http://localhost:3000/api/v1/user -H "Content-Type: application/json" -d '{"name":"test"}'控制台输出(pino-pretty 美化):
code
[1711756800000] INFO GET /api/v1/user
req: { method: "GET", url: "/api/v1/user" }
res: { statusCode: 200 }
responseTime: 12ms
[1711756801000] INFO POST /api/v1/user
req: { method: "POST", url: "/api/v1/user", body: { name: "test" } }
res: { statusCode: 201 }
responseTime: 25ms日志文件(logs/log.txt,原始 JSON 格式):
code
{"level":30,"time":1711756800000,"req":{"method":"GET","url":"/api/v1/user"},"res":{"statusCode":200},"responseTime":12}
{"level":30,"time":1711756801000,"req":{"method":"POST","url":"/api/v1/user"},"res":{"statusCode":201},"responseTime":25}文件中记录的是原始 JSON,虽然没有美化,但便于后续日志分析工具解析和回溯。
常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 生产环境日志性能下降 | 使用了 pino-pretty | 生产环境使用 pino-roll,仅开发环境使用 pino-pretty |
| logs 目录不存在报错 | 未设置 mkdir: true | 在 pino-roll options 中添加 mkdir: true |
| 文件滚动未生效 | frequency 或 size 未设置 | 设置 frequency: 'daily' 或 size: '10M' |
| 日志文件太大无法打开 | 文件大小设置不合理 | 设置 size: '10M',10MB 文件可正常打开 |
| 日志只在某个 Module 生效 | 中间件注册在子 Module 中 | 将中间件注册到 AppModule 的 configure() 中 |
学习要点总结
- Pino 三件套:
pino-http(核心中间件)+pino-pretty(开发美化)+pino-roll(生产文件滚动) - 环境区分:开发环境用
pino-pretty美化输出,生产环境用pino-roll文件记录 - 滚动方式:
frequency: 'daily'(按天)或size: '10M'(按大小),推荐 10MB 一文件 - targets 多目标:可同时输出到控制台和文件,每个目标可设置不同日志等级
- 全局注册:在
AppModule.configure()中使用forRoutes('*')全局生效
延伸学习资源
官方文档
后续课程预告
- Winston 日志库:另一主流日志库,支持更多传输通道
- ELK Stack 集成:日志收集 + 存储 + 可视化分析
- 日志告警:基于错误日志自动触发告警通知
生产环境日志最佳实践
code
推荐配置方案:
├── 控制台:pino-pretty(仅开发环境)
├── 文件记录:pino-roll + daily(生产环境)
│ └── logs/log.txt.2026-03-30
├── 文件大小:10MB 滚动
├── 日志格式:JSON(便于日志分析工具解析)
└── 日志级别:info 及以上(error、warn、log)