From 3355a1c24aa50e7a0a7803be8cc3dc0722c9b386 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 5 Aug 2026 20:32:00 +0200 Subject: [PATCH 1/3] fix(core): Clear contexts in Scope.clear() --- sentry/api/sentry.api | 2 ++ sentry/src/main/java/io/sentry/CombinedContextsView.java | 5 +++++ sentry/src/main/java/io/sentry/Scope.java | 1 + sentry/src/main/java/io/sentry/protocol/Contexts.java | 4 ++++ 4 files changed, 12 insertions(+) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 51cffae3302..43de4164a4f 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -227,6 +227,7 @@ public final class io/sentry/CheckInStatus : java/lang/Enum { public final class io/sentry/CombinedContextsView : io/sentry/protocol/Contexts { public fun (Lio/sentry/protocol/Contexts;Lio/sentry/protocol/Contexts;Lio/sentry/protocol/Contexts;Lio/sentry/ScopeType;)V + public fun clear ()V public fun containsKey (Ljava/lang/Object;)Z public fun entrySet ()Ljava/util/Set; public fun get (Ljava/lang/Object;)Ljava/lang/Object; @@ -5795,6 +5796,7 @@ public class io/sentry/protocol/Contexts : io/sentry/JsonSerializable { protected final field responseLock Lio/sentry/util/AutoClosableReentrantLock; public fun ()V public fun (Lio/sentry/protocol/Contexts;)V + public fun clear ()V public fun containsKey (Ljava/lang/Object;)Z public fun entrySet ()Ljava/util/Set; public fun equals (Ljava/lang/Object;)Z diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java index 3cb10e88b81..d9a8b14c628 100644 --- a/sentry/src/main/java/io/sentry/CombinedContextsView.java +++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java @@ -293,6 +293,11 @@ public boolean containsKey(final @Nullable Object key) { return getDefaultContexts().remove(key); } + @Override + public void clear() { + getDefaultContexts().clear(); + } + @Override public @NotNull Enumeration keys() { return mergeContexts().keys(); diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 195e5b5b05a..42e1078216c 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -575,6 +575,7 @@ public void clear() { tags.clear(); attributes.clear(); extra.clear(); + contexts.clear(); eventProcessors.clear(); clearTransaction(); clearAttachments(); diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java index 83a770eb0fc..f6ba635383a 100644 --- a/sentry/src/main/java/io/sentry/protocol/Contexts.java +++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java @@ -248,6 +248,10 @@ public boolean containsKey(final @Nullable Object key) { return internalStorage.remove(key); } + public void clear() { + internalStorage.clear(); + } + public @NotNull Enumeration keys() { return internalStorage.keys(); } From 2264ef6f85990df795c02d16371fa12e284a7041 Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 5 Aug 2026 20:44:57 +0200 Subject: [PATCH 2/3] Add tests --- .../java/io/sentry/CombinedScopeViewTest.kt | 31 +++++++++++++++++++ sentry/src/test/java/io/sentry/ScopeTest.kt | 14 +++++++++ .../java/io/sentry/protocol/ContextsTest.kt | 16 ++++++++++ 3 files changed, 61 insertions(+) diff --git a/sentry/src/test/java/io/sentry/CombinedScopeViewTest.kt b/sentry/src/test/java/io/sentry/CombinedScopeViewTest.kt index fd187235a92..9cb6fd2aa17 100644 --- a/sentry/src/test/java/io/sentry/CombinedScopeViewTest.kt +++ b/sentry/src/test/java/io/sentry/CombinedScopeViewTest.kt @@ -1,5 +1,6 @@ package io.sentry +import com.google.common.truth.Truth.assertThat import io.sentry.protocol.Device import io.sentry.protocol.Request import io.sentry.protocol.SentryId @@ -575,6 +576,36 @@ class CombinedScopeViewTest { assertNotNull(fixture.globalScope.level) } + @Test + fun `clear removes contexts from default scope`() { + val combined = fixture.getSut() + + fixture.scope.setContexts("scopeContext", "scopeValue") + fixture.isolationScope.setContexts("isolationContext", "isolationValue") + fixture.globalScope.setContexts("globalContext", "globalValue") + + combined.clear() + + assertThat(fixture.scope.contexts.containsKey("scopeContext")).isTrue() + assertThat(fixture.isolationScope.contexts.isEmpty).isTrue() + assertThat(fixture.globalScope.contexts.containsKey("globalContext")).isTrue() + } + + @Test + fun `contexts view clear removes from default scope`() { + val combined = fixture.getSut() + + fixture.scope.setContexts("scopeContext", "scopeValue") + fixture.isolationScope.setContexts("isolationContext", "isolationValue") + fixture.globalScope.setContexts("globalContext", "globalValue") + + combined.contexts.clear() + + assertThat(fixture.scope.contexts.containsKey("scopeContext")).isTrue() + assertThat(fixture.isolationScope.contexts.isEmpty).isTrue() + assertThat(fixture.globalScope.contexts.containsKey("globalContext")).isTrue() + } + @Test fun `tags are combined from all scopes`() { val combined = fixture.getSut() diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index 7af4f6ccdca..f3309caef67 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -1,5 +1,6 @@ package io.sentry +import com.google.common.truth.Truth.assertThat import io.sentry.SentryLevel.WARNING import io.sentry.protocol.Request import io.sentry.protocol.SentryId @@ -292,6 +293,7 @@ class ScopeTest { scope.screen = "MainActivity" scope.setExtra("some", "extra") scope.setAttribute("some", "attribute") + scope.setContexts("some", "context") scope.addEventProcessor(eventProcessor()) scope.addAttachment(Attachment("path")) scope.addFeatureFlag("flag", true) @@ -308,6 +310,7 @@ class ScopeTest { assertEquals(0, scope.tags.size) assertEquals(0, scope.attributes.size) assertEquals(0, scope.extras.size) + assertEquals(0, scope.contexts.size) assertEquals(0, scope.eventProcessors.size) assertEquals(0, scope.attachments.size) assertEquals(0, scope.featureFlags!!.values.size) @@ -1290,6 +1293,17 @@ class ScopeTest { assertEquals(0, scope.attributes.size) } + @Test + fun `clear removes contexts`() { + val scope = Scope(SentryOptions()) + scope.setContexts("key1", "value1") + assertThat(scope.contexts.size).isEqualTo(1) + + scope.clear() + + assertThat(scope.contexts.isEmpty).isTrue() + } + private fun eventProcessor(): EventProcessor = object : EventProcessor { override fun process(event: SentryEvent, hint: Hint): SentryEvent? = event diff --git a/sentry/src/test/java/io/sentry/protocol/ContextsTest.kt b/sentry/src/test/java/io/sentry/protocol/ContextsTest.kt index 0035b733b43..897e9ae4907 100644 --- a/sentry/src/test/java/io/sentry/protocol/ContextsTest.kt +++ b/sentry/src/test/java/io/sentry/protocol/ContextsTest.kt @@ -1,5 +1,6 @@ package io.sentry.protocol +import com.google.common.truth.Truth.assertThat import io.sentry.ProfileContext import io.sentry.SpanContext import kotlin.test.Test @@ -137,4 +138,19 @@ class ContextsTest { assertEquals(listOf("a"), contexts.keys().toList()) } + + @Test + fun `clear removes all entries`() { + val contexts = Contexts() + contexts["some-property"] = "some-value" + contexts.setApp(App()) + contexts.setTrace(SpanContext("op")) + + contexts.clear() + + assertThat(contexts.isEmpty).isTrue() + assertThat(contexts["some-property"]).isNull() + assertThat(contexts.app).isNull() + assertThat(contexts.trace).isNull() + } } From 3c4467525ef90fa88720bf3da2ae0bc46f4a665c Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Wed, 5 Aug 2026 21:04:15 +0200 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a200976b614..8802c99c9c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- Reset contexts when a scope is cleared ([#5895](https://github.com/getsentry/sentry-java/pull/5895)) + ## 8.52.0 ### Fixes