diff --git a/packages/node-core/src/integrations/context.ts b/packages/node-core/src/integrations/context.ts index 3c3904582315..c0868f9527b3 100644 --- a/packages/node-core/src/integrations/context.ts +++ b/packages/node-core/src/integrations/context.ts @@ -102,7 +102,6 @@ const _nodeContextIntegration = ((options: ContextOptions = {}) => { async function addContext(event: Event): Promise { const updatedContext = _updateContext(await contextsPromise); - // TODO(v11): conditional with `sendDefaultPii` here? event.contexts = { ...event.contexts, app: { ...updatedContext.app, ...event.contexts?.app }, diff --git a/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts b/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts index 314f733a7dae..48a6bb08897e 100644 --- a/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts +++ b/packages/node-core/src/integrations/http/httpServerSpansIntegration.ts @@ -167,10 +167,7 @@ const _httpServerSpansIntegration = ((options: HttpServerSpansIntegrationOptions 'http.flavor': httpVersion, 'net.transport': httpVersion?.toUpperCase() === 'QUIC' ? 'ip_udp' : 'ip_tcp', ...getRequestContentLengthAttribute(request), - ...httpHeadersToSpanAttributes( - normalizedRequest.headers || {}, - client.getOptions().sendDefaultPii ?? false, - ), + ...httpHeadersToSpanAttributes(normalizedRequest.headers || {}, client.getDataCollectionOptions()), }, }); diff --git a/packages/node-core/src/integrations/systemError.ts b/packages/node-core/src/integrations/systemError.ts index 29c4410a01f9..7b38566b98fa 100644 --- a/packages/node-core/src/integrations/systemError.ts +++ b/packages/node-core/src/integrations/systemError.ts @@ -56,7 +56,7 @@ export const systemErrorIntegration = defineIntegration((options: Options = {}) ...(error as SystemErrorContext), }; - if (!client.getOptions().sendDefaultPii && options.includePaths !== true) { + if (!client.getDataCollectionOptions().userInfo && options.includePaths !== true) { delete errorContext.path; delete errorContext.dest; } diff --git a/packages/node-core/test/integrations/systemError.test.ts b/packages/node-core/test/integrations/systemError.test.ts index 3d29be490104..cdbe2c824b6c 100644 --- a/packages/node-core/test/integrations/systemError.test.ts +++ b/packages/node-core/test/integrations/systemError.test.ts @@ -25,9 +25,13 @@ describe('systemErrorIntegration', () => { vi.mocked(util.getSystemErrorMap).mockRestore(); }); - function createClient(sendDefaultPii = false): Client { + function createClient({ sendDefaultPii, userInfo }: { sendDefaultPii?: boolean; userInfo?: boolean } = {}): Client { + // When userInfo is explicitly provided, use it directly. + // Otherwise fall back to sendDefaultPii (mimicking resolveDataCollectionOptions). + const resolvedUserInfo = userInfo ?? sendDefaultPii ?? false; return { getOptions: () => ({ sendDefaultPii }), + getDataCollectionOptions: () => ({ userInfo: resolvedUserInfo }), } as unknown as Client; } @@ -68,7 +72,7 @@ describe('systemErrorIntegration', () => { expect(result.exception?.values?.[0]?.value).not.toContain('/secret/path'); }); - it('keeps path in context when sendDefaultPii is true', () => { + it('keeps path in context when userInfo is true', () => { const errno = -2; vi.mocked(util.getSystemErrorMap).mockReturnValue( new Map([[errno, ['ENOENT', 'no such file or directory']]]), @@ -78,11 +82,68 @@ describe('systemErrorIntegration', () => { const error = Object.assign(new Error('boom'), { errno, path: '/secret/path' }); const event = { exception: { values: [{ value: error.message }] } } as Event; - const result = integration.processEvent!(event, { originalException: error }, createClient(true)) as Event; + const result = integration.processEvent!( + event, + { originalException: error }, + createClient({ userInfo: true }), + ) as Event; expect(result.contexts?.node_system_error).toEqual({ errno, path: '/secret/path' }); }); + it('strips path from context when userInfo is false', () => { + const errno = -2; + vi.mocked(util.getSystemErrorMap).mockReturnValue( + new Map([[errno, ['ENOENT', 'no such file or directory']]]), + ); + + const integration = systemErrorIntegration(); + const error = Object.assign(new Error('boom'), { errno, path: '/secret/path' }); + const event = { exception: { values: [{ value: error.message }] } } as Event; + + const result = integration.processEvent!(event, { originalException: error }, createClient()) as Event; + + expect(result.contexts?.node_system_error).toEqual({ errno }); + }); + + it('keeps path in context when legacy sendDefaultPii is true', () => { + const errno = -2; + vi.mocked(util.getSystemErrorMap).mockReturnValue( + new Map([[errno, ['ENOENT', 'no such file or directory']]]), + ); + + const integration = systemErrorIntegration(); + const error = Object.assign(new Error('boom'), { errno, path: '/secret/path' }); + const event = { exception: { values: [{ value: error.message }] } } as Event; + + const result = integration.processEvent!( + event, + { originalException: error }, + createClient({ sendDefaultPii: true }), + ) as Event; + + expect(result.contexts?.node_system_error).toEqual({ errno, path: '/secret/path' }); + }); + + it('strips path from context when legacy sendDefaultPii is false', () => { + const errno = -2; + vi.mocked(util.getSystemErrorMap).mockReturnValue( + new Map([[errno, ['ENOENT', 'no such file or directory']]]), + ); + + const integration = systemErrorIntegration(); + const error = Object.assign(new Error('boom'), { errno, path: '/secret/path' }); + const event = { exception: { values: [{ value: error.message }] } } as Event; + + const result = integration.processEvent!( + event, + { originalException: error }, + createClient({ sendDefaultPii: false }), + ) as Event; + + expect(result.contexts?.node_system_error).toEqual({ errno }); + }); + it('keeps path in context when includePaths option is true', () => { const errno = -2; vi.mocked(util.getSystemErrorMap).mockReturnValue(