From cd4fd9e2d117cd5ce47f1606a7823effcf63800c Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Tue, 23 Apr 2024 15:32:30 +0200 Subject: [PATCH 1/2] feat(replay): Add `sendReplay` method for Hybrid SDKs --- .../sentry/android/replay/ReplayIntegration.kt | 12 ++++++++++-- .../replay/capture/BufferCaptureStrategy.kt | 17 +++++++++-------- .../android/replay/capture/CaptureStrategy.kt | 3 +-- .../replay/capture/SessionCaptureStrategy.kt | 13 +++++-------- .../java/io/sentry/NoOpReplayController.java | 5 +++++ .../main/java/io/sentry/ReplayController.java | 3 +++ 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayIntegration.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayIntegration.kt index cc3248e1a46..902d12b1ae9 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayIntegration.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayIntegration.kt @@ -138,12 +138,20 @@ public class ReplayIntegration( return } + sendReplay(event.isCrashed, event.eventId.toString(), hint) + } + + override fun sendReplay(isCrashed: Boolean?, eventId: String?, hint: Hint?) { + if (!isEnabled.get() || !isRecording.get()) { + return + } + if (SentryId.EMPTY_ID.equals(captureStrategy?.currentReplayId?.get())) { - options.logger.log(DEBUG, "Replay id is not set, not capturing for event %s", event.eventId) + options.logger.log(DEBUG, "Replay id is not set, not capturing for event %s", eventId) return } - captureStrategy?.sendReplayForEvent(event, hint, onSegmentSent = { captureStrategy?.currentSegment?.getAndIncrement() }) + captureStrategy?.sendReplayForEvent(isCrashed == true, eventId, hint, onSegmentSent = { captureStrategy?.currentSegment?.getAndIncrement() }) captureStrategy = captureStrategy?.convert() } diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt index 0c5dfc73149..2d69852abf1 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt @@ -3,7 +3,6 @@ package io.sentry.android.replay.capture import io.sentry.DateUtils import io.sentry.Hint import io.sentry.IHub -import io.sentry.SentryEvent import io.sentry.SentryLevel.ERROR import io.sentry.SentryLevel.INFO import io.sentry.SentryOptions @@ -41,14 +40,16 @@ internal class BufferCaptureStrategy( super.stop() } - override fun sendReplayForEvent(event: SentryEvent, hint: Hint, onSegmentSent: () -> Unit) { + override fun sendReplayForEvent( + isCrashed: Boolean, + eventId: String?, + hint: Hint?, + onSegmentSent: () -> Unit + ) { val sampled = random.sample(options.experimental.sessionReplay.errorSampleRate) - if (sampled) { - // don't ask me why - event.setTag("replayId", currentReplayId.get().toString()) - } else { - options.logger.log(INFO, "Replay wasn't sampled by errorSampleRate, not capturing for event %s", event.eventId) + if (!sampled) { + options.logger.log(INFO, "Replay wasn't sampled by errorSampleRate, not capturing for event %s", eventId) return } @@ -83,7 +84,7 @@ internal class BufferCaptureStrategy( BUFFER ) if (segment is ReplaySegment.Created) { - segment.capture(hub, hint) + segment.capture(hub, hint ?: Hint()) // we only want to increment segment_id in the case of success, but currentSegment // might be irrelevant since we changed strategies, so in the callback we increment diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/CaptureStrategy.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/CaptureStrategy.kt index 821ebcef663..d78d02ad6bf 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/CaptureStrategy.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/CaptureStrategy.kt @@ -1,7 +1,6 @@ package io.sentry.android.replay.capture import io.sentry.Hint -import io.sentry.SentryEvent import io.sentry.android.replay.ReplayCache import io.sentry.android.replay.ScreenshotRecorderConfig import io.sentry.protocol.SentryId @@ -22,7 +21,7 @@ internal interface CaptureStrategy { fun resume() - fun sendReplayForEvent(event: SentryEvent, hint: Hint, onSegmentSent: () -> Unit) + fun sendReplayForEvent(isCrashed: Boolean, eventId: String?, hint: Hint?, onSegmentSent: () -> Unit) fun onScreenshotRecorded(store: ReplayCache.(frameTimestamp: Long) -> Unit) diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/SessionCaptureStrategy.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/SessionCaptureStrategy.kt index 771b760b882..43af2e3c374 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/SessionCaptureStrategy.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/capture/SessionCaptureStrategy.kt @@ -3,7 +3,6 @@ package io.sentry.android.replay.capture import io.sentry.DateUtils import io.sentry.Hint import io.sentry.IHub -import io.sentry.SentryEvent import io.sentry.SentryLevel.DEBUG import io.sentry.SentryLevel.INFO import io.sentry.SentryOptions @@ -58,16 +57,14 @@ internal class SessionCaptureStrategy( super.stop() } - override fun sendReplayForEvent(event: SentryEvent, hint: Hint, onSegmentSent: () -> Unit) { - // don't ask me why - event.setTag("replayId", currentReplayId.get().toString()) - if (!event.isCrashed) { - options.logger.log(DEBUG, "Replay is already running in 'session' mode, not capturing for event %s", event.eventId) + override fun sendReplayForEvent(isCrashed: Boolean, eventId: String?, hint: Hint?, onSegmentSent: () -> Unit) { + if (!isCrashed) { + options.logger.log(DEBUG, "Replay is already running in 'session' mode, not capturing for event %s", eventId) } else { - options.logger.log(DEBUG, "Replay is already running in 'session' mode, capturing last segment for crashed event %s", event.eventId) + options.logger.log(DEBUG, "Replay is already running in 'session' mode, capturing last segment for crashed event %s", eventId) createCurrentSegment("send_replay_for_event") { segment -> if (segment is ReplaySegment.Created) { - segment.capture(hub, hint) + segment.capture(hub, hint ?: Hint()) } } } diff --git a/sentry/src/main/java/io/sentry/NoOpReplayController.java b/sentry/src/main/java/io/sentry/NoOpReplayController.java index 516b1e06f5e..a1a715318c3 100644 --- a/sentry/src/main/java/io/sentry/NoOpReplayController.java +++ b/sentry/src/main/java/io/sentry/NoOpReplayController.java @@ -2,6 +2,7 @@ import io.sentry.protocol.SentryId; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public final class NoOpReplayController implements ReplayController { @@ -33,6 +34,10 @@ public boolean isRecording() { @Override public void sendReplayForEvent(@NotNull SentryEvent event, @NotNull Hint hint) {} + @Override + public void sendReplay( + @Nullable Boolean isCrashed, @Nullable String eventId, @Nullable Hint hint) {} + @Override public @NotNull SentryId getReplayId() { return SentryId.EMPTY_ID; diff --git a/sentry/src/main/java/io/sentry/ReplayController.java b/sentry/src/main/java/io/sentry/ReplayController.java index 76ae4501682..a85cdacc939 100644 --- a/sentry/src/main/java/io/sentry/ReplayController.java +++ b/sentry/src/main/java/io/sentry/ReplayController.java @@ -3,6 +3,7 @@ import io.sentry.protocol.SentryId; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; @ApiStatus.Internal public interface ReplayController { @@ -18,6 +19,8 @@ public interface ReplayController { void sendReplayForEvent(@NotNull SentryEvent event, @NotNull Hint hint); + void sendReplay(@Nullable Boolean isCrashed, @Nullable String eventId, @Nullable Hint hint); + @NotNull SentryId getReplayId(); } From e836f49a992eaaf2a76bf4dbc52e4075e7312d0b Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Tue, 23 Apr 2024 16:44:48 +0200 Subject: [PATCH 2/2] fix apiDump --- sentry-android-replay/api/sentry-android-replay.api | 1 + sentry/api/sentry.api | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sentry-android-replay/api/sentry-android-replay.api b/sentry-android-replay/api/sentry-android-replay.api index 3918cde06b1..9e4dcb074d8 100644 --- a/sentry-android-replay/api/sentry-android-replay.api +++ b/sentry-android-replay/api/sentry-android-replay.api @@ -52,6 +52,7 @@ public final class io/sentry/android/replay/ReplayIntegration : android/content/ public fun pause ()V public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V public fun resume ()V + public fun sendReplay (Ljava/lang/Boolean;Ljava/lang/String;Lio/sentry/Hint;)V public fun sendReplayForEvent (Lio/sentry/SentryEvent;Lio/sentry/Hint;)V public fun start ()V public fun stop ()V diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 7d00d432077..2158b7f929c 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -1259,6 +1259,7 @@ public final class io/sentry/NoOpReplayController : io/sentry/ReplayController { public fun isRecording ()Z public fun pause ()V public fun resume ()V + public fun sendReplay (Ljava/lang/Boolean;Ljava/lang/String;Lio/sentry/Hint;)V public fun sendReplayForEvent (Lio/sentry/SentryEvent;Lio/sentry/Hint;)V public fun start ()V public fun stop ()V @@ -1662,6 +1663,7 @@ public abstract interface class io/sentry/ReplayController { public abstract fun isRecording ()Z public abstract fun pause ()V public abstract fun resume ()V + public abstract fun sendReplay (Ljava/lang/Boolean;Ljava/lang/String;Lio/sentry/Hint;)V public abstract fun sendReplayForEvent (Lio/sentry/SentryEvent;Lio/sentry/Hint;)V public abstract fun start ()V public abstract fun stop ()V