diff --git a/packages/core/src/tracing/sentrySpan.ts b/packages/core/src/tracing/sentrySpan.ts index ad2bfeb7dc34..d7c800e338a7 100644 --- a/packages/core/src/tracing/sentrySpan.ts +++ b/packages/core/src/tracing/sentrySpan.ts @@ -261,7 +261,15 @@ export class SentrySpan implements Span { // if this is a standalone span, we send it immediately if (this._isStandaloneSpan) { - sendSpanEnvelope(createSpanEnvelope([this], client)); + if (this._sampled) { + sendSpanEnvelope(createSpanEnvelope([this], client)); + } else { + DEBUG_BUILD && + logger.log('[Tracing] Discarding standalone span because its trace was not chosen to be sampled.'); + if (client) { + client.recordDroppedEvent('sample_rate', 'span'); + } + } return; } diff --git a/packages/core/test/lib/tracing/sentrySpan.test.ts b/packages/core/test/lib/tracing/sentrySpan.test.ts index 5d6895f34026..9698ab5e3398 100644 --- a/packages/core/test/lib/tracing/sentrySpan.test.ts +++ b/packages/core/test/lib/tracing/sentrySpan.test.ts @@ -91,6 +91,39 @@ describe('SentrySpan', () => { expect(spanToJSON(span).timestamp).toBeGreaterThan(1); }); + test('uses sampled config for standalone span', () => { + const client = new TestClient( + getDefaultTestClientOptions({ + dsn: 'https://username@domain/123', + enableSend: true, + }), + ); + setCurrentClient(client); + + // @ts-expect-error Accessing private transport API + const mockSend = jest.spyOn(client._transport, 'send'); + + const notSampledSpan = new SentrySpan({ + name: 'not-sampled', + isStandalone: true, + startTimestamp: 1, + endTimestamp: 2, + sampled: false, + }); + notSampledSpan.end(); + expect(mockSend).not.toHaveBeenCalled(); + + const sampledSpan = new SentrySpan({ + name: 'is-sampled', + isStandalone: true, + startTimestamp: 1, + endTimestamp: 2, + sampled: true, + }); + sampledSpan.end(); + expect(mockSend).toHaveBeenCalledTimes(1); + }); + test('sends the span if `beforeSendSpan` does not modify the span ', () => { const beforeSendSpan = jest.fn(span => span); const client = new TestClient(