Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ public abstract interface class io/sentry/IScopeObserver {
public abstract fun clearAttachments ()V
public abstract fun removeExtra (Ljava/lang/String;)V
public abstract fun removeTag (Ljava/lang/String;)V
public abstract fun setBreadcrumbs (Ljava/util/Collection;)V
public abstract fun clearBreadcrumbs ()V
public abstract fun setContexts (Lio/sentry/protocol/Contexts;)V
public abstract fun setEnvironment (Ljava/lang/String;)V
public abstract fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
Expand Down Expand Up @@ -2646,7 +2646,7 @@ public abstract class io/sentry/ScopeObserverAdapter : io/sentry/IScopeObserver
public fun clearAttachments ()V
public fun removeExtra (Ljava/lang/String;)V
public fun removeTag (Ljava/lang/String;)V
public fun setBreadcrumbs (Ljava/util/Collection;)V
public fun clearBreadcrumbs ()V
public fun setContexts (Lio/sentry/protocol/Contexts;)V
public fun setEnvironment (Ljava/lang/String;)V
public fun setExtra (Ljava/lang/String;Ljava/lang/String;)V
Expand Down
5 changes: 2 additions & 3 deletions sentry/src/main/java/io/sentry/IScopeObserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
import org.jetbrains.annotations.Nullable;

/**
* A Scope observer that tracks changes on Scope. All methods are "default", so implementors can
* subscribe to only those properties, that they are interested in.
* A Scope observer that tracks changes on Scope.
*/
public interface IScopeObserver {
void setUser(@Nullable User user);

void addBreadcrumb(@NotNull Breadcrumb crumb);

void setBreadcrumbs(@NotNull Collection<Breadcrumb> breadcrumbs);
void clearBreadcrumbs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking observer API without deprecation

High Severity

Replacing IScopeObserver.setBreadcrumbs with abstract clearBreadcrumbs is binary-incompatible. Existing implementors can throw AbstractMethodError when breadcrumbs are cleared, and ScopeObserverAdapter subclasses that overrode setBreadcrumbs stop receiving clear notifications. Issue #5844 targeted this for 9.0; the repo is still at 8.62.0.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bugbot

Reviewed by Cursor Bugbot for commit 5a60510. Configure here.


void setTag(@NotNull String key, @NotNull String value);

Expand Down
3 changes: 1 addition & 2 deletions sentry/src/main/java/io/sentry/Scope.java
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Hint hint) {

for (final IScopeObserver observer : options.getScopeObservers()) {
observer.addBreadcrumb(breadcrumb);
observer.setBreadcrumbs(breadcrumbs);
}
} else {
options.getLogger().log(SentryLevel.INFO, "Breadcrumb was dropped by beforeBreadcrumb");
Expand All @@ -558,7 +557,7 @@ public void clearBreadcrumbs() {
breadcrumbs.clear();

for (final IScopeObserver observer : options.getScopeObservers()) {
observer.setBreadcrumbs(breadcrumbs);
observer.clearBreadcrumbs();
}
}

Expand Down
2 changes: 1 addition & 1 deletion sentry/src/main/java/io/sentry/ScopeObserverAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public void setUser(@Nullable User user) {}
public void addBreadcrumb(@NotNull Breadcrumb crumb) {}

@Override
public void setBreadcrumbs(@NotNull Collection<Breadcrumb> breadcrumbs) {}
public void clearBreadcrumbs() {}

@Override
public void setTag(@NotNull String key, @NotNull String value) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,12 @@ public void addBreadcrumb(@NotNull Breadcrumb crumb) {
}

@Override
public void setBreadcrumbs(@NotNull Collection<Breadcrumb> breadcrumbs) {
if (breadcrumbs.isEmpty()) {
// we only clear the queue if the new collection is empty (someone called clearBreadcrumbs)
// If it's not empty, we'd add breadcrumbs one-by-one in the method above
if (!options.isEnableScopePersistence()) {
return;
}
pendingBreadcrumbs.offer(CLEAR_MARKER);
requestFlush();
public void clearBreadcrumbs() {
if (!options.isEnableScopePersistence()) {
return;
}
pendingBreadcrumbs.offer(CLEAR_MARKER);
requestFlush();
}

@Override
Expand Down
6 changes: 2 additions & 4 deletions sentry/src/test/java/io/sentry/ScopeTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -761,12 +761,10 @@ class ScopeTest {
val breadcrumb = Breadcrumb()
scope.addBreadcrumb(breadcrumb)
verify(observer).addBreadcrumb(eq(breadcrumb))
verify(observer).setBreadcrumbs(argThat { elementAt(0) == breadcrumb })

scope.addBreadcrumb(Breadcrumb.debug("test"))
verify(observer).addBreadcrumb(argThat { message == "test" })
verify(observer, times(2))
.setBreadcrumbs(argThat { elementAt(0) == breadcrumb && elementAt(1).message == "test" })
verify(observer, never()).clearBreadcrumbs()
}

@Test
Expand All @@ -780,7 +778,7 @@ class ScopeTest {
assertFalse(scope.breadcrumbs.isEmpty())

scope.clearBreadcrumbs()
verify(observer, times(2)).setBreadcrumbs(argThat { isEmpty() })
verify(observer).clearBreadcrumbs()
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class PersistingScopeObserverBatchingTest {
val sut = getSut(executor)

sut.addBreadcrumb(Breadcrumb().apply { message = "dropped" })
sut.setBreadcrumbs(emptyList())
sut.clearBreadcrumbs()
sut.addBreadcrumb(Breadcrumb().apply { message = "kept" })
executor.runAll()

Expand All @@ -95,7 +95,7 @@ class PersistingScopeObserverBatchingTest {
// fires while the flush is draining, i.e. after the first breadcrumb has been written
options.setSerializer(
SerializerHook(options.serializer) {
sut.setBreadcrumbs(emptyList())
sut.clearBreadcrumbs()
sut.addBreadcrumb(Breadcrumb().apply { message = "kept" })
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class PersistingScopeObserverTest<T>(
breadcrumbs.forEach { addBreadcrumb(it) }
},
BREADCRUMBS_FILENAME,
DeleteScopeValue { setBreadcrumbs(emptyList()) },
DeleteScopeValue { clearBreadcrumbs() },
DeletedEntityProvider { emptyList<Breadcrumb>() },
)

Expand All @@ -141,7 +141,7 @@ class PersistingScopeObserverTest<T>(
)
},
BREADCRUMBS_FILENAME,
DeleteScopeValue { setBreadcrumbs(emptyList()) },
DeleteScopeValue { clearBreadcrumbs() },
DeletedEntityProvider { emptyList<Breadcrumb>() },
)

Expand Down