71 lines
1.6 KiB
TypeScript
71 lines
1.6 KiB
TypeScript
import { Injectable, OnApplicationShutdown } from '@nestjs/common';
|
|
import { PinoLogger } from 'nestjs-pino';
|
|
|
|
type LogLevel = 'debug' | 'error' | 'info' | 'warn';
|
|
type LogContext = Record<string, boolean | number | string | undefined>;
|
|
|
|
const allowedFields = new Set([
|
|
'asOf',
|
|
'attempts',
|
|
'brokerageAccountId',
|
|
'channelState',
|
|
'clientRequestId',
|
|
'code',
|
|
'count',
|
|
'durationMs',
|
|
'environment',
|
|
'errorName',
|
|
'errorStack',
|
|
'found',
|
|
'grpcCode',
|
|
'headersReceived',
|
|
'invalidFields',
|
|
'method',
|
|
'networkMs',
|
|
'operation',
|
|
'queueWaitMs',
|
|
'requestId',
|
|
'route',
|
|
'service',
|
|
'status',
|
|
'trackingId',
|
|
'userId',
|
|
]);
|
|
|
|
@Injectable()
|
|
export class StructuredLogger implements OnApplicationShutdown {
|
|
constructor(private readonly pino: PinoLogger) {}
|
|
|
|
info(message: string, context?: LogContext): void {
|
|
this.write('info', message, context);
|
|
}
|
|
|
|
event(level: LogLevel, message: string, context?: LogContext): void {
|
|
this.write(level, message, context);
|
|
}
|
|
|
|
onApplicationShutdown(): void {
|
|
this.info('application.stopped');
|
|
}
|
|
|
|
private write(
|
|
level: LogLevel,
|
|
message: string,
|
|
context: LogContext = {},
|
|
): void {
|
|
// eslint-disable-next-line security/detect-object-injection -- The log level is restricted to the internal LogLevel union.
|
|
this.pino[level](
|
|
this.safeContext(context),
|
|
message,
|
|
);
|
|
}
|
|
|
|
private safeContext(context: LogContext): LogContext {
|
|
return Object.fromEntries(
|
|
Object.entries(context).filter(
|
|
([key, value]) => allowedFields.has(key) && value !== undefined,
|
|
),
|
|
);
|
|
}
|
|
}
|