diff --git a/src/Sentry.OpenTelemetry/SentrySpanProcessor.cs b/src/Sentry.OpenTelemetry/SentrySpanProcessor.cs index cc341c73df..6c9113aca2 100644 --- a/src/Sentry.OpenTelemetry/SentrySpanProcessor.cs +++ b/src/Sentry.OpenTelemetry/SentrySpanProcessor.cs @@ -172,7 +172,10 @@ private void CreateRootSpan(Activity data) tracer.Contexts.Trace.Origin = OpenTelemetryOrigin; tracer.StartTimestamp = data.StartTimeUtc; } - _hub.ConfigureScope(static (scope, transaction) => scope.Transaction = transaction, transaction); + _hub.ConfigureScope(static (scope, transaction) => + { + scope.Transaction ??= transaction; + }, transaction); transaction.SetFused(data); _map[data.SpanId] = transaction; } diff --git a/test/Sentry.OpenTelemetry.Tests/SentrySpanProcessorTests.cs b/test/Sentry.OpenTelemetry.Tests/SentrySpanProcessorTests.cs index a986a4779f..1c3adbbea5 100644 --- a/test/Sentry.OpenTelemetry.Tests/SentrySpanProcessorTests.cs +++ b/test/Sentry.OpenTelemetry.Tests/SentrySpanProcessorTests.cs @@ -1012,4 +1012,35 @@ public void ParseOtelSpanDescription_HttpClient() description.Should().Be("POST https://example.com/foo"); source.Should().Be(TransactionNameSource.Custom); } + + [Fact] + public void OnStart_WithExistingTransactionOnScope_DoesNotOverwriteExistingTransaction() + { + // Arrange + _fixture.Options.Instrumenter = Instrumenter.OpenTelemetry; + var sut = _fixture.GetSut(); + + var parentContext = new TransactionContext("Program", "Main") + { + Instrumenter = Instrumenter.OpenTelemetry, + }; + var parent = _fixture.Hub.StartTransaction(parentContext); + _fixture.Hub.ConfigureScope(scope => scope.Transaction = parent); + + using var data = Tracer.StartActivity("TestActivity"); + + // Act + sut.OnStart(data!); + + // Assert + data.ParentSpanId.Should().Be(default(ActivitySpanId), $"{nameof(data)} should be a new root Activity, not a child Activity"); + Assert.True(sut._map.TryGetValue(data.SpanId, out var span)); + span.Should().BeOfType($"{nameof(data)} should be a new root Transaction, not a child Span"); + + object scopeTransaction = null; + _fixture.Hub.ConfigureScope(scope => scopeTransaction = scope.Transaction); + + scopeTransaction.Should().BeSameAs(parent, + "CreateRootSpan should not overwrite an already-set Scope.Transaction"); + } }