diff --git a/CHANGELOG.md b/CHANGELOG.md index 1da07233a0..ff11b3220f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Performance + +- Defer starting Session Replay off the `Sentry.init` critical path to reduce app start time ([#5904](https://github.com/getsentry/sentry-java/pull/5904)) + ### Fixes - Clear contexts when calling `Scope.clear()` ([#5902](https://github.com/getsentry/sentry-java/pull/5902)) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java index ab18a5827b..1989e06078 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java @@ -3,6 +3,8 @@ import android.annotation.SuppressLint; import android.app.Application; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.os.Process; import android.os.SystemClock; import android.os.Trace; @@ -203,7 +205,11 @@ public static void init( scopes.startSession(); } } - scopes.getOptions().getReplayController().start(); + // Defer starting replay off the SDK init critical path so it doesn't add to app start + // time. start() is idempotent, so the later start() from the app lifecycle integration + // (once the first activity is in foreground) is a no-op if this one ran first. + new Handler(Looper.getMainLooper()) + .post(() -> scopes.getOptions().getReplayController().start()); } } catch (IllegalAccessException e) { logger.log(SentryLevel.FATAL, "Fatal error during SentryAndroid.init(...)", e); diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt index 2bd26051c0..d3239ebb1e 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt @@ -352,6 +352,8 @@ class SentryAndroidTest { @Config(sdk = [26]) fun `init starts session replay if app is in foreground`() { initSentryWithForegroundImportance(true) { _ -> + // replay start is posted to the main looper, so drain it before asserting + Shadows.shadowOf(Looper.getMainLooper()).idle() assertTrue(Sentry.getCurrentHub().options.replayController.isRecording()) } }