diff --git a/packages/nestjs/src/integrations/sentry-nest-event-instrumentation.ts b/packages/nestjs/src/integrations/sentry-nest-event-instrumentation.ts index f8076087fd5d..92c90c3719de 100644 --- a/packages/nestjs/src/integrations/sentry-nest-event-instrumentation.ts +++ b/packages/nestjs/src/integrations/sentry-nest-event-instrumentation.ts @@ -74,10 +74,18 @@ export class SentryNestEventInstrumentation extends InstrumentationBase { return decoratorResult(target, propertyKey, descriptor); } + function eventNameFromEvent(event: unknown): string { + if (typeof event === 'string') { + return event; + } else if (Array.isArray(event)) { + return event.map(eventNameFromEvent).join(','); + } else return String(event); + } + const originalHandler = descriptor.value; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const handlerName = originalHandler.name || propertyKey; - let eventName = typeof event === 'string' ? event : String(event); + let eventName = eventNameFromEvent(event); // Instrument the actual handler descriptor.value = async function (...args: unknown[]) { @@ -93,7 +101,7 @@ export class SentryNestEventInstrumentation extends InstrumentationBase { eventName = eventData .map((data: unknown) => { if (data && typeof data === 'object' && 'event' in data && data.event) { - return data.event; + return eventNameFromEvent(data.event); } return ''; }) diff --git a/packages/nestjs/test/integrations/nest.test.ts b/packages/nestjs/test/integrations/nest.test.ts index 69fb022441dd..2d1d73b4657a 100644 --- a/packages/nestjs/test/integrations/nest.test.ts +++ b/packages/nestjs/test/integrations/nest.test.ts @@ -75,17 +75,72 @@ describe('Nest', () => { await descriptor.value(); - expect(core.startSpan).toHaveBeenCalled(); + expect(core.startSpan).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'event test.event', + }), + expect.any(Function), + ); expect(originalHandler).toHaveBeenCalled(); }); - it('should wrap array event handlers', async () => { + it('should wrap symbol event handlers', async () => { + const decorated = wrappedOnEvent(Symbol('test.event')); + decorated(mockTarget, 'testMethod', descriptor); + + await descriptor.value(); + + expect(core.startSpan).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'event Symbol(test.event)', + }), + expect.any(Function), + ); + expect(originalHandler).toHaveBeenCalled(); + }); + + it('should wrap string array event handlers', async () => { const decorated = wrappedOnEvent(['test.event1', 'test.event2']); decorated(mockTarget, 'testMethod', descriptor); await descriptor.value(); - expect(core.startSpan).toHaveBeenCalled(); + expect(core.startSpan).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'event test.event1,test.event2', + }), + expect.any(Function), + ); + expect(originalHandler).toHaveBeenCalled(); + }); + + it('should wrap symbol array event handlers', async () => { + const decorated = wrappedOnEvent([Symbol('test.event1'), Symbol('test.event2')]); + decorated(mockTarget, 'testMethod', descriptor); + + await descriptor.value(); + + expect(core.startSpan).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'event Symbol(test.event1),Symbol(test.event2)', + }), + expect.any(Function), + ); + expect(originalHandler).toHaveBeenCalled(); + }); + + it('should wrap mixed type array event handlers', async () => { + const decorated = wrappedOnEvent([Symbol('test.event1'), 'test.event2', Symbol('test.event3')]); + decorated(mockTarget, 'testMethod', descriptor); + + await descriptor.value(); + + expect(core.startSpan).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'event Symbol(test.event1),test.event2,Symbol(test.event3)', + }), + expect.any(Function), + ); expect(originalHandler).toHaveBeenCalled(); });