diff --git a/src/Sentry/TransactionTracer.cs b/src/Sentry/TransactionTracer.cs index a133a97184..cfb6cb8b15 100644 --- a/src/Sentry/TransactionTracer.cs +++ b/src/Sentry/TransactionTracer.cs @@ -324,16 +324,16 @@ internal ISpan StartChild(SpanId? spanId, SpanId parentSpanId, string operation, private void AddChildSpan(SpanTracer span) { - var isOutOfLimit = _spans.Count >= SpanLimit; - span.IsSampled = isOutOfLimit ? false : IsSampled; - if (isOutOfLimit) - { - _options?.LogDebug("Discarding child span '{0}' due to {1} span limit", SpanId, SpanLimit); - return; - } - lock (_finishLock) { + var isOutOfLimit = _spans.Count >= SpanLimit; + span.IsSampled = isOutOfLimit ? false : IsSampled; + if (isOutOfLimit) + { + _options?.LogDebug("Discarding child span '{0}' due to {1} span limit", SpanId, SpanLimit); + return; + } + if (_hasFinished) { _options?.LogDebug("Discarding child span '{0}' as the trace has already finished", SpanId); diff --git a/test/Sentry.Tests/Protocol/SentryTransactionTests.cs b/test/Sentry.Tests/Protocol/SentryTransactionTests.cs index e774e7a0f3..8ccca8ff84 100644 --- a/test/Sentry.Tests/Protocol/SentryTransactionTests.cs +++ b/test/Sentry.Tests/Protocol/SentryTransactionTests.cs @@ -350,6 +350,21 @@ public void StartChild_Limit_Maintained() spans.Count(s => s.IsSampled == true).Should().Be(1000); } + [Fact] + public void StartChild_Limit_Maintained_Concurrently() + { + // Arrange + var transaction = new TransactionTracer(DisabledHub.Instance, "my name", "my op"); + var spans = new ConcurrentBag(); + + // Act + Parallel.For(0, 5000, i => spans.Add(transaction.StartChild("span " + i))); + + // Assert + transaction.Spans.Should().HaveCount(1000); + spans.Count(s => s.IsSampled == true).Should().Be(1000); + } + [Fact] public void StartChild_SamplingInherited_True() {