You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中如何在Pino中间件外部获取请求ID(reqId)

获取请求ID并存入数据库的两种方案

方案一:直接从请求对象传递reqId

这种方法简单直接,通过控制器把请求对象中的reqId传递给服务层。

1. 修改控制器,传递reqId

import { Controller, Post, Req } from '@nestjs/common';
import { MyService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly myService: MyService) {}

  @Post('activity')
  async createActivity(@Req() req) {
    // pino会把genReqId生成的ID挂载到req.id上
    await this.myService.saveActivity(req.id);
  }
}

2. 服务层接收并使用reqId

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

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

  async saveActivity(requestId: string) {
     this.logger.log("saving user activity");
     // 将reqId存入数据库字段
     await userActivityRepo.save({ ...rest, request_id: requestId });
  }
}

方案二:使用AsyncLocalStorage全局共享reqId

如果不想在控制器和服务层之间显式传递reqId,可以用NestJS的AsyncLocalStorage(ALS)在整个请求链路中共享reqId。

1. 创建ALS服务

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

@Injectable()
export class AlsService {
  private readonly als = new AsyncLocalStorage();

  runWithId(id: string, callback: () => void) {
    return this.als.run({ requestId: id }, callback);
  }

  getRequestId(): string {
    return this.als.getStore()?.requestId;
  }
}

2. 编写中间件存入reqId到ALS

import { Injectable, NestMiddleware } from '@nestjs/common';
import { AlsService } from '../als/als.service';

@Injectable()
export class RequestIdMiddleware implements NestMiddleware {
  constructor(private readonly alsService: AlsService) {}

  use(req: any, res: any, next: () => void) {
    // 从请求对象获取pino生成的reqId
    const requestId = req.id;
    // 将reqId存入ALS,后续链路可全局访问
    this.alsService.runWithId(requestId, next);
  }
}

3. 在模块中注册中间件和ALS服务

import { Module, MiddlewareConsumer } from '@nestjs/common';
import { LoggerModule } from 'nestjs-pino';
import { v4 as uuid } from 'uuid';
import { AlsService } from './als/als.service';
import { RequestIdMiddleware } from './middlewares/request-id.middleware';
import { MyService } from './app.service';
import { AppController } from './app.controller';

@Module({
  imports: [
    LoggerModule.forRoot({
      pinoHttp: {
        genReqId: (req: any) => {
          return req.headers.req_id || uuid();
        },
        base: undefined,
        quietReqLogger: true,
        timestamp: false,
      },
    }),
  ],
  controllers: [AppController],
  providers: [MyService, AlsService],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    // 全局应用中间件
    consumer.apply(RequestIdMiddleware).forRoutes('*');
  }
}

4. 服务层从ALS获取reqId

import { Injectable, Logger } from '@nestjs/common';
import { AlsService } from './als/als.service';

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

  constructor(private readonly alsService: AlsService) {}

  async saveActivity() {
     // 从ALS获取当前请求的reqId
     const requestId = this.alsService.getRequestId();
     this.logger.log("saving user activity");
     await userActivityRepo.save({ ...rest, request_id: requestId });
  }
}

内容的提问来源于stack exchange,提问作者Zain Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:02:53