feat(server): enable cls plugin to store request id (#9758)

POC
This commit is contained in:
fengmk2
2025-01-20 10:00:21 +00:00
parent fa5e6e1f45
commit 2ae05c28b7
7 changed files with 70 additions and 4 deletions
+1
View File
@@ -76,6 +76,7 @@
"nanoid": "^5.0.9",
"nest-commander": "^3.15.0",
"nest-winston": "^1.9.7",
"nestjs-cls": "^4.5.0",
"nestjs-throttler-storage-redis": "^0.5.1",
"nodemailer": "^6.9.16",
"on-headers": "^1.0.2",
+14
View File
@@ -1,3 +1,5 @@
import { randomUUID } from 'node:crypto';
import {
DynamicModule,
ForwardReference,
@@ -6,6 +8,7 @@ import {
} from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { get } from 'lodash-es';
import { ClsModule } from 'nestjs-cls';
import { AppController } from './app.controller';
import { getOptionalModuleMetadata } from './base';
@@ -42,6 +45,17 @@ import { REGISTERED_PLUGINS } from './plugins';
import { ENABLED_PLUGINS } from './plugins/registry';
export const FunctionalityModules = [
ClsModule.forRoot({
global: true,
middleware: {
mount: true,
generateId: true,
idGenerator() {
// make every request has a unique id to tracing
return randomUUID();
},
},
}),
ConfigModule.forRoot(),
RuntimeModule,
EventModule,
+2
View File
@@ -12,6 +12,7 @@ import {
import { SocketIoAdapter } from './base/websocket';
import { AuthGuard } from './core/auth';
import { ENABLED_FEATURES } from './core/config/server-feature';
import { responseRequestIdHeader } from './middleware/request-id';
import { serverTimingAndCache } from './middleware/timing';
export async function createApp() {
@@ -31,6 +32,7 @@ export async function createApp() {
}
app.use(serverTimingAndCache);
app.use(responseRequestIdHeader);
app.use(
graphqlUploadExpress({
@@ -1,6 +1,20 @@
import { ConsoleLogger, Injectable } from '@nestjs/common';
import { ConsoleLogger, Injectable, type LogLevel } from '@nestjs/common';
import { ClsServiceManager } from 'nestjs-cls';
// DO NOT use this Logger directly
// Use it via this way: `private readonly logger = new Logger(MyService.name)`
@Injectable()
export class AFFiNELogger extends ConsoleLogger {}
export class AFFiNELogger extends ConsoleLogger {
override stringifyMessage(message: unknown, logLevel: LogLevel) {
const messageString = super.stringifyMessage(message, logLevel);
const requestId = AFFiNELogger.getRequestId();
if (!requestId) {
return messageString;
}
return `<${requestId}> ${messageString}`;
}
static getRequestId(): string | undefined {
return ClsServiceManager.getClsService()?.getId();
}
}
@@ -0,0 +1,16 @@
import { NextFunction, Request, Response } from 'express';
import { ClsServiceManager } from 'nestjs-cls';
import onHeaders from 'on-headers';
export const responseRequestIdHeader = (
_req: Request,
res: Response,
next: NextFunction
) => {
onHeaders(res, () => {
const requestId = ClsServiceManager.getClsService().getId();
res.setHeader('X-Request-Id', requestId);
});
next();
};
@@ -1,22 +1,28 @@
import { LoggingWinston } from '@google-cloud/logging-winston';
import { LoggerService, Provider } from '@nestjs/common';
import { createLogger, transports } from 'winston';
import { createLogger, format, transports } from 'winston';
import { AFFiNELogger as LoggerProvide } from '../../../base/logger';
import { AFFiNELogger } from './logger';
const moreMetadata = format(info => {
info.requestId = LoggerProvide.getRequestId();
return info;
});
export const loggerProvider: Provider<LoggerService> = {
provide: LoggerProvide,
useFactory: () => {
const loggingWinston = new LoggingWinston();
// Create a Winston logger that streams to Cloud Logging
const instance = createLogger({
level: 'log',
level: 'info',
transports: [
new transports.Console(),
// Add Cloud Logging
loggingWinston,
],
format: format.combine(moreMetadata(), format.json()),
});
return new AFFiNELogger(instance);
},
+13
View File
@@ -838,6 +838,7 @@ __metadata:
nanoid: "npm:^5.0.9"
nest-commander: "npm:^3.15.0"
nest-winston: "npm:^1.9.7"
nestjs-cls: "npm:^4.5.0"
nestjs-throttler-storage-redis: "npm:^0.5.1"
nodemailer: "npm:^6.9.16"
nodemon: "npm:^3.1.7"
@@ -27239,6 +27240,18 @@ __metadata:
languageName: node
linkType: hard
"nestjs-cls@npm:^4.5.0":
version: 4.5.0
resolution: "nestjs-cls@npm:4.5.0"
peerDependencies:
"@nestjs/common": "> 7.0.0 < 11"
"@nestjs/core": "> 7.0.0 < 11"
reflect-metadata: "*"
rxjs: ">= 7"
checksum: 10/cbd807244aaf0e89480e5fa7d08415e27953d4f6264246318cd3aa5ec4817564988d5cbed4f700c79090f0ded6f72752887bc842543f7f0af49c515df41e937e
languageName: node
linkType: hard
"nestjs-throttler-storage-redis@npm:^0.5.1":
version: 0.5.1
resolution: "nestjs-throttler-storage-redis@npm:0.5.1"