npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lark-apaas/nestjs-logger

v1.0.13

Published

Nestjs Logger

Readme

NestJS Logger

基于 Pino 的高性能 NestJS 日志库,支持请求追踪和结构化日志。

功能特性

  • 基于 Pino 的高性能日志记录
  • 自动 HTTP 请求追踪(双层日志:info 链路日志 + verbose 详细日志)
  • 请求和响应体日志记录(可配置)
  • 支持多日志级别
  • 独立的 trace 日志文件
  • 请求上下文传递
  • 日志体长度截断
  • 完美兼容 Exception Filter
    • 拦截 response.json()response.send() 方法
    • 能够捕获 Exception Filter 改写的响应体和最终状态码
    • 确保异常日志的完整性和准确性

安装

npm install @lark-apaas/nestjs-logger

基本使用

1. 导入模块

import { Module } from '@nestjs/common';
import { LoggerModule } from '@lark-apaas/nestjs-logger';

@Module({
  imports: [LoggerModule],
})
export class AppModule {}

2. 使用 Logger(完全兼容 NestJS 官方 API)

本库完全遵循 NestJS 官方 Logger API,无缝替换官方 Logger。

import { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class MyService {
  private readonly logger = new Logger(MyService.name);

  doSomething() {
    // 简单日志
    this.logger.log('This is an info log');

    // 带 context 的日志(最后一个参数)
    this.logger.log('User logged in', 'AuthModule');
    //                                ↑ context

    // 多个参数会用空格连接
    this.logger.log('User', userId, 'logged in from', ip);
    // 输出: User 123 logged in from 192.168.1.1

    // 使用模板字符串
    this.logger.log(`User ${userId} logged in from ${ip}`);

    // 多参数 + context
    this.logger.log('Processing order', orderId, 'OrderService');
    //                                             ↑ context
  }

  handleError() {
    try {
      // 业务逻辑
    } catch (error) {
      // Error 日志 + stack trace(官方推荐方式)
      this.logger.error('Failed to process', error.stack);
      //                                     ↑ 第一个参数自动识别为 stack

      // Error + stack + context
      this.logger.error('Payment failed', error.stack, 'PaymentService');
      //                                  ↑ stack      ↑ context
    }
  }
}

参数规则(与 NestJS 官方一致)

  • 最后一个字符串参数:自动识别为 context
  • Error/Fatal 方法的第一个参数:如果是 stack trace 格式,自动识别为 stack
  • 多个参数:会用空格连接成一个字符串
  • 不支持格式化占位符:不支持 %s, %d, %o 等占位符,请使用模板字符串

3. 使用 logStructured 记录结构化日志(扩展功能)

除了标准的 Logger API,本库还提供了 logStructured() 方法用于记录结构化日志:

import { Inject, Injectable } from '@nestjs/common';
import { AppLogger } from '@lark-apaas/nestjs-logger';

@Injectable()
export class MyService {
  constructor(
    @Inject(AppLogger) private readonly logger: AppLogger,
  ) {}

  doSomething() {
    // 使用 logStructured 记录结构化日志
    this.logger.logStructured(
      'log',  // 日志级别
      'User action completed',  // 消息
      {  // 元数据对象(会合并到日志字段中)
        action: 'create_order',
        order_id: '123',
        amount: 100,
      },
      'MyService',  // context(可选)
    );
  }
}

两种方式对比

| 特性 | 标准 Logger API | logStructured API | |------|----------------|-------------------| | 用途 | 常规日志,兼容 NestJS 官方 | 结构化日志,将 meta 合并到字段 | | Context | 最后一个参数自动识别 | 显式传递第4个参数 | | 消息格式 | 使用模板字符串拼接 | 纯文本消息 | | 元数据 | 需要手动拼接到消息中 | 作为独立字段存储,便于查询 | | 使用场景 | 日常日志、错误日志 | 需要结构化查询的业务日志 |

环境变量配置

基础配置

# 日志级别: trace, debug, info, warn, error, fatal, silent
# 注意:HTTP 请求追踪日志使用 verbose 级别(对应 Pino 的 trace)
# 生产环境默认为 info,不会打印 verbose 级别的日志
LOGGER_LEVEL=info

# 日志目录
LOG_DIR=logs

# Node 环境(默认:开发环境使用 debug,生产环境使用 info)
NODE_ENV=production

请求/响应体日志配置

# 启用请求体日志(默认:false)
LOG_REQUEST_BODY=true

# 启用响应体日志(默认:false)
LOG_RESPONSE_BODY=true

# 注意:即使启用了请求/响应体日志,也需要将日志级别设置为 verbose 才能实际输出
# 因为 HTTP 请求追踪日志使用的是 verbose 级别
LOGGER_LEVEL=verbose

# 日志体最大长度,超过会截断(默认:不限制)
# 不设置此环境变量时,不会进行截断
LOG_MAX_BODY_LENGTH=10000

请求/响应体日志

日志级别说明

HTTP 请求追踪日志使用 verbose 级别(对应 Pino 的 trace 级别),这意味着:

  • 生产环境默认不打印:生产环境默认日志级别为 info,不会输出 verbose 级别的日志
  • 需要显式启用:要查看 HTTP 请求追踪日志,需要将 LOGGER_LEVEL 设置为 verbose
  • 细粒度控制:可以通过日志级别控制是否打印请求追踪,而无需修改 LOG_REQUEST_BODYLOG_RESPONSE_BODY 配置

响应体记录规则

只针对 JSON 响应记录 body

  • 自动检测 Content-Type 是否包含 application/json
  • 只有 JSON 响应才会记录 response_body 字段
  • 文件下载、HTML 页面等非 JSON 响应不会记录 body,避免日志污染
  • 这样可以显著减少日志体积,同时保持日志的可读性

启用方式

通过环境变量启用:

# 方式一:仅启用 HTTP 请求追踪(不包含 body)
LOGGER_LEVEL=verbose

# 方式二:启用 HTTP 请求追踪 + 请求/响应体
LOGGER_LEVEL=verbose
LOG_REQUEST_BODY=true
LOG_RESPONSE_BODY=true

重要说明

  1. 双层日志机制

    • info 级别:始终记录基础链路日志(不含 body),用于生产环境请求追踪
    • verbose 级别:记录详细追踪日志(包含 body),用于开发调试
  2. 默认不限制长度:如果不设置 LOG_MAX_BODY_LENGTH 环境变量,日志体不会被截断。建议在生产环境设置合理的限制值。

  3. 响应体过滤

    • 只记录 JSON 响应的 body(检测 Content-Type)
    • 文件下载、HTML、图片等非 JSON 响应不会记录 body
    • 避免记录无法序列化的数据(如 Buffer、Stream)
    • 显著减少日志体积,提高日志可读性

日志输出示例

Info 级别(链路日志)

{
  "level": "INFO",
  "time": 1234567890,
  "msg": "HTTP request started",
  "method": "GET",
  "path": "/api/users",
  "trace_id": "req-123-456",
  "user_id": "user-001",
  "tenant_id": 24020896,
  "app_id": "",
  "context": "HTTPTraceInterceptor"
}
{
  "level": "INFO",
  "time": 1234567890,
  "msg": "HTTP request completed",
  "method": "GET",
  "path": "/api/users",
  "trace_id": "req-123-456",
  "status_code": 200,
  "duration_ms": 125,
  "context": "HTTPTraceInterceptor"
}

Verbose 级别(详细追踪日志)

{
  "level": "TRACE",
  "time": 1234567890,
  "msg": "HTTP request started",
  "method": "POST",
  "path": "/api/users",
  "trace_id": "req-123-456",
  "request_body": {
    "username": "john_doe",
    "email": "[email protected]",
    "password": "secret123"
  },
  "query_params": {
    "filter": "active"
  },
  "context": "HTTPTraceInterceptor"
}
{
  "level": "TRACE",
  "time": 1234567890,
  "msg": "HTTP request completed",
  "method": "POST",
  "path": "/api/users",
  "trace_id": "req-123-456",
  "status_code": 201,
  "duration_ms": 125,
  "response_body": {
    "id": "user-123",
    "username": "john_doe",
    "email": "[email protected]"
  },
  "context": "HTTPTraceInterceptor"
}

数据截断

默认情况下,不会对日志体进行截断。当设置 LOG_MAX_BODY_LENGTH 环境变量后,如果请求/响应体超过指定长度,会自动截断:

{
  "response_body": {
    "_truncated": true,
    "_originalLength": 50000,
    "_data": "{ 前 10000 个字符... }..."
  }
}

建议:在生产环境设置合理的限制值(如 10000),避免单条日志过大。

日志级别映射

NestJS LoggerService 级别到 Pino 级别的映射:

  • fatalfatal
  • errorerror
  • warnwarn
  • loginfo
  • debugdebug
  • verbosetrace

日志文件

日志会写入以下文件(默认在 logs/ 目录):

  • server.log - 应用日志
  • trace.log - HTTP 请求追踪日志

注意事项

架构设计

  1. Exception Filter 兼容性

    • 使用 response.on('finish') 事件记录日志,确保在响应完全发送后才记录
    • 拦截 response.json()response.send() 方法,捕获最终发送的响应体
    • 能够正确捕获全局 Exception Filter 设置的最终状态码和响应体
    • 日志记录发生在 NestJS 请求生命周期的最后阶段,确保信息完整准确
  2. 请求生命周期

    Middleware → Guards → Interceptor (before) → Pipes → Controller
        ↓
    Interceptor (after/catchError) → Exception Filters → Response Finish (✅ 日志记录)
  3. 实现原理

    • 拦截响应方法:在 Interceptor 中拦截 res.json()res.send(),存储响应体到 res.__finalResponseBody
    • 类型检测:通过 Content-Type header 判断是否为 JSON 响应,只记录 JSON 类型的 body
    • 延迟记录:不在 Interceptor 的 tap()catchError() 中记录日志,而是在 finish 事件中统一记录
    • 完整信息:此时可以获取 Exception Filter 处理后的最终状态码和响应体,确保日志准确性
  4. Logger API 兼容性

    • 完全兼容 NestJS 官方:实现与 @nestjs/common 的 Logger 完全一致的 API
    • 参数解析规则
      • 最后一个字符串参数自动识别为 context
      • Error/Fatal 方法的第一个参数如果是 stack trace 格式,自动识别为 stack
    • 无缝替换:可以直接替换项目中的官方 Logger,无需修改业务代码
    • 扩展功能:提供 logStructured() 方法用于结构化日志场景

安全性

  1. 生产环境默认不打印 HTTP 追踪日志:由于使用 verbose 级别,生产环境(info 级别)默认不会输出详细日志
  2. 双层日志设计:info 级别始终记录链路日志,verbose 级别记录详细信息,按需启用
  3. 按需启用:需要查看详细追踪时,将 LOGGER_LEVEL 设置为 verbose
  4. 敏感数据处理:日志库不提供脱敏功能,请在业务层或通过中间件处理敏感数据

性能

  1. verbose 级别会输出所有 HTTP 请求详细日志,可能影响性能
  2. 开启请求/响应体日志会增加日志体积和 I/O 开销
  3. 大对象的序列化会影响性能
  4. 建议在开发/测试环境使用,生产环境按需临时启用

存储

  1. 开发环境默认启用日志轮转(基于 rotating-file-stream),活跃文件始终为 server.log,归档为 server.log.1(最新)→ server.log.N(最旧)
  2. 默认单文件 10MB,最多保留 5 个归档,总占用上限约 60MB
  3. 可通过环境变量控制轮转行为:LOG_ROTATION_ENABLEDLOG_ROTATION_MAX_SIZELOG_ROTATION_MAX_FILES
  4. verbose 级别 + 请求/响应体日志会显著增加日志量
  5. 建议设置 LOG_MAX_BODY_LENGTH 限制单条日志大小(默认不限制)

最佳实践

开发环境

NODE_ENV=development
# 使用 verbose 级别查看 HTTP 请求追踪
LOGGER_LEVEL=verbose
LOG_REQUEST_BODY=true
LOG_RESPONSE_BODY=true
# 开发环境可以不限制长度,或设置较大值
# LOG_MAX_BODY_LENGTH=50000

生产环境

NODE_ENV=production
# 生产环境使用 info 级别,不会打印 HTTP 请求追踪日志
LOGGER_LEVEL=info
# 这两个配置可以保留,只有当 LOGGER_LEVEL=verbose 时才会生效
LOG_REQUEST_BODY=false
LOG_RESPONSE_BODY=false

故障排查

临时启用详细日志:

NODE_ENV=production
# 临时开启 verbose 级别查看 HTTP 请求追踪
LOGGER_LEVEL=verbose
LOG_REQUEST_BODY=true
LOG_RESPONSE_BODY=true
LOG_MAX_BODY_LENGTH=10000  # 建议设置限制,避免日志过大

License

MIT