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

@nest-packages/nestjs-trace-logger

v0.2.0

Published

一个功能强大的 NestJS 日志追踪包,提供完整的 traceId 支持、上下文管理和自定义格式化功能。

Readme

@nest-packages/nestjs-trace-logger

一个功能强大的 NestJS 日志追踪包,提供完整的 traceId 支持、上下文管理和自定义格式化功能。

特性

  • 完全继承 NestJS Logger - 保持所有原生功能,API 完全兼容
  • 自动 traceId 注入 - 使用 AsyncLocalStorage 自动在异步调用链中传递 traceId
  • 支持 LogLevel 配置 - 兼容 getLogLevels 函数,支持生产/开发环境不同日志级别
  • 自定义格式化器 - 支持默认、SLS、JSON 等多种格式化方式
  • 中间件和拦截器 - 开箱即用的 TraceMiddleware 和 TraceInterceptor
  • 类型安全 - 完整的 TypeScript 类型定义
  • 零配置 - 默认配置即可使用,也支持深度自定义

安装

npm install @nest-packages/nestjs-trace-logger
# 或
pnpm add @nest-packages/nestjs-trace-logger
# 或
yarn add @nest-packages/nestjs-trace-logger

依赖要求

  • @nestjs/common: ^11.0.0
  • @nestjs/core: ^11.0.0
  • uuid: ^9.0.0
  • fast-safe-stringify: ^2.1.0

快速开始

1. 在 main.ts 中配置

import { NestFactory } from '@nestjs/core';
import {
  TraceConsoleLogger,
  TraceMiddleware,
  TraceInterceptor,
} from '@nest-packages/nestjs-trace-logger';
import { AppModule } from './app.module';

function getLogLevels(isProduction: boolean): LogLevel[] {
  if (isProduction) {
    return ['warn', 'error', 'log'];
  }
  return ['error', 'warn', 'log', 'verbose', 'debug'];
}

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: new TraceConsoleLogger({
      logLevels: getLogLevels(process.env.NODE_ENV === 'production'),
      compact: true,
      json: false,
      colors: true,
    }),
  });

  // 注册 Trace 中间件(在健康检查之后)
  const traceMiddleware = new TraceMiddleware();
  app.use((req, res, next) => traceMiddleware.use(req, res, next));

  // 注册 Trace 拦截器
  app.useGlobalInterceptors(new TraceInterceptor());

  await app.listen(3000);
}
bootstrap();

2. 在服务中使用

import { Injectable } from '@nestjs/common';
import { TraceLogger } from '@nest-packages/nestjs-trace-logger';

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

  async doSomething() {
    // 自动注入 traceId,支持对象上下文
    this.logger.log('操作完成', { userId: 123, action: 'create' });

    // 支持 NestJS Logger 的所有方法
    this.logger.debug('调试信息');
    this.logger.warn('警告信息');
    this.logger.error('错误信息', 'stack trace');
  }
}

API 文档

TraceContextService

用于管理请求上下文和 traceId 的服务类。

import { TraceContextService } from '@nest-packages/nestjs-trace-logger';

// 获取当前 traceId
const traceId = TraceContextService.getTraceId();

// 运行函数并设置 traceId(同步)
TraceContextService.run('trace-id-123', () => {
  // 在这个函数内部,traceId 自动可用
  const id = TraceContextService.getTraceId(); // 'trace-id-123'
});

// 运行函数并设置 traceId(异步)
await TraceContextService.runAsync('trace-id-123', async () => {
  // 异步函数内部,traceId 自动可用
  const id = TraceContextService.getTraceId(); // 'trace-id-123'
});

// 设置自定义上下文数据
TraceContextService.set('userId', 123);
const userId = TraceContextService.get<number>('userId'); // 123

// 获取完整上下文
const context = TraceContextService.getContext();

TraceLogger

完全继承 NestJS Logger 的日志类,自动注入 traceId。

import { TraceLogger } from '@nest-packages/nestjs-trace-logger';

// 创建实例
const logger = new TraceLogger('MyService');

// 使用默认格式化器
logger.log('消息', { key: 'value' });
// 输出: [traceId] 消息 | {"traceId":"abc123","key":"value"}

// 使用自定义格式化器
import { JsonFormatter } from '@nest-packages/nestjs-trace-logger';
logger.setFormatter(new JsonFormatter());
logger.log('消息', { key: 'value' });
// 输出: {"message":"消息","timestamp":"2024-01-01T00:00:00.000Z","traceId":"abc123","key":"value"}

TraceConsoleLogger

类似 ConsoleLogger,支持 LogLevel 配置。

import { TraceConsoleLogger, LogLevel } from '@nest-packages/nestjs-trace-logger';

const logger = new TraceConsoleLogger({
  logLevels: ['error', 'warn', 'log'] as LogLevel[],
  compact: true,
  json: false,
  colors: true,
  formatter: new SlsFormatter(), // 可选:自定义格式化器
});

TraceMiddleware

自动从请求头获取或生成 traceId 的中间件。

import { TraceMiddleware } from '@nest-packages/nestjs-trace-logger';

// 在 main.ts 中注册
const traceMiddleware = new TraceMiddleware();
app.use((req, res, next) => traceMiddleware.use(req, res, next));

功能:

  • x-request-id 请求头获取 traceId
  • 如果没有,自动生成 UUID 并截取前 8 位
  • 在响应头中设置 X-Request-ID
  • 使用 AsyncLocalStorage 存储上下文

TraceInterceptor

确保 NestJS 执行上下文中 traceId 可用的拦截器。

import { TraceInterceptor } from '@nest-packages/nestjs-trace-logger';

// 在 main.ts 中注册
app.useGlobalInterceptors(new TraceInterceptor());

格式化器

DefaultFormatter(默认)

格式:[traceId] message | {context}

import { DefaultFormatter } from '@nest-packages/nestjs-trace-logger';

const logger = new TraceLogger('MyService', new DefaultFormatter());
logger.log('操作完成', { userId: 123 });
// 输出: [abc123] 操作完成 | {"traceId":"abc123","userId":123}

SlsFormatter(阿里云 SLS)

适配阿里云 SLS 日志格式,traceId 包含在 context 中。

import { SlsFormatter } from '@nest-packages/nestjs-trace-logger';

const logger = new TraceLogger('MyService', new SlsFormatter());
logger.log('操作完成', { userId: 123 });
// 输出: 操作完成 | {"traceId":"abc123","userId":123}

JsonFormatter(JSON 格式)

输出完整的 JSON 格式日志。

import { JsonFormatter } from '@nest-packages/nestjs-trace-logger';

const logger = new TraceLogger('MyService', new JsonFormatter());
logger.log('操作完成', { userId: 123 });
// 输出: {"message":"操作完成","timestamp":"2024-01-01T00:00:00.000Z","traceId":"abc123","userId":123}

自定义格式化器

import { IFormatter, LogContext } from '@nest-packages/nestjs-trace-logger';

class CustomFormatter implements IFormatter {
  format(message: string, traceId?: string, context?: LogContext): string {
    return `[${traceId || 'N/A'}] ${message} - ${JSON.stringify(context || {})}`;
  }
}

const logger = new TraceLogger('MyService', new CustomFormatter());

高级用法

在队列任务中使用

import { TraceContextService } from '@nest-packages/nestjs-trace-logger';

@Processor('my-queue')
export class MyProcessor {
  @Process()
  async handle(job: Job) {
    const traceId = job.data.traceId || 'generated-id';
    
    await TraceContextService.runAsync(traceId, async () => {
      // 在这个异步函数中,traceId 自动可用
      const logger = new TraceLogger(MyProcessor.name);
      logger.log('处理任务', { jobId: job.id });
    });
  }
}

继承 TraceLogger 创建自定义 Logger

import { TraceLogger, LogContext } from '@nest-packages/nestjs-trace-logger';

export class AlarmLogger extends TraceLogger {
  constructor(context: string) {
    super(context);
  }

  log(message: string, context?: LogContext | string): void {
    if (context && typeof context === 'object') {
      super.log(message, context as LogContext);
    } else {
      super.log(message, context);
    }
  }
}

使用 LoggerManager

import { LoggerManager, TraceLogger } from '@nest-packages/nestjs-trace-logger';

// 设置自定义 Logger 工厂
LoggerManager.setLoggerFactory((context: string) => {
  return new TraceLogger(context, new SlsFormatter());
});

// 创建 Logger
const logger = LoggerManager.createLogger('MyService');

在模块配置中使用

import { TraceLogger } from '@nest-packages/nestjs-trace-logger';

@Module({
  imports: [
    SomeModule.forRootAsync({
      useFactory: () => ({
        loggerFactory: (context: string) => new TraceLogger(context),
      }),
    }),
  ],
})
export class AppModule {}

配置选项

TraceConsoleLoggerOptions

interface TraceConsoleLoggerOptions {
  /**
   * 日志级别数组
   * @example ['error', 'warn', 'log', 'verbose', 'debug']
   */
  logLevels?: LogLevel[];

  /**
   * 是否使用紧凑格式
   * @default false
   */
  compact?: boolean;

  /**
   * 是否输出 JSON 格式
   * @default false
   */
  json?: boolean;

  /**
   * 是否使用颜色
   * @default true
   */
  colors?: boolean;

  /**
   * 自定义格式化器
   */
  formatter?: IFormatter;
}

最佳实践

1. 日志级别配置

根据环境配置不同的日志级别:

function getLogLevels(isProduction: boolean): LogLevel[] {
  if (isProduction) {
    return ['warn', 'error', 'log'];
  }
  return ['error', 'warn', 'log', 'verbose', 'debug'];
}

2. 在异步操作中保持 traceId

使用 TraceContextService.runAsync 确保异步操作中 traceId 可用:

await TraceContextService.runAsync(traceId, async () => {
  // 所有异步操作都会自动包含 traceId
  await someAsyncOperation();
  await anotherAsyncOperation();
});

3. 使用对象上下文

传递结构化数据而不是字符串拼接:

// ✅ 推荐
logger.log('用户登录', { userId: 123, ip: '192.168.1.1' });

// ❌ 不推荐
logger.log(`用户登录: userId=${userId}, ip=${ip}`);

4. 错误日志记录

try {
  // 业务逻辑
} catch (error) {
  logger.error('操作失败', { 
    error: error.message,
    stack: error.stack,
    userId: 123 
  });
}

类型定义

// TraceContext
interface TraceContext {
  traceId: string;
  startTime: number;
  [key: string]: any;
}

// LogContext
type LogContext = Record<string, unknown>;

// ILogger
interface ILogger {
  log(message: string, ...context: any[]): void;
  debug(message: string, ...context: any[]): void;
  warn(message: string, ...context: any[]): void;
  error(message: string, ...context: any[]): void;
}

// IFormatter
interface IFormatter {
  format(message: string, traceId?: string, context?: LogContext): string;
}

许可证

MIT

贡献

欢迎提交 Issue 和 Pull Request!

相关链接