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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Fixes

- Prevent duplicated breadcrumbs on tombstone-merged native crash events ([#5888](https://github.com/getsentry/sentry-java/pull/5888))
- Clear contexts when calling `Scope.clear()` ([#5902](https://github.com/getsentry/sentry-java/pull/5902))
- Preserve custom `Throwable` identities when R8 optimizes Android apps ([#5881](https://github.com/getsentry/sentry-java/pull/5881))
- Report the correct cpu usage for the first performance sample of a transaction, which was measured against the time since device boot ([#5926](https://github.com/getsentry/sentry-java/pull/5926))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,16 +349,19 @@ private void setExtras(final @NotNull SentryBaseEvent event) {

@SuppressWarnings("unchecked")
private void setBreadcrumbs(final @NotNull SentryBaseEvent event) {
final List<Breadcrumb> eventBreadcrumbs = event.getBreadcrumbs();
if (eventBreadcrumbs != null && !eventBreadcrumbs.isEmpty()) {
// the event already carries its own breadcrumbs (e.g. a tombstone-merged native
// crash event), so appending the persisted ones here would duplicate entries. Skip the
// disk read altogether since the result would be discarded anyway.
return;
}
final List<Breadcrumb> breadcrumbs =
(List<Breadcrumb>) readFromDisk(options, BREADCRUMBS_FILENAME, List.class);
if (breadcrumbs == null) {
return;
}
if (event.getBreadcrumbs() == null) {
event.setBreadcrumbs(breadcrumbs);
} else {
event.getBreadcrumbs().addAll(breadcrumbs);
}
event.setBreadcrumbs(breadcrumbs);
}

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,21 @@ class ApplicationExitInfoEventProcessorTest {
assertEquals("Google Chrome", processed.contexts.browser!!.name)
}

@Test
fun `when backfillable event already has breadcrumbs, does not duplicate them with persisted ones`() {
// simulates a tombstone-merged native crash event, which already carries its own
// breadcrumb history captured at crash time, overlapping with what was persisted to disk
val hint = HintUtils.createWithTypeCheckHint(BackfillableHint())

val processed =
processEvent(hint, populateScopeCache = true) {
breadcrumbs = listOf(Breadcrumb.debug("own-crash-time-breadcrumb"))
}

assertEquals(1, processed.breadcrumbs!!.size)
assertEquals("own-crash-time-breadcrumb", processed.breadcrumbs!![0].message)
}

@Test
fun `when backfillable event is enrichable, does not backfill user ip`() {
val hint = HintUtils.createWithTypeCheckHint(BackfillableHint())
Expand Down Expand Up @@ -670,10 +685,11 @@ class ApplicationExitInfoEventProcessorTest {

assertEquals("MainActivity", processed.transaction)
assertEquals(DEBUG, processed.level)
assertEquals(3, processed.breadcrumbs!!.size)
// breadcrumbs already set on the event are preserved as-is, not merged with the persisted
// ones, since the event already carries its own authoritative breadcrumb history
assertEquals(1, processed.breadcrumbs!!.size)
assertEquals("debug", processed.breadcrumbs!![0].type)
assertEquals("debug", processed.breadcrumbs!![1].type)
assertEquals("navigation", processed.breadcrumbs!![2].type)
assertEquals("test", processed.breadcrumbs!![0].message)

assertEquals("debug", processed.environment)
assertEquals("io.sentry.samples@1.1.0+220", processed.release)
Expand Down
3 changes: 2 additions & 1 deletion sentry/src/main/java/io/sentry/SentryClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,8 @@ public void captureBatchedMetricsEvents(final @NotNull SentryMetricsEvents metri
}
}
}
if (sentryBaseEvent.getBreadcrumbs() == null) {
final List<Breadcrumb> eventBreadcrumbs = sentryBaseEvent.getBreadcrumbs();
if (eventBreadcrumbs == null || eventBreadcrumbs.isEmpty()) {
sentryBaseEvent.setBreadcrumbs(new ArrayList<>(scope.getBreadcrumbs()));
} else if (!isCached) {
// A Cached event comes from the outbox and already carries its own breadcrumbs (e.g. native
Expand Down
Loading