NestJS:如何自定义日志消息,以包括请求id和日志消息发生的文件名



我是NestJS的新手,我想自定义日志消息,以包括x-request-id/x-correlation-id和日志消息产生的文件名,但不确定NestJS中是否有这样的功能。

我的应用程序正在将NestJS与Fastify适配器一起使用,并且在bootstrap((函数中有以下配置

const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
{
logger: WinstonModule.createLogger(winston.createLogger({
exitOnError: false,
level: 'debug',
handleExceptions: true,
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
winston.format.colorize(),
winston.format.align(),
winston.format.splat(),
winston.format.printf((info) => {
return `${info.timestamp} [ ${info.level} ] : ${info.message}`;
}),
),
transports: [
new (winston.transports.Console)()
]
}),
)
}
);

这似乎像预期的那样使用winston来格式化日志。

2022-03-09T11:21:22.131Z [ info ] : Starting Nest application...

然而,我也想在消息中包括请求/相关性id和日志消息发生的文件名,例如

2022-03-09T11:21:22.131Z 2cfd4eee-ca2b-4869-b66b-2b7da291f567 [ info ] [ Main.ts ]: Starting Nest application...

NestJS本身是否有任何东西可以允许我使用这个或任何外部库来实现所需的结果?

我设法使用嵌套的皮诺库:使其工作

// main.ts
import { Logger } from 'nestjs-pino';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
{ bufferLogs: true }
);
app.useLogger(app.get(Logger));

}
bootstrap();

// app.module.ts
import { LoggerModule } from 'nestjs-pino';
@Module({
imports: [
LoggerModule.forRoot({
pinoHttp: {
level: process.env.LOG_LEVEL || 'debug',
redact: ['request.headers.authorization'],
prettyPrint: {
colorize: true,
singleLine: true,
levelFirst: false,
translateTime: "yyyy-MM-dd'T'HH:mm:ss.l'Z'",
messageFormat: "{req.headers.x-correlation-id} [{context}] {msg}",
ignore: "pid,hostname,context,req,res,responseTime",
errorLikeObjectKeys: ['err', 'error']
}
}
}),
],
controllers: [MyController],
})
export class AppModule {}

// my.controller.ts
import { Controller, Get, Param, Logger } from '@nestjs/common';
@Controller()
export class MyController {
private readonly logger: Logger = new Logger(MyController.name);
@Get('/:id')
async getCustomerDetails(@Headers() headers, @Param('id') id: string): Promise<Customer> {
this.logger.log(`Accepted incoming request with id: ${id}`);
// Do some processing ....
return customer;
}
}

[2022-11-14T11:03:07.100Z] INFO: 428f0df9-d12b-4fca-9b11-805a13ff41be [MyController] Accepted incoming request with id: 1

******更新**********

我还设法更新了经过编辑的字段,使其可以从.yaml文件中进行配置

// app.module.ts
import { ConfigModule, ConfigService } from '@nestjs/config';
import { LoggerModule } from 'nestjs-pino';
@Module({
imports: [
LoggerModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
pinoHttp: {
level: process.env.LOG_LEVEL || 'info',
redact: configService.get<string[]>('logger.redacted.fields'),
prettyPrint: {
colorize: false,
singleLine: true,
levelFirst: false,
translateTime: "yyyy-mm-dd'T'HH:MM:ss.l'Z'",
messageFormat: '{req.headers.x-correlation-id} [{context}] {msg}',
ignore: 'pid,hostname,context,req,res,responseTime',
errorLikeObjectKeys: ['err', 'error'],
},
},
}),
inject: [ConfigService],
}),
],
controllers: [MyController],
})
export class AppModule {}

dev.yaml

logger:
redacted:
fields:
- 'headers.Authorization'
- 'headers["X-Api-Key"]'
  1. 分配一个请求ID。让它成为您的第一个middleware
  2. 将请求上下文与logger绑定。制作一个Logger类,将request context绑定到记录器。它将基本上充当WinstonLogger的包装器。覆盖winston logger的所有方法,以您想要的方式打印请求ID(首选方式是使用JSON,因为它更容易在日志中查询(

如果您使用的是winston,

使用来自winston的logFormatter为每个日志添加更多字段:-

下面的一个例子:

const { format} = require("winston");
var reqId = '123123' //function or const request id
const addRequestId = format((info, opts) => {
if(reqId)
info.reqId= reqId;
return info;
});

然后在创建记录器时添加以下配置

var config = {
format: format.combine(
addRequestId(),
format.timestamp(new Date().toISOString()),
format.json(),
),
transports: [new transports.Console()],
level: 'debug'
}
const logger = createLogger(config);

要获取文件名,请使用(new Error(((.trace属性。这将为您提供完整的堆栈跟踪,其中包含每个文件中的文件名和行号。

相关内容

  • 没有找到相关文章

最新更新