From fe17b7dfbfc3a5e9c8dd35571b240cae0eb055a0 Mon Sep 17 00:00:00 2001 From: stefanosiano Date: Fri, 20 Jun 2025 12:43:55 +0200 Subject: [PATCH 1/5] breadcumbs queue is now a simple DisabledQueue when maxBreadcrumb is 0 if breadcumbs is a DisabledQueue, no more processing is done (beforeBreadcrumb or scopeObservers) --- sentry/src/main/java/io/sentry/Scope.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 3cb7b5554d..7a54c4c755 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -466,7 +466,7 @@ public Queue getBreadcrumbs() { */ @Override public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Hint hint) { - if (breadcrumb == null) { + if (breadcrumb == null || breadcrumbs instanceof DisabledQueue) { return; } if (hint == null) { @@ -862,7 +862,7 @@ public void clearAttachments() { static @NotNull Queue createBreadcrumbsList(final int maxBreadcrumb) { return maxBreadcrumb > 0 ? SynchronizedQueue.synchronizedQueue(new CircularFifoQueue<>(maxBreadcrumb)) - : SynchronizedQueue.synchronizedQueue(new DisabledQueue<>()); + : new DisabledQueue<>(); } /** From a74f4c69efb934be7f80fbeeea58bb976683d0ea Mon Sep 17 00:00:00 2001 From: stefanosiano Date: Fri, 20 Jun 2025 12:52:27 +0200 Subject: [PATCH 2/5] updated changelog added test --- CHANGELOG.md | 1 + sentry/src/test/java/io/sentry/ScopeTest.kt | 33 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28c336afd6..6e6de9db9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Fixes +- Optimize scope when maxBreadcrumb is 0 ([#4504](https://github.com/getsentry/sentry-java/pull/4504)) - No longer send out empty log envelopes ([#4497](https://github.com/getsentry/sentry-java/pull/4497)) ### Dependencies diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index 8ebde80548..185dc56d74 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -1,6 +1,7 @@ package io.sentry import io.sentry.SentryLevel.WARNING +import io.sentry.protocol.Contexts import io.sentry.protocol.Request import io.sentry.protocol.SentryId import io.sentry.protocol.User @@ -13,6 +14,7 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.times import org.mockito.kotlin.verify +import org.mockito.kotlin.verifyNoInteractions import org.mockito.kotlin.whenever import java.util.concurrent.CopyOnWriteArrayList import kotlin.test.Test @@ -339,6 +341,37 @@ class ScopeTest { assertEquals(1, scope.breadcrumbs.count()) } + @Test + fun `when adding breadcrumb and maxBreadcrumb is 0, beforeBreadcrumb is not executed`() { + var called = false + val options = SentryOptions().apply { + maxBreadcrumbs = 0 + beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback{ breadcrumb, _ -> + called = true + breadcrumb + } + } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(0, scope.breadcrumbs.count()) + assertFalse(called) + } + + @Test + fun `when adding breadcrumb and maxBreadcrumb is 0, scopesObservers are not called`() { + val observer = mock() + val options = SentryOptions().apply { + maxBreadcrumbs = 0 + addScopeObserver(observer) + } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(0, scope.breadcrumbs.count()) + verifyNoInteractions(observer) + } + @Test fun `when adding eventProcessor, eventProcessor should be in the list`() { val processor = CustomEventProcessor() From e3234c5589d24ac10d5ff63c1e256a0fe120b24d Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Fri, 20 Jun 2025 10:55:12 +0000 Subject: [PATCH 3/5] Format code --- sentry/src/test/java/io/sentry/ScopeTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index 185dc56d74..90a581a262 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -1,7 +1,6 @@ package io.sentry import io.sentry.SentryLevel.WARNING -import io.sentry.protocol.Contexts import io.sentry.protocol.Request import io.sentry.protocol.SentryId import io.sentry.protocol.User @@ -346,7 +345,7 @@ class ScopeTest { var called = false val options = SentryOptions().apply { maxBreadcrumbs = 0 - beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback{ breadcrumb, _ -> + beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> called = true breadcrumb } From 501d5b8c5722c9c4e3e4284b3276b98eca5fcdae Mon Sep 17 00:00:00 2001 From: stefanosiano Date: Fri, 20 Jun 2025 12:55:13 +0200 Subject: [PATCH 4/5] added tests --- sentry/src/test/java/io/sentry/ScopeTest.kt | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index 185dc56d74..1773488792 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -1,12 +1,12 @@ package io.sentry import io.sentry.SentryLevel.WARNING -import io.sentry.protocol.Contexts import io.sentry.protocol.Request import io.sentry.protocol.SentryId import io.sentry.protocol.User import io.sentry.test.callMethod import org.junit.Assert.assertArrayEquals +import org.mockito.kotlin.any import org.mockito.kotlin.argThat import org.mockito.kotlin.check import org.mockito.kotlin.eq @@ -346,7 +346,7 @@ class ScopeTest { var called = false val options = SentryOptions().apply { maxBreadcrumbs = 0 - beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback{ breadcrumb, _ -> + beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> called = true breadcrumb } @@ -358,6 +358,22 @@ class ScopeTest { assertFalse(called) } + @Test + fun `when adding breadcrumb and maxBreadcrumb is not 0, beforeBreadcrumb is executed`() { + var called = false + val options = SentryOptions().apply { + beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> + called = true + breadcrumb + } + } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(1, scope.breadcrumbs.count()) + assertTrue(called) + } + @Test fun `when adding breadcrumb and maxBreadcrumb is 0, scopesObservers are not called`() { val observer = mock() @@ -372,6 +388,19 @@ class ScopeTest { verifyNoInteractions(observer) } + @Test + fun `when adding breadcrumb and maxBreadcrumb is not 0, scopesObservers are called`() { + val observer = mock() + val options = SentryOptions().apply { + addScopeObserver(observer) + } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(1, scope.breadcrumbs.count()) + verify(observer).addBreadcrumb(any()) + } + @Test fun `when adding eventProcessor, eventProcessor should be in the list`() { val processor = CustomEventProcessor() From ef4bdc753f05495e5d44bc386a57b3a91ff41584 Mon Sep 17 00:00:00 2001 From: stefanosiano Date: Mon, 30 Jun 2025 13:24:32 +0200 Subject: [PATCH 5/5] merged master --- sentry/src/test/java/io/sentry/ScopeTest.kt | 115 ++++++++++---------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index f4720cfb4d..8671017eae 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -333,65 +333,68 @@ class ScopeTest { assertEquals(1, scope.breadcrumbs.count()) } - @Test - fun `when adding breadcrumb and maxBreadcrumb is 0, beforeBreadcrumb is not executed`() { - var called = false - val options = SentryOptions().apply { - maxBreadcrumbs = 0 - beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> - called = true - breadcrumb - } - } - - val scope = Scope(options) - scope.addBreadcrumb(Breadcrumb()) - assertEquals(0, scope.breadcrumbs.count()) - assertFalse(called) - } + @Test + fun `when adding breadcrumb and maxBreadcrumb is 0, beforeBreadcrumb is not executed`() { + var called = false + val options = + SentryOptions().apply { + maxBreadcrumbs = 0 + beforeBreadcrumb = + SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> + called = true + breadcrumb + } + } - @Test - fun `when adding breadcrumb and maxBreadcrumb is not 0, beforeBreadcrumb is executed`() { - var called = false - val options = SentryOptions().apply { - beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> - called = true - breadcrumb - } - } - - val scope = Scope(options) - scope.addBreadcrumb(Breadcrumb()) - assertEquals(1, scope.breadcrumbs.count()) - assertTrue(called) - } + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(0, scope.breadcrumbs.count()) + assertFalse(called) + } - @Test - fun `when adding breadcrumb and maxBreadcrumb is 0, scopesObservers are not called`() { - val observer = mock() - val options = SentryOptions().apply { - maxBreadcrumbs = 0 - addScopeObserver(observer) - } - - val scope = Scope(options) - scope.addBreadcrumb(Breadcrumb()) - assertEquals(0, scope.breadcrumbs.count()) - verifyNoInteractions(observer) - } + @Test + fun `when adding breadcrumb and maxBreadcrumb is not 0, beforeBreadcrumb is executed`() { + var called = false + val options = + SentryOptions().apply { + beforeBreadcrumb = + SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ -> + called = true + breadcrumb + } + } - @Test - fun `when adding breadcrumb and maxBreadcrumb is not 0, scopesObservers are called`() { - val observer = mock() - val options = SentryOptions().apply { - addScopeObserver(observer) - } - - val scope = Scope(options) - scope.addBreadcrumb(Breadcrumb()) - assertEquals(1, scope.breadcrumbs.count()) - verify(observer).addBreadcrumb(any()) - } + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(1, scope.breadcrumbs.count()) + assertTrue(called) + } + + @Test + fun `when adding breadcrumb and maxBreadcrumb is 0, scopesObservers are not called`() { + val observer = mock() + val options = + SentryOptions().apply { + maxBreadcrumbs = 0 + addScopeObserver(observer) + } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(0, scope.breadcrumbs.count()) + verifyNoInteractions(observer) + } + + @Test + fun `when adding breadcrumb and maxBreadcrumb is not 0, scopesObservers are called`() { + val observer = mock() + val options = SentryOptions().apply { addScopeObserver(observer) } + + val scope = Scope(options) + scope.addBreadcrumb(Breadcrumb()) + assertEquals(1, scope.breadcrumbs.count()) + verify(observer).addBreadcrumb(any()) + } @Test fun `when adding eventProcessor, eventProcessor should be in the list`() {