diff --git a/CHANGELOG.md b/CHANGELOG.md index c71f589a2b..e3fe23b8ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,30 @@ ## Unreleased +### Features + +- Session Replay GA ([#4017](https://github.com/getsentry/sentry-java/pull/4017)) + +To enable Replay use the `sessionReplay.sessionSampleRate` or `sessionReplay.onErrorSampleRate` options. + + ```kotlin + import io.sentry.SentryReplayOptions + import io.sentry.android.core.SentryAndroid + + SentryAndroid.init(context) { options -> + + options.sessionReplay.sessionSampleRate = 1.0 + options.sessionReplay.onErrorSampleRate = 1.0 + + // To change default redaction behavior (defaults to true) + options.sessionReplay.redactAllImages = true + options.sessionReplay.redactAllText = true + + // To change quality of the recording (defaults to MEDIUM) + options.sessionReplay.quality = SentryReplayOptions.SentryReplayQuality.MEDIUM // (LOW|MEDIUM|HIGH) + } + ``` + ### Fixes - Fix warm start detection ([#3937](https://github.com/getsentry/sentry-java/pull/3937)) @@ -13,6 +37,10 @@ - Session Replay: Allow overriding `SdkVersion` for replay events ([#4014](https://github.com/getsentry/sentry-java/pull/4014)) - Session Replay: Send replay options as tags ([#4015](https://github.com/getsentry/sentry-java/pull/4015)) +### Breaking changes + +- Session Replay options were moved from under `experimental` to the main `options` object ([#4017](https://github.com/getsentry/sentry-java/pull/4017)) + ## 7.19.1 ### Fixes diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java index eb60c5d9c4..2d2df5700a 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ManifestMetadataReader.java @@ -399,28 +399,26 @@ static void applyMetadata( options.setEnableMetrics( readBool(metadata, logger, ENABLE_METRICS, options.isEnableMetrics())); - if (options.getExperimental().getSessionReplay().getSessionSampleRate() == null) { + if (options.getSessionReplay().getSessionSampleRate() == null) { final Double sessionSampleRate = readDouble(metadata, logger, REPLAYS_SESSION_SAMPLE_RATE); if (sessionSampleRate != -1) { - options.getExperimental().getSessionReplay().setSessionSampleRate(sessionSampleRate); + options.getSessionReplay().setSessionSampleRate(sessionSampleRate); } } - if (options.getExperimental().getSessionReplay().getOnErrorSampleRate() == null) { + if (options.getSessionReplay().getOnErrorSampleRate() == null) { final Double onErrorSampleRate = readDouble(metadata, logger, REPLAYS_ERROR_SAMPLE_RATE); if (onErrorSampleRate != -1) { - options.getExperimental().getSessionReplay().setOnErrorSampleRate(onErrorSampleRate); + options.getSessionReplay().setOnErrorSampleRate(onErrorSampleRate); } } options - .getExperimental() .getSessionReplay() .setMaskAllText(readBool(metadata, logger, REPLAYS_MASK_ALL_TEXT, true)); options - .getExperimental() .getSessionReplay() .setMaskAllImages(readBool(metadata, logger, REPLAYS_MASK_ALL_IMAGES, true)); } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt index ee4b4ae39a..d60f47bd2c 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ManifestMetadataReaderTest.kt @@ -1459,14 +1459,14 @@ class ManifestMetadataReaderTest { ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) // Assert - assertEquals(expectedSampleRate.toDouble(), fixture.options.experimental.sessionReplay.onErrorSampleRate) + assertEquals(expectedSampleRate.toDouble(), fixture.options.sessionReplay.onErrorSampleRate) } @Test fun `applyMetadata does not override replays onErrorSampleRate from options`() { // Arrange val expectedSampleRate = 0.99f - fixture.options.experimental.sessionReplay.onErrorSampleRate = expectedSampleRate.toDouble() + fixture.options.sessionReplay.onErrorSampleRate = expectedSampleRate.toDouble() val bundle = bundleOf(ManifestMetadataReader.REPLAYS_ERROR_SAMPLE_RATE to 0.1f) val context = fixture.getContext(metaData = bundle) @@ -1474,7 +1474,7 @@ class ManifestMetadataReaderTest { ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) // Assert - assertEquals(expectedSampleRate.toDouble(), fixture.options.experimental.sessionReplay.onErrorSampleRate) + assertEquals(expectedSampleRate.toDouble(), fixture.options.sessionReplay.onErrorSampleRate) } @Test @@ -1486,7 +1486,7 @@ class ManifestMetadataReaderTest { ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) // Assert - assertNull(fixture.options.experimental.sessionReplay.onErrorSampleRate) + assertNull(fixture.options.sessionReplay.onErrorSampleRate) } @Test @@ -1499,8 +1499,8 @@ class ManifestMetadataReaderTest { ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) // Assert - assertTrue(fixture.options.experimental.sessionReplay.unmaskViewClasses.contains(SentryReplayOptions.IMAGE_VIEW_CLASS_NAME)) - assertTrue(fixture.options.experimental.sessionReplay.unmaskViewClasses.contains(SentryReplayOptions.TEXT_VIEW_CLASS_NAME)) + assertTrue(fixture.options.sessionReplay.unmaskViewClasses.contains(SentryReplayOptions.IMAGE_VIEW_CLASS_NAME)) + assertTrue(fixture.options.sessionReplay.unmaskViewClasses.contains(SentryReplayOptions.TEXT_VIEW_CLASS_NAME)) } @Test @@ -1512,8 +1512,8 @@ class ManifestMetadataReaderTest { ManifestMetadataReader.applyMetadata(context, fixture.options, fixture.buildInfoProvider) // Assert - assertTrue(fixture.options.experimental.sessionReplay.maskViewClasses.contains(SentryReplayOptions.IMAGE_VIEW_CLASS_NAME)) - assertTrue(fixture.options.experimental.sessionReplay.maskViewClasses.contains(SentryReplayOptions.TEXT_VIEW_CLASS_NAME)) + assertTrue(fixture.options.sessionReplay.maskViewClasses.contains(SentryReplayOptions.IMAGE_VIEW_CLASS_NAME)) + assertTrue(fixture.options.sessionReplay.maskViewClasses.contains(SentryReplayOptions.TEXT_VIEW_CLASS_NAME)) } @Test @@ -1562,7 +1562,7 @@ class ManifestMetadataReaderTest { assertEquals(expectedSampleRate.toDouble(), fixture.options.sampleRate) assertEquals(expectedSampleRate.toDouble(), fixture.options.tracesSampleRate) assertEquals(expectedSampleRate.toDouble(), fixture.options.profilesSampleRate) - assertEquals(expectedSampleRate.toDouble(), fixture.options.experimental.sessionReplay.sessionSampleRate) - assertEquals(expectedSampleRate.toDouble(), fixture.options.experimental.sessionReplay.onErrorSampleRate) + assertEquals(expectedSampleRate.toDouble(), fixture.options.sessionReplay.sessionSampleRate) + assertEquals(expectedSampleRate.toDouble(), fixture.options.sessionReplay.onErrorSampleRate) } } 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 17c11475c9..ec2b3db4ce 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 @@ -371,7 +371,7 @@ class SentryAndroidTest { options.release = "prod" options.dsn = "https://key@sentry.io/123" options.isEnableAutoSessionTracking = true - options.experimental.sessionReplay.onErrorSampleRate = 1.0 + options.sessionReplay.onErrorSampleRate = 1.0 optionsConfig(options) } diff --git a/sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/ReplayTest.kt b/sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/ReplayTest.kt index ffea8f2e04..96fb906609 100644 --- a/sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/ReplayTest.kt +++ b/sentry-android-integration-tests/sentry-uitest-android/src/androidTest/java/io/sentry/uitest/android/ReplayTest.kt @@ -65,7 +65,7 @@ class ReplayTest : BaseUiTest() { activityScenario.moveToState(Lifecycle.State.RESUMED) initSentry { - it.experimental.sessionReplay.sessionSampleRate = 1.0 + it.sessionReplay.sessionSampleRate = 1.0 it.beforeSendReplay = SentryOptions.BeforeSendReplayCallback { event, _ -> diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayCache.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayCache.kt index 8031455c68..88638e7e16 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayCache.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/ReplayCache.kt @@ -85,7 +85,7 @@ public class ReplayCache( it.createNewFile() } screenshot.outputStream().use { - bitmap.compress(JPEG, options.experimental.sessionReplay.quality.screenshotQuality, it) + bitmap.compress(JPEG, options.sessionReplay.quality.screenshotQuality, it) it.flush() } 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 4148fbb26c..c0b77abc2a 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 @@ -118,8 +118,8 @@ public class ReplayIntegration( return } - if (!options.experimental.sessionReplay.isSessionReplayEnabled && - !options.experimental.sessionReplay.isSessionReplayForErrorsEnabled + if (!options.sessionReplay.isSessionReplayEnabled && + !options.sessionReplay.isSessionReplayForErrorsEnabled ) { options.logger.log(INFO, "Session replay is disabled, no sample rate specified") return @@ -132,7 +132,7 @@ public class ReplayIntegration( options.connectionStatusProvider.addConnectionStatusObserver(this) hub.rateLimiter?.addRateLimitObserver(this) - if (options.experimental.sessionReplay.isTrackOrientationChange) { + if (options.sessionReplay.isTrackOrientationChange) { try { context.registerComponentCallbacks(this) } catch (e: Throwable) { @@ -167,13 +167,13 @@ public class ReplayIntegration( return } - val isFullSession = random.sample(options.experimental.sessionReplay.sessionSampleRate) - if (!isFullSession && !options.experimental.sessionReplay.isSessionReplayForErrorsEnabled) { + val isFullSession = random.sample(options.sessionReplay.sessionSampleRate) + if (!isFullSession && !options.sessionReplay.isSessionReplayForErrorsEnabled) { options.logger.log(INFO, "Session replay is not started, full session was not sampled and onErrorSampleRate is not specified") return } - val recorderConfig = recorderConfigProvider?.invoke(false) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay) + val recorderConfig = recorderConfigProvider?.invoke(false) ?: ScreenshotRecorderConfig.from(context, options.sessionReplay) captureStrategy = replayCaptureStrategyProvider?.invoke(isFullSession) ?: if (isFullSession) { SessionCaptureStrategy(options, hub, dateProvider, replayExecutor, replayCacheProvider) } else { @@ -264,7 +264,7 @@ public class ReplayIntegration( options.connectionStatusProvider.removeConnectionStatusObserver(this) hub?.rateLimiter?.removeRateLimitObserver(this) - if (options.experimental.sessionReplay.isTrackOrientationChange) { + if (options.sessionReplay.isTrackOrientationChange) { try { context.unregisterComponentCallbacks(this) } catch (ignored: Throwable) { @@ -285,7 +285,7 @@ public class ReplayIntegration( recorder?.stop() // refresh config based on new device configuration - val recorderConfig = recorderConfigProvider?.invoke(true) ?: ScreenshotRecorderConfig.from(context, options.experimental.sessionReplay) + val recorderConfig = recorderConfigProvider?.invoke(true) ?: ScreenshotRecorderConfig.from(context, options.sessionReplay) captureStrategy?.onConfigurationChanged(recorderConfig) recorder?.start(recorderConfig) 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 8ef346f8a3..996e31afbd 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 @@ -65,7 +65,7 @@ internal class BufferCaptureStrategy( isTerminating: Boolean, onSegmentSent: (Date) -> Unit ) { - val sampled = random.sample(options.experimental.sessionReplay.onErrorSampleRate) + val sampled = random.sample(options.sessionReplay.onErrorSampleRate) if (!sampled) { options.logger.log(INFO, "Replay wasn't sampled by onErrorSampleRate, not capturing for event") @@ -107,7 +107,7 @@ internal class BufferCaptureStrategy( cache?.store(frameTimestamp) val now = dateProvider.currentTimeMillis - val bufferLimit = now - options.experimental.sessionReplay.errorReplayDuration + val bufferLimit = now - options.sessionReplay.errorReplayDuration screenAtStart = cache?.rotate(bufferLimit) bufferedSegments.rotate(bufferLimit) } @@ -137,7 +137,7 @@ internal class BufferCaptureStrategy( override fun onTouchEvent(event: MotionEvent) { super.onTouchEvent(event) - val bufferLimit = dateProvider.currentTimeMillis - options.experimental.sessionReplay.errorReplayDuration + val bufferLimit = dateProvider.currentTimeMillis - options.sessionReplay.errorReplayDuration rotateEvents(currentEvents, bufferLimit) } @@ -189,7 +189,7 @@ internal class BufferCaptureStrategy( } private fun createCurrentSegment(taskName: String, onSegmentCreated: (ReplaySegment) -> Unit) { - val errorReplayDuration = options.experimental.sessionReplay.errorReplayDuration + val errorReplayDuration = options.sessionReplay.errorReplayDuration val now = dateProvider.currentTimeMillis val currentSegmentTimestamp = if (cache?.frames?.isNotEmpty() == true) { // in buffer mode we have to set the timestamp of the first frame as the actual start 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 a8c8f1387c..03ca0cdf55 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 @@ -92,10 +92,10 @@ internal class SessionCaptureStrategy( } val now = dateProvider.currentTimeMillis - if ((now - currentSegmentTimestamp.time >= options.experimental.sessionReplay.sessionSegmentDuration)) { + if ((now - currentSegmentTimestamp.time >= options.sessionReplay.sessionSegmentDuration)) { val segment = createSegmentInternal( - options.experimental.sessionReplay.sessionSegmentDuration, + options.sessionReplay.sessionSegmentDuration, currentSegmentTimestamp, currentReplayId, currentSegment, @@ -110,7 +110,7 @@ internal class SessionCaptureStrategy( } } - if ((now - replayStartTimestamp.get() >= options.experimental.sessionReplay.sessionDuration)) { + if ((now - replayStartTimestamp.get() >= options.sessionReplay.sessionDuration)) { options.replayController.stop() options.logger.log(INFO, "Session replay deadline exceeded (1h), stopping recording") } diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ComposeViewHierarchyNode.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ComposeViewHierarchyNode.kt index 652e8cd040..a4d82159da 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ComposeViewHierarchyNode.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ComposeViewHierarchyNode.kt @@ -56,11 +56,11 @@ internal object ComposeViewHierarchyNode { } val className = getProxyClassName(isImage) - if (options.experimental.sessionReplay.unmaskViewClasses.contains(className)) { + if (options.sessionReplay.unmaskViewClasses.contains(className)) { return false } - return options.experimental.sessionReplay.maskViewClasses.contains(className) + return options.sessionReplay.maskViewClasses.contains(className) } private var _rootCoordinates: WeakReference? = null diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt index 03bda7cfc6..329717d62c 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt @@ -269,22 +269,22 @@ sealed class ViewHierarchyNode( return false } - if (this.javaClass.isAssignableFrom(options.experimental.sessionReplay.unmaskViewClasses)) { + if (this.javaClass.isAssignableFrom(options.sessionReplay.unmaskViewClasses)) { return false } - return this.javaClass.isAssignableFrom(options.experimental.sessionReplay.maskViewClasses) + return this.javaClass.isAssignableFrom(options.sessionReplay.maskViewClasses) } private fun ViewParent.isUnmaskContainer(options: SentryOptions): Boolean { val unmaskContainer = - options.experimental.sessionReplay.unmaskViewContainerClass ?: return false + options.sessionReplay.unmaskViewContainerClass ?: return false return this.javaClass.name == unmaskContainer } private fun View.isMaskContainer(options: SentryOptions): Boolean { val maskContainer = - options.experimental.sessionReplay.maskViewContainerClass ?: return false + options.sessionReplay.maskViewContainerClass ?: return false return this.javaClass.name == maskContainer } diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/AnrWithReplayIntegrationTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/AnrWithReplayIntegrationTest.kt index a050bd885f..510f87715f 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/AnrWithReplayIntegrationTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/AnrWithReplayIntegrationTest.kt @@ -151,7 +151,7 @@ class AnrWithReplayIntegrationTest { it.cacheDirPath = cacheDir it.isDebug = true it.setLogger(SystemOutLogger()) - it.experimental.sessionReplay.onErrorSampleRate = 1.0 + it.sessionReplay.onErrorSampleRate = 1.0 // beforeSend is called after event processors are applied, so we can assert here // against the enriched ANR event it.beforeSend = SentryOptions.BeforeSendCallback { event, _ -> diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationTest.kt index f375136149..4183a780b8 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationTest.kt @@ -113,8 +113,8 @@ class ReplayIntegrationTest { dateProvider: ICurrentDateProvider = CurrentDateProvider.getInstance() ): ReplayIntegration { options.run { - experimental.sessionReplay.onErrorSampleRate = onErrorSampleRate - experimental.sessionReplay.sessionSampleRate = sessionSampleRate + sessionReplay.onErrorSampleRate = onErrorSampleRate + sessionReplay.sessionSampleRate = sessionSampleRate connectionStatusProvider = mock { on { connectionStatus }.thenReturn(if (isOffline) DISCONNECTED else CONNECTED) } diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationWithRecorderTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationWithRecorderTest.kt index ea28ce7e54..ae817a1759 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationWithRecorderTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationWithRecorderTest.kt @@ -87,10 +87,10 @@ class ReplayIntegrationWithRecorderTest { // fake current time to trigger segment creation, CurrentDateProvider.getInstance() should // be used in prod val dateProvider = ICurrentDateProvider { - System.currentTimeMillis() + fixture.options.experimental.sessionReplay.sessionSegmentDuration + System.currentTimeMillis() + fixture.options.sessionReplay.sessionSegmentDuration } - fixture.options.experimental.sessionReplay.sessionSampleRate = 1.0 + fixture.options.sessionReplay.sessionSampleRate = 1.0 fixture.options.cacheDirPath = tmpDir.newFolder().absolutePath val replay: ReplayIntegration diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplaySmokeTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplaySmokeTest.kt index 1b4fa39411..9bd8e2038d 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplaySmokeTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/ReplaySmokeTest.kt @@ -108,7 +108,7 @@ class ReplaySmokeTest { captured.set(true) } - fixture.options.experimental.sessionReplay.sessionSampleRate = 1.0 + fixture.options.sessionReplay.sessionSampleRate = 1.0 fixture.options.cacheDirPath = tmpDir.newFolder().absolutePath val replay: ReplayIntegration = fixture.getSut(context) @@ -155,7 +155,7 @@ class ReplaySmokeTest { captured.set(true) } - fixture.options.experimental.sessionReplay.onErrorSampleRate = 1.0 + fixture.options.sessionReplay.onErrorSampleRate = 1.0 fixture.options.cacheDirPath = tmpDir.newFolder().absolutePath val replay: ReplayIntegration = fixture.getSut(context) @@ -204,7 +204,7 @@ class ReplaySmokeTest { @Test fun `works when double inited`() { - fixture.options.experimental.sessionReplay.sessionSampleRate = 1.0 + fixture.options.sessionReplay.sessionSampleRate = 1.0 fixture.options.cacheDirPath = tmpDir.newFolder().absolutePath // first init + close diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/BufferCaptureStrategyTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/BufferCaptureStrategyTest.kt index 1fdb41386a..29c777e171 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/BufferCaptureStrategyTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/BufferCaptureStrategyTest.kt @@ -91,7 +91,7 @@ class BufferCaptureStrategyTest { whenever(replayCache.replayCacheDir).thenReturn(it) } options.run { - experimental.sessionReplay.onErrorSampleRate = onErrorSampleRate + sessionReplay.onErrorSampleRate = onErrorSampleRate } return BufferCaptureStrategy( options, @@ -181,7 +181,7 @@ class BufferCaptureStrategyTest { @Test fun `onScreenshotRecorded adds screenshot to cache`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.errorReplayDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.errorReplayDuration * 5) val strategy = fixture.getSut( dateProvider = { now } ) @@ -195,7 +195,7 @@ class BufferCaptureStrategyTest { @Test fun `onScreenshotRecorded rotates screenshots when out of buffer bounds`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.errorReplayDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.errorReplayDuration * 5) val strategy = fixture.getSut( dateProvider = { now } ) @@ -204,7 +204,7 @@ class BufferCaptureStrategyTest { strategy.onScreenshotRecorded(mock()) { frameTimestamp -> assertEquals(now, frameTimestamp) } - verify(fixture.replayCache).rotate(eq(now - fixture.options.experimental.sessionReplay.errorReplayDuration)) + verify(fixture.replayCache).rotate(eq(now - fixture.options.sessionReplay.errorReplayDuration)) } @Test diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/SessionCaptureStrategyTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/SessionCaptureStrategyTest.kt index 1a817609d0..dfe4137fb0 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/SessionCaptureStrategyTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/capture/SessionCaptureStrategyTest.kt @@ -214,7 +214,7 @@ class SessionCaptureStrategyTest { @Test fun `when process is crashing, onScreenshotRecorded does not create new segment`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut( dateProvider = { now } ) @@ -229,7 +229,7 @@ class SessionCaptureStrategyTest { @Test fun `onScreenshotRecorded creates new segment when segment duration exceeded`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut( dateProvider = { now } ) @@ -260,7 +260,7 @@ class SessionCaptureStrategyTest { @Test fun `onScreenshotRecorded stops replay when replay duration exceeded`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionDuration * 2) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionDuration * 2) var count = 0 val strategy = fixture.getSut( dateProvider = { @@ -315,7 +315,7 @@ class SessionCaptureStrategyTest { @Test fun `fills replay urls from navigation breadcrumbs`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut(dateProvider = { now }) strategy.start(fixture.recorderConfig) @@ -341,7 +341,7 @@ class SessionCaptureStrategyTest { fixture.scope.screen = "MainActivity" val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut(dateProvider = { now }) strategy.start(fixture.recorderConfig) @@ -376,13 +376,13 @@ class SessionCaptureStrategyTest { @Test fun `records replay options event for segment 0`() { - fixture.options.experimental.sessionReplay.sessionSampleRate = 1.0 - fixture.options.experimental.sessionReplay.maskAllImages = false - fixture.options.experimental.sessionReplay.quality = HIGH - fixture.options.experimental.sessionReplay.addMaskViewClass("my.custom.View") + fixture.options.sessionReplay.sessionSampleRate = 1.0 + fixture.options.sessionReplay.maskAllImages = false + fixture.options.sessionReplay.quality = HIGH + fixture.options.sessionReplay.addMaskViewClass("my.custom.View") val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut(dateProvider = { now }) strategy.start(fixture.recorderConfig) @@ -426,7 +426,7 @@ class SessionCaptureStrategyTest { @Test fun `does not record replay options event for segment above 0`() { val now = - System.currentTimeMillis() + (fixture.options.experimental.sessionReplay.sessionSegmentDuration * 5) + System.currentTimeMillis() + (fixture.options.sessionReplay.sessionSegmentDuration * 5) val strategy = fixture.getSut(dateProvider = { now }) strategy.start(fixture.recorderConfig) diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ComposeMaskingOptionsTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ComposeMaskingOptionsTest.kt index e5330fa827..8fa3106058 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ComposeMaskingOptionsTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ComposeMaskingOptionsTest.kt @@ -57,7 +57,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } val textNodes = activity.get().collectNodesOfType(options) @@ -72,7 +72,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = false + sessionReplay.maskAllText = false } val textNodes = activity.get().collectNodesOfType(options) @@ -85,7 +85,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllImages = true + sessionReplay.maskAllImages = true } val imageNodes = activity.get().collectNodesOfType(options) @@ -98,7 +98,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllImages = false + sessionReplay.maskAllImages = false } val imageNodes = activity.get().collectNodesOfType(options) @@ -112,7 +112,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = false + sessionReplay.maskAllText = false } val textNodes = activity.get().collectNodesOfType(options) @@ -132,7 +132,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } val textNodes = activity.get().collectNodesOfType(options) @@ -152,7 +152,7 @@ class ComposeMaskingOptionsTest { val activity = buildActivity(ComposeMaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } val textNodes = activity.get().collectNodesOfType(options) diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ContainerMaskingOptionsTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ContainerMaskingOptionsTest.kt index ff9a125d95..fab8d81ac7 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ContainerMaskingOptionsTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/ContainerMaskingOptionsTest.kt @@ -38,8 +38,8 @@ class ContainerMaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true - experimental.sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) + sessionReplay.maskAllText = true + sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) } val textNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.textViewInUnmask!!, null, 0, options) @@ -51,8 +51,8 @@ class ContainerMaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllImages = true - experimental.sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) + sessionReplay.maskAllImages = true + sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) } val imageNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.imageViewInUnmask!!, null, 0, options) @@ -64,7 +64,7 @@ class ContainerMaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.setMaskViewContainerClass(CustomMask::class.java.name) + sessionReplay.setMaskViewContainerClass(CustomMask::class.java.name) } val maskContainer = ViewHierarchyNode.fromView(MaskingOptionsActivity.maskWithChildren!!, null, 0, options) @@ -77,8 +77,8 @@ class ContainerMaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.addMaskViewClass(CustomView::class.java.name) - experimental.sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) + sessionReplay.addMaskViewClass(CustomView::class.java.name) + sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) } val maskContainer = ViewHierarchyNode.fromView(MaskingOptionsActivity.unmaskWithChildren!!, null, 0, options) @@ -95,8 +95,8 @@ class ContainerMaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.setMaskViewContainerClass(CustomMask::class.java.name) - experimental.sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) + sessionReplay.setMaskViewContainerClass(CustomMask::class.java.name) + sessionReplay.setUnmaskViewContainerClass(CustomUnmask::class.java.name) } val unmaskNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.unmaskWithMaskChild!!, null, 0, options) diff --git a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/MaskingOptionsTest.kt b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/MaskingOptionsTest.kt index 4a40e0a915..6620392bde 100644 --- a/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/MaskingOptionsTest.kt +++ b/sentry-android-replay/src/test/java/io/sentry/android/replay/viewhierarchy/MaskingOptionsTest.kt @@ -42,7 +42,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } val textNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.textView!!, null, 0, options) @@ -60,7 +60,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = false + sessionReplay.maskAllText = false } val textNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.textView!!, null, 0, options) @@ -78,7 +78,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllImages = true + sessionReplay.maskAllImages = true } val imageNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.imageView!!, null, 0, options) @@ -92,7 +92,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllImages = false + sessionReplay.maskAllImages = false } val imageNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.imageView!!, null, 0, options) @@ -106,7 +106,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = false + sessionReplay.maskAllText = false } MaskingOptionsActivity.textView!!.tag = "sentry-mask" @@ -120,7 +120,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } MaskingOptionsActivity.textView!!.tag = "sentry-unmask" @@ -134,7 +134,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = false + sessionReplay.maskAllText = false } MaskingOptionsActivity.textView!!.sentryReplayMask() @@ -148,7 +148,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } MaskingOptionsActivity.textView!!.sentryReplayUnmask() @@ -162,7 +162,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true + sessionReplay.maskAllText = true } MaskingOptionsActivity.textView!!.visibility = View.GONE @@ -176,7 +176,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskViewClasses.add(CustomView::class.java.canonicalName) + sessionReplay.maskViewClasses.add(CustomView::class.java.canonicalName) } val customViewNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.customView!!, null, 0, options) @@ -189,8 +189,8 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.maskAllText = true // all TextView subclasses - experimental.sessionReplay.unmaskViewClasses.add(RadioButton::class.java.canonicalName) + sessionReplay.maskAllText = true // all TextView subclasses + sessionReplay.unmaskViewClasses.add(RadioButton::class.java.canonicalName) } val textNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.textView!!, null, 0, options) @@ -205,7 +205,7 @@ class MaskingOptionsTest { buildActivity(MaskingOptionsActivity::class.java).setup() val options = SentryOptions().apply { - experimental.sessionReplay.unmaskViewClasses.add(LinearLayout::class.java.canonicalName) + sessionReplay.unmaskViewClasses.add(LinearLayout::class.java.canonicalName) } val linearLayoutNode = ViewHierarchyNode.fromView(MaskingOptionsActivity.textView!!.parent as LinearLayout, null, 0, options) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index fa303ba61a..c38d11e945 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -316,8 +316,6 @@ public abstract interface class io/sentry/EventProcessor { public final class io/sentry/ExperimentalOptions { public fun (ZLio/sentry/protocol/SdkVersion;)V - public fun getSessionReplay ()Lio/sentry/SentryReplayOptions; - public fun setSessionReplay (Lio/sentry/SentryReplayOptions;)V } public final class io/sentry/ExternalOptions { @@ -2434,6 +2432,7 @@ public class io/sentry/SentryOptions { public fun getSerializer ()Lio/sentry/ISerializer; public fun getServerName ()Ljava/lang/String; public fun getSessionFlushTimeoutMillis ()J + public fun getSessionReplay ()Lio/sentry/SentryReplayOptions; public fun getSessionTrackingIntervalMillis ()J public fun getShutdownTimeout ()J public fun getShutdownTimeoutMillis ()J @@ -2560,6 +2559,7 @@ public class io/sentry/SentryOptions { public fun setSerializer (Lio/sentry/ISerializer;)V public fun setServerName (Ljava/lang/String;)V public fun setSessionFlushTimeoutMillis (J)V + public fun setSessionReplay (Lio/sentry/SentryReplayOptions;)V public fun setSessionTrackingIntervalMillis (J)V public fun setShutdownTimeout (J)V public fun setShutdownTimeoutMillis (J)V diff --git a/sentry/src/main/java/io/sentry/ExperimentalOptions.java b/sentry/src/main/java/io/sentry/ExperimentalOptions.java index f1bf9a8bc7..80d59d4f01 100644 --- a/sentry/src/main/java/io/sentry/ExperimentalOptions.java +++ b/sentry/src/main/java/io/sentry/ExperimentalOptions.java @@ -1,7 +1,6 @@ package io.sentry; import io.sentry.protocol.SdkVersion; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -11,18 +10,6 @@ *

Beware that experimental options can change at any time. */ public final class ExperimentalOptions { - private @NotNull SentryReplayOptions sessionReplay; - public ExperimentalOptions(final boolean empty, final @Nullable SdkVersion sdkVersion) { - this.sessionReplay = new SentryReplayOptions(empty, sdkVersion); - } - - @NotNull - public SentryReplayOptions getSessionReplay() { - return sessionReplay; - } - - public void setSessionReplay(final @NotNull SentryReplayOptions sessionReplayOptions) { - this.sessionReplay = sessionReplayOptions; - } + public ExperimentalOptions(final boolean empty, final @Nullable SdkVersion sdkVersion) {} } diff --git a/sentry/src/main/java/io/sentry/MainEventProcessor.java b/sentry/src/main/java/io/sentry/MainEventProcessor.java index 30f95b8b8f..45be9212ba 100644 --- a/sentry/src/main/java/io/sentry/MainEventProcessor.java +++ b/sentry/src/main/java/io/sentry/MainEventProcessor.java @@ -160,8 +160,7 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) { if (shouldApplyScopeData(event, hint)) { processNonCachedEvent(event); - final @Nullable SdkVersion replaySdkVersion = - options.getExperimental().getSessionReplay().getSdkVersion(); + final @Nullable SdkVersion replaySdkVersion = options.getSessionReplay().getSdkVersion(); if (replaySdkVersion != null) { // we override the SdkVersion only for replay events as those may come from Hybrid SDKs event.setSdk(replaySdkVersion); diff --git a/sentry/src/main/java/io/sentry/Sentry.java b/sentry/src/main/java/io/sentry/Sentry.java index f075876325..4d363dc261 100644 --- a/sentry/src/main/java/io/sentry/Sentry.java +++ b/sentry/src/main/java/io/sentry/Sentry.java @@ -373,7 +373,7 @@ private static void notifyOptionsObservers(final @NotNull SentryOptions options) observer.setEnvironment(options.getEnvironment()); observer.setTags(options.getTags()); observer.setReplayErrorSampleRate( - options.getExperimental().getSessionReplay().getOnErrorSampleRate()); + options.getSessionReplay().getOnErrorSampleRate()); } }); } catch (Throwable e) { diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index a94d6b5ec3..8dde6f2f14 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -644,7 +644,7 @@ public void captureUserFeedback(final @NotNull UserFeedback userFeedback) { // overwritten by the hybrid SDKs final SentryEnvelopeHeader envelopeHeader = new SentryEnvelopeHeader( - sentryId, options.getExperimental().getSessionReplay().getSdkVersion(), traceContext); + sentryId, options.getSessionReplay().getSdkVersion(), traceContext); return new SentryEnvelope(envelopeHeader, envelopeItems); } diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index 23f195ba8e..8e528ba508 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -501,6 +501,8 @@ public class SentryOptions { */ @ApiStatus.Experimental private boolean enableScreenTracking = true; + private @NotNull SentryReplayOptions sessionReplay; + /** * Adds an event processor * @@ -1421,12 +1423,12 @@ public void setSslSocketFactory(final @Nullable SSLSocketFactory sslSocketFactor */ @ApiStatus.Internal public void setSdkVersion(final @Nullable SdkVersion sdkVersion) { - final @Nullable SdkVersion replaySdkVersion = experimental.getSessionReplay().getSdkVersion(); + final @Nullable SdkVersion replaySdkVersion = getSessionReplay().getSdkVersion(); if (this.sdkVersion != null && replaySdkVersion != null && this.sdkVersion.equals(replaySdkVersion)) { // if sdkVersion = sessionReplay.sdkVersion we override it, as it means no one else set it - experimental.getSessionReplay().setSdkVersion(sdkVersion); + getSessionReplay().setSdkVersion(sdkVersion); } this.sdkVersion = sdkVersion; } @@ -2484,6 +2486,15 @@ public void setEnableScreenTracking(final boolean enableScreenTracking) { this.enableScreenTracking = enableScreenTracking; } + @NotNull + public SentryReplayOptions getSessionReplay() { + return sessionReplay; + } + + public void setSessionReplay(final @NotNull SentryReplayOptions sessionReplayOptions) { + this.sessionReplay = sessionReplayOptions; + } + /** * Load the lazy fields. Useful to load in the background, so that results are already cached. DO * NOT CALL THIS METHOD ON THE MAIN THREAD. @@ -2635,6 +2646,7 @@ public SentryOptions() { private SentryOptions(final boolean empty) { final @NotNull SdkVersion sdkVersion = createSdkVersion(); experimental = new ExperimentalOptions(empty, sdkVersion); + sessionReplay = new SentryReplayOptions(empty, sdkVersion); if (!empty) { // SentryExecutorService should be initialized before any // SendCachedEventFireAndForgetIntegration diff --git a/sentry/src/main/java/io/sentry/rrweb/RRWebOptionsEvent.java b/sentry/src/main/java/io/sentry/rrweb/RRWebOptionsEvent.java index d7ad2b1b48..f9a96074c1 100644 --- a/sentry/src/main/java/io/sentry/rrweb/RRWebOptionsEvent.java +++ b/sentry/src/main/java/io/sentry/rrweb/RRWebOptionsEvent.java @@ -40,7 +40,7 @@ public RRWebOptionsEvent(final @NotNull SentryOptions options) { optionsPayload.put("nativeSdkName", sdkVersion.getName()); optionsPayload.put("nativeSdkVersion", sdkVersion.getVersion()); } - final @NotNull SentryReplayOptions replayOptions = options.getExperimental().getSessionReplay(); + final @NotNull SentryReplayOptions replayOptions = options.getSessionReplay(); optionsPayload.put("errorSampleRate", replayOptions.getOnErrorSampleRate()); optionsPayload.put("sessionSampleRate", replayOptions.getSessionSampleRate()); optionsPayload.put( diff --git a/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt b/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt index e82b184c27..8881b6d386 100644 --- a/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt +++ b/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt @@ -623,7 +623,7 @@ class MainEventProcessorTest { fun `uses SdkVersion from replay options for replay events`() { val sut = fixture.getSut(tags = mapOf("tag1" to "value1")) - fixture.sentryOptions.experimental.sessionReplay.sdkVersion = SdkVersion("dart", "3.2.1") + fixture.sentryOptions.sessionReplay.sdkVersion = SdkVersion("dart", "3.2.1") var replayEvent = SentryReplayEvent() replayEvent = sut.process(replayEvent, Hint()) diff --git a/sentry/src/test/java/io/sentry/SentryTest.kt b/sentry/src/test/java/io/sentry/SentryTest.kt index ae34ad870b..697450f0e5 100644 --- a/sentry/src/test/java/io/sentry/SentryTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTest.kt @@ -737,7 +737,7 @@ class SentryTest { it.sdkVersion = SdkVersion("sentry.java.android", "6.13.0") it.environment = "debug" it.setTag("one", "two") - it.experimental.sessionReplay.onErrorSampleRate = 0.5 + it.sessionReplay.onErrorSampleRate = 0.5 } assertEquals("io.sentry.sample@1.1.0+220", optionsObserver.release)