diff --git a/CHANGELOG.md b/CHANGELOG.md index d032e8cd952..f78bfd64901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # vNext + * Fix: Remove experimental annotation for Attachment #1257 * Fix: Mark stacktrace as snapshot if captured at arbitrary moment #1231 * Enchancement: Improve EventProcessor nullability annotations (#1229). @@ -18,6 +19,7 @@ * Enchancement: Add Request to the Scope. #1270 * Fix: Fix SentryTransaction#getStatus NPE (#1273) * Enchancement: Optimize SentryTracingFilter when hub is disabled. +* Fix: Discard unfinished Spans before sending them over to Sentry (#1279) * Fix: Interrupt the thread in QueuedThreadPoolExecutor (#1276) * Fix: SentryTransaction#finish should not clear another transaction from the scope (#1278) diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 9979eae28f5..6464ba81530 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -409,6 +409,18 @@ public void captureSession(final @NotNull Session session, final @Nullable Objec } } } + final List unfinishedSpans = new ArrayList<>(); + for (Span span : transaction.getSpans()) { + if (!span.isFinished()) { + unfinishedSpans.add(span); + } + } + if (!unfinishedSpans.isEmpty()) { + options + .getLogger() + .log(SentryLevel.WARNING, "Dropping %d unfinished spans", unfinishedSpans.size()); + } + transaction.getSpans().removeAll(unfinishedSpans); return transaction; } diff --git a/sentry/src/test/java/io/sentry/SentryClientTest.kt b/sentry/src/test/java/io/sentry/SentryClientTest.kt index 71b78c4b70a..1fe7408304b 100644 --- a/sentry/src/test/java/io/sentry/SentryClientTest.kt +++ b/sentry/src/test/java/io/sentry/SentryClientTest.kt @@ -757,6 +757,25 @@ class SentryClientTest { }, eq(null)) } + @Test + fun `when captureTransactions unfinished spans are removed`() { + val sut = fixture.getSut() + val transaction = SentryTransaction("a-transaction", "op") + val span1 = transaction.startChild("span1") + span1.finish() + val span2 = transaction.startChild("span2") + + sut.captureTransaction(transaction, mock(), null) + verify(fixture.transport).send(check { + val sentTransaction = it.items.first().getTransaction(fixture.sentryOptions.serializer) + assertNotNull(sentTransaction) { tx -> + val sentSpanIds = tx.spans.map { span -> span.spanId } + assertTrue(sentSpanIds.contains(span1.spanContext.spanId)) + assertFalse(sentSpanIds.contains(span2.spanContext.spanId)) + } + }, eq(null)) + } + @Test fun `when captureTransaction with attachments`() { val transaction = SentryTransaction("a-transaction", "op")