From 417a1f91715569c9f35ef800e5f1242aa7c226d1 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 25 Apr 2024 10:31:34 +0200 Subject: [PATCH 1/4] adjust mixed transaction and standalone test --- .../startSpan/standalone-mixed-transaction/test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone-mixed-transaction/test.ts b/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone-mixed-transaction/test.ts index 36aab28d2a77..7c93f923164b 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone-mixed-transaction/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone-mixed-transaction/test.ts @@ -38,9 +38,16 @@ sentryTest( expect(traceId).toMatch(/[a-f0-9]{32}/); expect(parentSpanId).toMatch(/[a-f0-9]{16}/); - // TODO: the span envelope also needs to contain the `trace` header (follow-up PR) expect(spanEnvelopeHeader).toEqual({ sent_at: expect.any(String), + trace: { + environment: 'production', + public_key: 'public', + sample_rate: '1', + sampled: 'true', + trace_id: traceId, + transaction: 'outer', + }, }); expect(transactionEnvelopeHeader).toEqual({ From 5095e825da4c08dc5244509312d00ba59818a95e Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 25 Apr 2024 10:54:40 +0200 Subject: [PATCH 2/4] fix core unit test --- packages/core/test/lib/envelope.test.ts | 87 ++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 2 deletions(-) diff --git a/packages/core/test/lib/envelope.test.ts b/packages/core/test/lib/envelope.test.ts index 0d6684233cbb..f5240e826604 100644 --- a/packages/core/test/lib/envelope.test.ts +++ b/packages/core/test/lib/envelope.test.ts @@ -1,6 +1,15 @@ -import type { DsnComponents, DynamicSamplingContext, Event } from '@sentry/types'; +import type { Client, DsnComponents, DynamicSamplingContext, Event } from '@sentry/types'; -import { createEventEnvelope } from '../../src/envelope'; +import { + SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, + SentrySpan, + getCurrentScope, + getIsolationScope, + setAsyncContextStrategy, + setCurrentClient, +} from '../../src'; +import { createEventEnvelope, createSpanEnvelope } from '../../src/envelope'; +import { TestClient, getDefaultTestClientOptions } from '../mocks/client'; const testDsn: DsnComponents = { protocol: 'https', projectId: 'abc', host: 'testry.io', publicKey: 'pubKey123' }; @@ -75,3 +84,77 @@ describe('createEventEnvelope', () => { }); }); }); + +describe('createSpanEnvelope', () => { + let client: Client | undefined; + beforeEach(() => { + getCurrentScope().clear(); + getIsolationScope().clear(); + setAsyncContextStrategy(undefined); + const options = getDefaultTestClientOptions({ tracesSampleRate: 1, dsn: 'https://username@domain/123' }); + client = new TestClient(options); + setCurrentClient(client); + client.init(); + }); + + it('creates a span envelope', () => { + const span = new SentrySpan({ + name: 'test', + isStandalone: true, + startTimestamp: 1, + endTimestamp: 2, + sampled: true, + attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' }, + }); + + const spanEnvelope = createSpanEnvelope([span]); + + const spanItem = spanEnvelope[1][0][1]; + expect(spanItem).toEqual({ + data: { + 'sentry.origin': 'manual', + 'sentry.source': 'custom', + }, + description: 'test', + is_segment: true, + origin: 'manual', + span_id: expect.stringMatching(/^[0-9a-f]{16}$/), + segment_id: spanItem.segment_id, + start_timestamp: 1, + timestamp: 2, + trace_id: expect.stringMatching(/^[0-9a-f]{32}$/), + }); + }); + + it('adds `trace` and `sent_at` envelope headers', () => { + const spanEnvelope = createSpanEnvelope([ + new SentrySpan({ name: 'test', attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom' } }), + ]); + + const spanEnvelopeHeaders = spanEnvelope[0]; + expect(spanEnvelopeHeaders).toEqual({ + sent_at: expect.any(String), + trace: { + environment: 'production', + public_key: 'username', + sampled: 'false', + trace_id: expect.stringMatching(/^[0-9a-f]{32}$/), + transaction: 'test', + }, + }); + }); + + it("doesn't add a `trace` envelope header if there's no public key", () => { + const options = getDefaultTestClientOptions({ tracesSampleRate: 1, dsn: 'https://domain/123' }); + client = new TestClient(options); + setCurrentClient(client); + client.init(); + + const spanEnvelope = createSpanEnvelope([new SentrySpan()]); + + const spanEnvelopeHeaders = spanEnvelope[0]; + expect(spanEnvelopeHeaders).toEqual({ + sent_at: expect.any(String), + }); + }); +}); From 47f21d07bcd5d4e61fa6b46e20c8308f116d62f6 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 25 Apr 2024 16:52:03 +0200 Subject: [PATCH 3/4] fix failed rebase --- packages/core/src/envelope.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/core/src/envelope.ts b/packages/core/src/envelope.ts index bc29c6fa8b01..11d38b2040e6 100644 --- a/packages/core/src/envelope.ts +++ b/packages/core/src/envelope.ts @@ -2,6 +2,7 @@ import type { Attachment, AttachmentItem, DsnComponents, + DynamicSamplingContext, Event, EventEnvelope, EventItem, @@ -21,7 +22,7 @@ import { getSdkMetadataForEnvelopeHeader, } from '@sentry/utils'; import { createSpanEnvelopeItem } from '@sentry/utils'; -import type { SentrySpan } from './tracing'; +import { type SentrySpan, getDynamicSamplingContextFromSpan } from './tracing'; import { spanToJSON } from './utils/spanUtils'; /** @@ -126,10 +127,19 @@ export function createAttachmentEnvelope( * Create envelope from Span item. */ export function createSpanEnvelope(spans: SentrySpan[]): SpanEnvelope { + function dscHasRequiredProps(dsc: Partial): dsc is DynamicSamplingContext { + return !!dsc.trace_id && !!dsc.public_key; + } + + // For the moment we'll obtain the DSC from the first span in the array + // This might need to be changed if we permit sending multiple spans from + // different segments in one envelope + const dsc = getDynamicSamplingContextFromSpan(spans[0]); + const headers: SpanEnvelope[0] = { sent_at: new Date().toISOString(), + ...(dscHasRequiredProps(dsc) && { trace: dsc }), }; - const items = spans.map(span => createSpanEnvelopeItem(spanToJSON(span))); return createEnvelope(headers, items); } From 12a331edfba209c60e98f32bed5196c72976eb7d Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Thu, 25 Apr 2024 16:58:20 +0200 Subject: [PATCH 4/4] and bring back missing test adjustment --- .../suites/public-api/startSpan/standalone/test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone/test.ts b/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone/test.ts index aab881e34580..256f047b5f9e 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/startSpan/standalone/test.ts @@ -22,8 +22,18 @@ sentryTest('sends a segment span envelope', async ({ getLocalTestPath, page }) = const itemHeader = item[0]; const spanJson = item[1]; + const traceId = spanJson.trace_id; + expect(headers).toEqual({ sent_at: expect.any(String), + trace: { + environment: 'production', + public_key: 'public', + sample_rate: '1', + sampled: 'true', + trace_id: traceId, + transaction: 'standalone_segment_span', + }, }); expect(itemHeader).toEqual({