From 6c48c9fd7eb18bfb42231ef1d7a8b5505f961035 Mon Sep 17 00:00:00 2001 From: Doug Ludlow Date: Wed, 20 Sep 2023 18:38:37 -0600 Subject: [PATCH] add custom err attribute key support --- __tests__/errors.spec.ts | 70 ++++++++++++++++++++++++++++++++++++++++ src/PinoLogger.ts | 11 ++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/__tests__/errors.spec.ts b/__tests__/errors.spec.ts index 3b16d006..56a723f1 100644 --- a/__tests__/errors.spec.ts +++ b/__tests__/errors.spec.ts @@ -175,6 +175,76 @@ describe('error logging', () => { }); }); + describe('setting custom attribute keys', () => { + it('setting the `err` custom attribute key', async () => { + const ctx = Math.random().toString(); + const message = 'custom `err` attribute key'; + + @Controller('/') + class TestController { + constructor(private readonly logger: PinoLogger) { + this.logger.setContext(ctx); + } + + @Get() + get() { + this.logger.info(new Error(message), 'baz'); + return {}; + } + } + + const logs = await new TestCase(new PlatformAdapter(), { + controllers: [TestController], + }) + .forRoot({ pinoHttp: { customAttributeKeys: { err: 'error' } } }) + .run(); + expect( + logs.some( + (v) => + v.req && + v.context === ctx && + !v.err && + v.error && + (v.error as { message: string }).message === message, + ), + ).toBeTruthy(); + }); + + it('setting the `req` custom attribute key', async () => { + const ctx = Math.random().toString(); + const message = 'custom `req` attribute key'; + + @Controller('/') + class TestController { + constructor(private readonly logger: PinoLogger) { + this.logger.setContext(ctx); + } + + @Get() + get() { + this.logger.info(new Error(message), 'baz'); + return {}; + } + } + + const logs = await new TestCase(new PlatformAdapter(), { + controllers: [TestController], + }) + .forRoot({ pinoHttp: { customAttributeKeys: { req: 'request' } } }) + .run(); + expect( + logs.some( + (v) => + !v.req && + v.request && + v.context === ctx && + v.err && + v.err.message === message, + ), + ).toBeTruthy(); + }); + }); + describe('keeps stack of thrown error', () => { it('built-in error handler logs with correct stack', async () => { const msg = Math.random().toString(); diff --git a/src/PinoLogger.ts b/src/PinoLogger.ts index c7d46d83..d6461c01 100644 --- a/src/PinoLogger.ts +++ b/src/PinoLogger.ts @@ -48,10 +48,19 @@ export class PinoLogger implements PinoMethods { protected context = ''; protected readonly contextName: string; + protected readonly errorKey: string = 'err'; constructor( @Inject(PARAMS_PROVIDER_TOKEN) { pinoHttp, renameContext }: Params, ) { + if ( + typeof pinoHttp === 'object' && + 'customAttributeKeys' in pinoHttp && + typeof pinoHttp.customAttributeKeys !== 'undefined' + ) { + this.errorKey = pinoHttp.customAttributeKeys.err ?? 'err'; + } + if (!outOfContext) { if (Array.isArray(pinoHttp)) { outOfContext = pino(...pinoHttp); @@ -135,7 +144,7 @@ export class PinoLogger implements PinoMethods { args = [ Object.assign( { [this.contextName]: this.context }, - { err: firstArg }, + { [this.errorKey]: firstArg }, ), ...args.slice(1), ];