diff --git a/packages/core/src/semanticAttributes.ts b/packages/core/src/semanticAttributes.ts index 02b6a4ec08a6..9eeed6378a5f 100644 --- a/packages/core/src/semanticAttributes.ts +++ b/packages/core/src/semanticAttributes.ts @@ -53,13 +53,13 @@ export const SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME = 'sentry.sdk.name'; /** The version of the Sentry SDK */ export const SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION = 'sentry.sdk.version'; -/** The user ID (gated by sendDefaultPii) */ +/** The user ID */ export const SEMANTIC_ATTRIBUTE_USER_ID = 'user.id'; -/** The user email (gated by sendDefaultPii) */ +/** The user email */ export const SEMANTIC_ATTRIBUTE_USER_EMAIL = 'user.email'; -/** The user IP address (gated by sendDefaultPii) */ +/** The user IP address */ export const SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS = 'user.ip_address'; -/** The user username (gated by sendDefaultPii) */ +/** The user username */ export const SEMANTIC_ATTRIBUTE_USER_USERNAME = 'user.name'; /** diff --git a/packages/core/src/tracing/spans/captureSpan.ts b/packages/core/src/tracing/spans/captureSpan.ts index bed3f1790740..afbc8ad60358 100644 --- a/packages/core/src/tracing/spans/captureSpan.ts +++ b/packages/core/src/tracing/spans/captureSpan.ts @@ -125,7 +125,7 @@ function applyCommonSpanAttributes( scopeData: ScopeData, ): void { const sdk = client.getSdkMetadata(); - const { release, environment, sendDefaultPii } = client.getOptions(); + const { release, environment } = client.getOptions(); // avoid overwriting any previously set attributes (from users or potentially our SDK instrumentation) safeSetSpanJSONAttributes(spanJSON, { @@ -135,14 +135,10 @@ function applyCommonSpanAttributes( [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: serializedSegmentSpan.span_id, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_NAME]: sdk?.sdk?.name, [SEMANTIC_ATTRIBUTE_SENTRY_SDK_VERSION]: sdk?.sdk?.version, - ...(sendDefaultPii - ? { - [SEMANTIC_ATTRIBUTE_USER_ID]: scopeData.user?.id, - [SEMANTIC_ATTRIBUTE_USER_EMAIL]: scopeData.user?.email, - [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: scopeData.user?.ip_address, - [SEMANTIC_ATTRIBUTE_USER_USERNAME]: scopeData.user?.username, - } - : {}), + [SEMANTIC_ATTRIBUTE_USER_ID]: scopeData.user?.id, + [SEMANTIC_ATTRIBUTE_USER_EMAIL]: scopeData.user?.email, + [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: scopeData.user?.ip_address, + [SEMANTIC_ATTRIBUTE_USER_USERNAME]: scopeData.user?.username, ...scopeData.attributes, }); } diff --git a/packages/core/test/lib/tracing/spans/captureSpan.test.ts b/packages/core/test/lib/tracing/spans/captureSpan.test.ts index 186f7f23a536..524f3287e82c 100644 --- a/packages/core/test/lib/tracing/spans/captureSpan.test.ts +++ b/packages/core/test/lib/tracing/spans/captureSpan.test.ts @@ -25,179 +25,102 @@ import { inferSpanDataFromOtelAttributes, safeSetSpanJSONAttributes } from '../. import { getDefaultTestClientOptions, TestClient } from '../../../mocks/client'; describe('captureSpan', () => { - it('captures user attributes iff sendDefaultPii is true', () => { - const client = new TestClient( - getDefaultTestClientOptions({ - dsn: 'https://dsn@ingest.f00.f00/1', - tracesSampleRate: 1, - release: '1.0.0', - environment: 'staging', - sendDefaultPii: true, - }), - ); - - const span = withScope(scope => { - scope.setClient(client); - scope.setUser({ - id: '123', - email: 'user@example.com', - username: 'testuser', - ip_address: '127.0.0.1', - }); - - const span = startInactiveSpan({ name: 'my-span', attributes: { 'sentry.op': 'http.client' } }); - span.end(); - - return span; - }); - - const serializedSpan = captureSpan(span, client); + it.each([true, false, undefined])( + 'always applies scope user attributes to spans (sendDefaultPii: %s)', + sendDefaultPii => { + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://dsn@ingest.f00.f00/1', + tracesSampleRate: 1, + release: '1.0.0', + environment: 'staging', + sendDefaultPii, + }), + ); - expect(serializedSpan).toStrictEqual({ - span_id: expect.stringMatching(/^[\da-f]{16}$/), - trace_id: expect.stringMatching(/^[\da-f]{32}$/), - parent_span_id: undefined, - links: undefined, - start_timestamp: expect.any(Number), - name: 'my-span', - end_timestamp: expect.any(Number), - status: 'ok', - is_segment: true, - attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { - type: 'string', - value: 'http.client', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { - type: 'string', - value: 'manual', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { - type: 'integer', - value: 1, - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { - value: 'my-span', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { - value: span.spanContext().spanId, - type: 'string', - }, - 'sentry.span.source': { - value: 'custom', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: { - value: 'custom', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { - value: '1.0.0', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { - value: 'staging', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_USER_ID]: { - value: '123', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_USER_EMAIL]: { - value: 'user@example.com', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_USER_USERNAME]: { - value: 'testuser', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: { - value: '127.0.0.1', - type: 'string', - }, - }, - _segmentSpan: span, - }); - }); + const span = withScope(scope => { + scope.setClient(client); + scope.setUser({ + id: '123', + email: 'user@example.com', + username: 'testuser', + ip_address: '127.0.0.1', + }); - it.each([false, undefined])("doesn't capture user attributes if sendDefaultPii is %s", sendDefaultPii => { - const client = new TestClient( - getDefaultTestClientOptions({ - dsn: 'https://dsn@ingest.f00.f00/1', - tracesSampleRate: 1, - release: '1.0.0', - environment: 'staging', - sendDefaultPii, - }), - ); + const span = startInactiveSpan({ name: 'my-span', attributes: { 'sentry.op': 'http.client' } }); + span.end(); - const span = withScope(scope => { - scope.setClient(client); - scope.setUser({ - id: '123', - email: 'user@example.com', - username: 'testuser', - ip_address: '127.0.0.1', + return span; }); - const span = startInactiveSpan({ name: 'my-span', attributes: { 'sentry.op': 'http.client' } }); - span.end(); - - return span; - }); - - expect(captureSpan(span, client)).toStrictEqual({ - span_id: expect.stringMatching(/^[\da-f]{16}$/), - trace_id: expect.stringMatching(/^[\da-f]{32}$/), - parent_span_id: undefined, - links: undefined, - start_timestamp: expect.any(Number), - name: 'my-span', - end_timestamp: expect.any(Number), - status: 'ok', - is_segment: true, - attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { - type: 'string', - value: 'http.client', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { - type: 'string', - value: 'manual', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { - type: 'integer', - value: 1, - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { - value: 'my-span', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { - value: span.spanContext().spanId, - type: 'string', - }, - 'sentry.span.source': { - value: 'custom', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: { - value: 'custom', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { - value: '1.0.0', - type: 'string', - }, - [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { - value: 'staging', - type: 'string', + expect(captureSpan(span, client)).toStrictEqual({ + span_id: expect.stringMatching(/^[\da-f]{16}$/), + trace_id: expect.stringMatching(/^[\da-f]{32}$/), + parent_span_id: undefined, + links: undefined, + start_timestamp: expect.any(Number), + name: 'my-span', + end_timestamp: expect.any(Number), + status: 'ok', + is_segment: true, + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: { + type: 'string', + value: 'http.client', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: { + type: 'string', + value: 'manual', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: { + type: 'integer', + value: 1, + }, + [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_NAME]: { + value: 'my-span', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_SEGMENT_ID]: { + value: span.spanContext().spanId, + type: 'string', + }, + 'sentry.span.source': { + value: 'custom', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: { + value: 'custom', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_RELEASE]: { + value: '1.0.0', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_SENTRY_ENVIRONMENT]: { + value: 'staging', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_ID]: { + value: '123', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_EMAIL]: { + value: 'user@example.com', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_USERNAME]: { + value: 'testuser', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: { + value: '127.0.0.1', + type: 'string', + }, }, - }, - _segmentSpan: span, - }); - }); + _segmentSpan: span, + }); + }, + ); it('captures sdk name and version if available', () => { const client = new TestClient( @@ -286,6 +209,22 @@ describe('captureSpan', () => { value: '1.0.0', type: 'string', }, + [SEMANTIC_ATTRIBUTE_USER_ID]: { + value: '123', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_EMAIL]: { + value: 'user@example.com', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_USERNAME]: { + value: 'testuser', + type: 'string', + }, + [SEMANTIC_ATTRIBUTE_USER_IP_ADDRESS]: { + value: '127.0.0.1', + type: 'string', + }, }, _segmentSpan: span, });