Skip to content

Commit 3f751c9

Browse files
committed
fix(replay): Do not capture replay for cached events (#4474)
* fix(replay): Do not capture replay for cached events * Changelog * Formatting * Wording * Still caputre replay for outbox events
1 parent ac2561c commit 3f751c9

3 files changed

Lines changed: 59 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- This should reduce ANRs seen with this class in the stack trace for Android 14 and above
1212
- Pre-load modules on a background thread upon SDK init ([#4348](https://github.com/getsentry/sentry-java/pull/4348))
1313
- Session Replay: Fix inconsistent `segment_id` ([#4471](https://github.com/getsentry/sentry-java/pull/4471))
14+
- Session Replay: Do not capture current replay for cached events from the past ([#4474](https://github.com/getsentry/sentry-java/pull/4474))
1415

1516
## 7.22.5
1617

sentry/src/main/java/io/sentry/SentryClient.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import io.sentry.clientreport.DiscardReason;
44
import io.sentry.exception.SentryEnvelopeException;
55
import io.sentry.hints.AbnormalExit;
6+
import io.sentry.hints.ApplyScopeData;
67
import io.sentry.hints.Backfillable;
8+
import io.sentry.hints.Cached;
79
import io.sentry.hints.DiskFlushNotification;
810
import io.sentry.hints.TransactionEnd;
911
import io.sentry.metrics.EncodedMetrics;
@@ -198,9 +200,12 @@ private boolean shouldApplyScopeData(final @NotNull CheckIn event, final @NotNul
198200
}
199201

200202
final boolean isBackfillable = HintUtils.hasType(hint, Backfillable.class);
201-
// if event is backfillable we don't wanna trigger capture replay, because it's an event from
202-
// the past
203-
if (event != null && !isBackfillable && (event.isErrored() || event.isCrashed())) {
203+
final boolean isCached =
204+
HintUtils.hasType(hint, Cached.class) && !HintUtils.hasType(hint, ApplyScopeData.class);
205+
// if event is backfillable or cached we don't wanna trigger capture replay, because it's
206+
// an event from the past. If it's cached, but with ApplyScopeData, it comes from the outbox
207+
// folder and we still want to capture replay (e.g. a native captureException error)
208+
if (event != null && !isBackfillable && !isCached && (event.isErrored() || event.isCrashed())) {
204209
options.getReplayController().captureReplay(event.isCrashed());
205210
}
206211

sentry/src/test/java/io/sentry/SentryClientTest.kt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,6 +2800,52 @@ class SentryClientTest {
28002800
assertFalse(called)
28012801
}
28022802

2803+
@Test
2804+
fun `does not captureReplay for cached events`() {
2805+
var called = false
2806+
fixture.sentryOptions.setReplayController(object : ReplayController by NoOpReplayController.getInstance() {
2807+
override fun captureReplay(isTerminating: Boolean?) {
2808+
called = true
2809+
}
2810+
})
2811+
val sut = fixture.getSut()
2812+
2813+
sut.captureEvent(
2814+
SentryEvent().apply {
2815+
exceptions = listOf(
2816+
SentryException().apply {
2817+
mechanism = Mechanism().apply { isHandled = false }
2818+
}
2819+
)
2820+
},
2821+
HintUtils.createWithTypeCheckHint(CachedHint())
2822+
)
2823+
assertFalse(called)
2824+
}
2825+
2826+
@Test
2827+
fun `captures replay for cached events with apply scope`() {
2828+
var called = false
2829+
fixture.sentryOptions.setReplayController(object : ReplayController by NoOpReplayController.getInstance() {
2830+
override fun captureReplay(isTerminating: Boolean?) {
2831+
called = true
2832+
}
2833+
})
2834+
val sut = fixture.getSut()
2835+
2836+
sut.captureEvent(
2837+
SentryEvent().apply {
2838+
exceptions = listOf(
2839+
SentryException().apply {
2840+
mechanism = Mechanism().apply { isHandled = false }
2841+
}
2842+
)
2843+
},
2844+
HintUtils.createWithTypeCheckHint(CachedWithApplyScopeHint())
2845+
)
2846+
assertTrue(called)
2847+
}
2848+
28032849
@Test
28042850
fun `when beforeSendReplay is set, callback is invoked`() {
28052851
var invoked = false
@@ -3123,6 +3169,10 @@ class SentryClientTest {
31233169
private class BackfillableHint : Backfillable {
31243170
override fun shouldEnrich(): Boolean = false
31253171
}
3172+
3173+
private class CachedHint : Cached
3174+
3175+
private class CachedWithApplyScopeHint : Cached, ApplyScopeData
31263176
}
31273177

31283178
class DropEverythingEventProcessor : EventProcessor {

0 commit comments

Comments
 (0)