From 01c247086cc4767399f287fe49bc880b8043c33c Mon Sep 17 00:00:00 2001 From: GIancarlo Buenaflor Date: Mon, 30 Sep 2024 17:04:03 +0200 Subject: [PATCH] update --- .../SentryOptionsExtensions.android.kt | 36 +++++++++++++------ .../multiplatform/PlatformOptions.android.kt | 10 ++++++ .../kotlin/multiplatform/TypeAliases.jvm.kt | 2 ++ ...eplayOptions.kt => SentryReplayOptions.kt} | 26 +++++++++++++- .../kotlin/multiplatform/SentryOptionsTest.kt | 10 ++++++ .../extensions/SentryOptionsExtensions.ios.kt | 1 + .../multiplatform/PlatformOptions.ios.kt | 10 ++++++ 7 files changed, 83 insertions(+), 12 deletions(-) rename sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/{SessionReplayOptions.kt => SentryReplayOptions.kt} (54%) diff --git a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt index da6d3448..20f4c937 100644 --- a/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.android.kt @@ -1,28 +1,42 @@ package io.sentry.kotlin.multiplatform.extensions import io.sentry.android.core.SentryAndroidOptions +import io.sentry.kotlin.multiplatform.JvmSentryReplayQuality import io.sentry.kotlin.multiplatform.SentryOptions +import io.sentry.kotlin.multiplatform.SentryReplayOptions import kotlin.collections.forEach as kForEach -internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = { +internal fun SentryOptions.toAndroidSentryOptionsCallback(): (SentryAndroidOptions) -> Unit = { androidOptions -> + val kmpOptions = this + // Apply base options available to all JVM targets - it.applyJvmBaseOptions(this) + androidOptions.applyJvmBaseOptions(kmpOptions) // Apply Android specific options - it.isAttachScreenshot = this.attachScreenshot - it.isAttachViewHierarchy = this.attachViewHierarchy - it.isAnrEnabled = this.isAnrEnabled - it.anrTimeoutIntervalMillis = this.anrTimeoutIntervalMillis + androidOptions.isAttachScreenshot = kmpOptions.attachScreenshot + androidOptions.isAttachViewHierarchy = kmpOptions.attachViewHierarchy + androidOptions.isAnrEnabled = kmpOptions.isAnrEnabled + androidOptions.anrTimeoutIntervalMillis = kmpOptions.anrTimeoutIntervalMillis // Replay options - it.experimental.sessionReplay.redactAllText = this.experimental.sessionReplay.redactAllText - it.experimental.sessionReplay.redactAllImages = this.experimental.sessionReplay.redactAllImages - it.experimental.sessionReplay.sessionSampleRate = this.experimental.sessionReplay.sessionSampleRate?.toDouble() - it.experimental.sessionReplay.errorSampleRate = this.experimental.sessionReplay.onErrorSampleRate?.toDouble() + androidOptions.experimental.sessionReplay.redactAllText = kmpOptions.experimental.sessionReplay.redactAllText + androidOptions.experimental.sessionReplay.redactAllImages = kmpOptions.experimental.sessionReplay.redactAllImages + androidOptions.experimental.sessionReplay.sessionSampleRate = kmpOptions.experimental.sessionReplay.sessionSampleRate + androidOptions.experimental.sessionReplay.errorSampleRate = kmpOptions.experimental.sessionReplay.onErrorSampleRate + androidOptions.experimental.sessionReplay.quality = kmpOptions.experimental.sessionReplay.quality.toAndroidSentryQuality() // kForEach solves an issue with linter where it thinks forEach is the Java version // see here: https://stackoverflow.com/questions/44751469/kotlin-extension-functions-suddenly-require-api-level-24/68897591#68897591 this.sdk?.packages?.kForEach { sdkPackage -> - it.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + androidOptions.sdkVersion?.addPackage(sdkPackage.name, sdkPackage.version) + } +} + +internal fun SentryReplayOptions.Quality.toAndroidSentryQuality(): JvmSentryReplayQuality { + val kmpQuality = this + return when (kmpQuality) { + SentryReplayOptions.Quality.LOW -> JvmSentryReplayQuality.LOW + SentryReplayOptions.Quality.MEDIUM -> JvmSentryReplayQuality.MEDIUM + SentryReplayOptions.Quality.HIGH -> JvmSentryReplayQuality.HIGH } } diff --git a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt index d91ec957..0601682e 100644 --- a/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt +++ b/sentry-kotlin-multiplatform/src/androidUnitTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.android.kt @@ -4,12 +4,14 @@ import io.sentry.android.core.SentryAndroidOptions import io.sentry.kotlin.multiplatform.extensions.toAndroidSentryOptionsCallback import io.sentry.kotlin.multiplatform.utils.fakeDsn import kotlin.test.assertEquals +import io.sentry.SentryReplayOptions as NativeSentryReplayOptions actual interface PlatformOptions : CommonPlatformOptions { val isAnrEnabled: Boolean val anrTimeoutIntervalMillis: Long val attachScreenshot: Boolean val attachViewHierarchy: Boolean + val sessionReplay: NativeSentryReplayOptions } class SentryAndroidOptionsWrapper(private val androidOptions: SentryAndroidOptions) : @@ -62,6 +64,9 @@ class SentryAndroidOptionsWrapper(private val androidOptions: SentryAndroidOptio override val attachViewHierarchy: Boolean get() = androidOptions.isAttachViewHierarchy + override val sessionReplay: NativeSentryReplayOptions + get() = androidOptions.experimental.sessionReplay + override fun applyFromOptions(options: SentryOptions) { options.toAndroidSentryOptionsCallback().invoke(androidOptions) } @@ -75,6 +80,11 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(options: SentryOptions) assertEquals(attachViewHierarchy, options.attachViewHierarchy) assertEquals(isAnrEnabled, options.isAnrEnabled) assertEquals(anrTimeoutIntervalMillis, options.anrTimeoutIntervalMillis) + assertEquals(sessionReplay.redactAllText, options.experimental.sessionReplay.redactAllText) + assertEquals(sessionReplay.redactAllImages, options.experimental.sessionReplay.redactAllImages) + assertEquals(sessionReplay.errorSampleRate, options.experimental.sessionReplay.onErrorSampleRate) + assertEquals(sessionReplay.sessionSampleRate, options.experimental.sessionReplay.sessionSampleRate) + assertEquals(sessionReplay.quality.name, options.experimental.sessionReplay.quality.name) } actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = { diff --git a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/TypeAliases.jvm.kt b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/TypeAliases.jvm.kt index 14923844..53f73de9 100644 --- a/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/TypeAliases.jvm.kt +++ b/sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/TypeAliases.jvm.kt @@ -7,6 +7,7 @@ import io.sentry.Scope import io.sentry.SentryEvent import io.sentry.SentryLevel import io.sentry.SentryOptions +import io.sentry.SentryReplayOptions import io.sentry.UserFeedback import io.sentry.protocol.Contexts import io.sentry.protocol.Message @@ -27,3 +28,4 @@ internal typealias JvmSentryEvent = SentryEvent internal typealias JvmMessage = Message internal typealias JvmSentryException = SentryException internal typealias JvmContexts = Contexts +internal typealias JvmSentryReplayQuality = SentryReplayOptions.SentryReplayQuality diff --git a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SessionReplayOptions.kt b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt similarity index 54% rename from sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SessionReplayOptions.kt rename to sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt index 6df1c3ac..10ba87cf 100644 --- a/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SessionReplayOptions.kt +++ b/sentry-kotlin-multiplatform/src/commonMain/kotlin/io/sentry/kotlin/multiplatform/SentryReplayOptions.kt @@ -33,5 +33,29 @@ public data class SentryReplayOptions( * The default is true. */ public var redactAllImages: Boolean = true, -) + /** + * Defines the quality of the session replay. The higher the quality, the more accurate the replay + * will be, but also more data to transfer and more CPU load, defaults to MEDIUM. + */ + public var quality: Quality = Quality.MEDIUM +) { + public enum class Quality( + /** The scale related to the window size (in dp) at which the replay will be created. */ + public val sizeScale: Float, + /** + * Defines the quality of the session replay. Higher bit rates have better replay quality, but + * also affect the final payload size to transfer, defaults to 40kbps. + */ + public val bitRate: Int + ) { + /** Video Scale: 80% Bit Rate: 50.000 */ + LOW(0.8f, 50000), + + /** Video Scale: 100% Bit Rate: 75.000 */ + MEDIUM(1.0f, 75000), + + /** Video Scale: 100% Bit Rate: 100.000 */ + HIGH(1.0f, 100000) + } +} diff --git a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt index 3be34660..4ea76a6e 100644 --- a/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt +++ b/sentry-kotlin-multiplatform/src/commonTest/kotlin/io/sentry/kotlin/multiplatform/SentryOptionsTest.kt @@ -126,6 +126,11 @@ class SentryOptionsTest : BaseSentryTest() { assertEquals(2000L, options.appHangTimeoutIntervalMillis) assertTrue(options.isAnrEnabled) assertEquals(5000L, options.anrTimeoutIntervalMillis) + assertNull(options.experimental.sessionReplay.onErrorSampleRate) + assertNull(options.experimental.sessionReplay.sessionSampleRate) + assertTrue(options.experimental.sessionReplay.redactAllText) + assertTrue(options.experimental.sessionReplay.redactAllImages) + assertEquals(SentryReplayOptions.Quality.MEDIUM, options.experimental.sessionReplay.quality) } @Test @@ -149,6 +154,11 @@ class SentryOptionsTest : BaseSentryTest() { appHangTimeoutIntervalMillis = 1000L isAnrEnabled = false anrTimeoutIntervalMillis = 1000L + experimental.sessionReplay.onErrorSampleRate = 0.5 + experimental.sessionReplay.sessionSampleRate = 0.5 + experimental.sessionReplay.redactAllText = false + experimental.sessionReplay.redactAllImages = false + experimental.sessionReplay.quality = SentryReplayOptions.Quality.LOW } val platformOptions = createPlatformOptions() diff --git a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt index 7077f128..1c7f849a 100644 --- a/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.ios.kt @@ -20,6 +20,7 @@ internal fun SentryOptions.toIosOptionsConfiguration(): (CocoaSentryOptions?) -> setRedactAllImages(kmpOptions.experimental.sessionReplay.redactAllImages) kmpOptions.experimental.sessionReplay.sessionSampleRate?.let { setSessionSampleRate(it.toFloat()) } kmpOptions.experimental.sessionReplay.onErrorSampleRate?.let { setOnErrorSampleRate(it.toFloat()) } + setQuality(kmpOptions.experimental.sessionReplay.quality.ordinal.toLong()) } } ?: run { // Log a warning if options is null diff --git a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt index 1e2775d8..3c3c4f19 100644 --- a/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt +++ b/sentry-kotlin-multiplatform/src/iosTest/kotlin/io/sentry/kotlin/multiplatform/PlatformOptions.ios.kt @@ -1,5 +1,6 @@ package io.sentry.kotlin.multiplatform +import cocoapods.Sentry.SentryReplayOptions import io.sentry.kotlin.multiplatform.extensions.toIosOptionsConfiguration import io.sentry.kotlin.multiplatform.utils.fakeDsn import kotlinx.cinterop.convert @@ -10,6 +11,7 @@ actual interface PlatformOptions : CommonPlatformOptions { val attachViewHierarchy: Boolean val enableAppHangTracking: Boolean val appHangTimeoutIntervalMillis: Long + val sessionReplay: SentryReplayOptions } class SentryIosOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : PlatformOptions { @@ -61,6 +63,9 @@ class SentryIosOptionsWrapper(private val cocoaOptions: CocoaSentryOptions) : Pl override val tracesSampleRate: Double? get() = cocoaOptions.tracesSampleRate?.doubleValue + override val sessionReplay: SentryReplayOptions + get() = cocoaOptions.experimental.sessionReplay() + override fun applyFromOptions(options: SentryOptions) { options.toIosOptionsConfiguration().invoke(cocoaOptions) } @@ -73,6 +78,11 @@ actual fun PlatformOptions.assertPlatformSpecificOptions(options: SentryOptions) assertEquals(attachViewHierarchy, options.attachViewHierarchy) assertEquals(enableAppHangTracking, options.enableAppHangTracking) assertEquals(appHangTimeoutIntervalMillis, options.appHangTimeoutIntervalMillis) + assertEquals(sessionReplay.redactAllText(), options.experimental.sessionReplay.redactAllText) + assertEquals(sessionReplay.redactAllImages(), options.experimental.sessionReplay.redactAllImages) + assertEquals(sessionReplay.onErrorSampleRate().toDouble(), options.experimental.sessionReplay.onErrorSampleRate) + assertEquals(sessionReplay.sessionSampleRate().toDouble(), options.experimental.sessionReplay.sessionSampleRate) + assertEquals(sessionReplay.quality(), options.experimental.sessionReplay.quality.ordinal.toLong()) } actual fun createSentryPlatformOptionsConfiguration(): PlatformOptionsConfiguration = {