diff --git a/packages/core/src/tracing/idletransaction.ts b/packages/core/src/tracing/idletransaction.ts index 9f7964a33f3f..6b72113097fc 100644 --- a/packages/core/src/tracing/idletransaction.ts +++ b/packages/core/src/tracing/idletransaction.ts @@ -158,15 +158,22 @@ export class IdleTransaction extends Transaction { logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2)); } - const keepSpan = span.startTimestamp < endTimestamp; - if (!keepSpan) { - __DEBUG_BUILD__ && - logger.log( - '[Tracing] discarding Span since it happened after Transaction was finished', - JSON.stringify(span, undefined, 2), - ); + const spanStartedBeforeTransactionFinish = span.startTimestamp < endTimestamp; + + // Add a delta with idle timeout so that we prevent false positives + const timeoutWithMarginOfError = (this._finalTimeout + this._idleTimeout) / 1000; + const spanEndedBeforeFinalTimeout = span.endTimestamp - this.startTimestamp < timeoutWithMarginOfError; + + if (__DEBUG_BUILD__) { + const stringifiedSpan = JSON.stringify(span, undefined, 2); + if (!spanStartedBeforeTransactionFinish) { + logger.log('[Tracing] discarding Span since it happened after Transaction was finished', stringifiedSpan); + } else if (!spanEndedBeforeFinalTimeout) { + logger.log('[Tracing] discarding Span since it finished after Transaction final timeout', stringifiedSpan); + } } - return keepSpan; + + return spanStartedBeforeTransactionFinish && spanEndedBeforeFinalTimeout; }); __DEBUG_BUILD__ && logger.log('[Tracing] flushing IdleTransaction'); diff --git a/packages/tracing/test/idletransaction.test.ts b/packages/tracing/test/idletransaction.test.ts index 027559c02296..88a2fb4f6d1d 100644 --- a/packages/tracing/test/idletransaction.test.ts +++ b/packages/tracing/test/idletransaction.test.ts @@ -202,6 +202,19 @@ describe('IdleTransaction', () => { } }); + it('filters out spans that exceed final timeout', () => { + const transaction = new IdleTransaction({ name: 'foo', startTimestamp: 1234 }, hub, 1000, 3000); + transaction.initSpanRecorder(10); + + const span = transaction.startChild({ startTimestamp: transaction.startTimestamp + 2 }); + span.finish(span.startTimestamp + 10 + 30 + 1); + + transaction.finish(transaction.startTimestamp + 50); + + expect(transaction.spanRecorder).toBeDefined(); + expect(transaction.spanRecorder!.spans).toHaveLength(1); + }); + it('should record dropped transactions', async () => { const transaction = new IdleTransaction({ name: 'foo', startTimestamp: 1234, sampled: false }, hub, 1000);