From e329aa45f2d23a55932277d0417654e6d34c7803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Santos?= Date: Wed, 25 Sep 2024 12:58:04 +0100 Subject: [PATCH] Configure Sentry crash reporting --- .../commonMain/kotlin/org/ooni/probe/App.kt | 5 + .../kotlin/org/ooni/probe/di/Dependencies.kt | 5 + .../shared/monitoring/CrashMonitoring.kt | 93 +++++++++++++++++++ gradle/libs.versions.toml | 4 + iosApp/Podfile | 6 ++ iosApp/Podfile.lock | 8 +- 6 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 composeApp/src/commonMain/kotlin/org/ooni/probe/shared/monitoring/CrashMonitoring.kt diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/App.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/App.kt index 58f9a21c2..2dac20193 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/App.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/App.kt @@ -78,9 +78,14 @@ fun App( } } + Logger.addLogWriter(dependencies.crashMonitoring.logWriter) + LaunchedEffect(Unit) { logAppStart(dependencies) } + LaunchedEffect(Unit) { + dependencies.crashMonitoring.setup() + } LaunchedEffect(Unit) { dependencies.bootstrapTestDescriptors() dependencies.bootstrapPreferences() diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt index 3f2ddc5bc..249b1ebf9 100644 --- a/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt @@ -65,6 +65,7 @@ import org.ooni.probe.domain.ShouldShowVpnWarning import org.ooni.probe.domain.TestRunStateManager import org.ooni.probe.domain.UploadMissingMeasurements import org.ooni.probe.shared.PlatformInfo +import org.ooni.probe.shared.monitoring.CrashMonitoring import org.ooni.probe.ui.dashboard.DashboardViewModel import org.ooni.probe.ui.descriptor.DescriptorViewModel import org.ooni.probe.ui.descriptor.add.AddDescriptorViewModel @@ -118,6 +119,10 @@ class Dependencies( private val writeFile: WriteFile by lazy { WriteFileOkio(FileSystem.SYSTEM, baseFileDir) } private val deleteFiles: DeleteFiles by lazy { DeleteFilesOkio(FileSystem.SYSTEM, baseFileDir) } + // Monitoring + + val crashMonitoring by lazy { CrashMonitoring(preferenceRepository) } + // Engine private val taskEventMapper by lazy { TaskEventMapper(networkTypeFinder, json) } diff --git a/composeApp/src/commonMain/kotlin/org/ooni/probe/shared/monitoring/CrashMonitoring.kt b/composeApp/src/commonMain/kotlin/org/ooni/probe/shared/monitoring/CrashMonitoring.kt new file mode 100644 index 000000000..a8925c365 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/org/ooni/probe/shared/monitoring/CrashMonitoring.kt @@ -0,0 +1,93 @@ +package org.ooni.probe.shared.monitoring + +import co.touchlab.kermit.LogWriter +import co.touchlab.kermit.Severity +import io.sentry.kotlin.multiplatform.Sentry +import io.sentry.kotlin.multiplatform.SentryLevel +import io.sentry.kotlin.multiplatform.protocol.Breadcrumb +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach +import org.ooni.probe.data.models.SettingsKey +import org.ooni.probe.data.repositories.PreferenceRepository + +class CrashMonitoring( + private val preferencesRepository: PreferenceRepository, +) { + private var isEnabled = false + + suspend fun setup() { + preferencesRepository.getValueByKey(SettingsKey.SEND_CRASH) + .onEach { sendCrash -> + if (sendCrash == true) { + Sentry.init { + it.dsn = SENTRY_DSN + } + isEnabled = true + } else { + isEnabled = false + Sentry.close() + } + } + .collect() + } + + val logWriter = object : LogWriter() { + override fun isLoggable( + tag: String, + severity: Severity, + ): Boolean = isEnabled && severity != Severity.Verbose + + override fun log( + severity: Severity, + message: String, + tag: String, + throwable: Throwable?, + ) { + if (!isEnabled) return + + if (severity == Severity.Error) { + if (throwable != null) { + addBreadcrumb(severity, message, tag) + Sentry.captureException(throwable) + } else { + Sentry.captureMessage(message) + } + } else { + addBreadcrumb(severity, message, tag) + } + } + + private fun addBreadcrumb( + severity: Severity, + message: String, + tag: String, + ) { + Sentry.addBreadcrumb( + Breadcrumb( + level = when (severity) { + Severity.Verbose, + Severity.Debug, + -> SentryLevel.DEBUG + + Severity.Info -> SentryLevel.INFO + Severity.Warn -> SentryLevel.WARNING + Severity.Error -> SentryLevel.ERROR + Severity.Assert -> SentryLevel.ERROR + }, + type = when (severity) { + Severity.Debug -> "debug" + Severity.Error -> "error" + else -> "default" + }, + message = message, + category = tag, + ), + ) + } + } + + companion object { + private const val SENTRY_DSN = + "https://9dcd83d9519844188803aa817cdcd416@o155150.ingest.sentry.io/5619989" + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 923e2b21b..155fe9295 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,6 +64,9 @@ kottie = { module = "io.github.alexzhirkevich:compottie", version = "2.0.0-rc01" # Permissions moko-permissions = { module ="dev.icerock.moko:permissions-compose", version = "0.18.0" } +# Crash Reporting +sentry = { module = "io.sentry:sentry-kotlin-multiplatform", version = "0.9.0" } + # Testing android-test-core = { module = "androidx.test:core", version = "1.6.1" } @@ -87,6 +90,7 @@ tooling = [ "markdown", "kottie", "moko-permissions", + "sentry", ] android = [ "android-oonimkall", diff --git a/iosApp/Podfile b/iosApp/Podfile index 1f40e8503..db9387490 100644 --- a/iosApp/Podfile +++ b/iosApp/Podfile @@ -9,6 +9,12 @@ def shared_pods pod 'sqlite3', '~> 3.42.0' + pod("Sentry") { + version = "~> 8.25" + linkOnly = true + extraOpts += listOf("-compiler-option", "-fmodules") + } + pod "libcrypto", :podspec => "#{ooni_pods_location}/libcrypto.podspec" pod "libevent", :podspec => "#{ooni_pods_location}/libevent.podspec" pod "libssl", :podspec => "#{ooni_pods_location}/libssl.podspec" diff --git a/iosApp/Podfile.lock b/iosApp/Podfile.lock index f39279d52..a0fe2b75f 100644 --- a/iosApp/Podfile.lock +++ b/iosApp/Podfile.lock @@ -6,6 +6,9 @@ PODS: - libtor (2024.05.22-093305) - libz (2024.05.22-093305) - oonimkall (2024.05.22-093305) + - Sentry (8.36.0): + - Sentry/Core (= 8.36.0) + - Sentry/Core (8.36.0) - sqlite3 (3.42.0): - sqlite3/common (= 3.42.0) - sqlite3/common (3.42.0) @@ -18,10 +21,12 @@ DEPENDENCIES: - libtor (from `https://github.com/ooni/probe-cli/releases/download/v3.22.0/libtor.podspec`) - libz (from `https://github.com/ooni/probe-cli/releases/download/v3.22.0/libz.podspec`) - oonimkall (from `https://github.com/ooni/probe-cli/releases/download/v3.22.0/oonimkall.podspec`) + - Sentry - sqlite3 (~> 3.42.0) SPEC REPOS: trunk: + - Sentry - sqlite3 EXTERNAL SOURCES: @@ -48,8 +53,9 @@ SPEC CHECKSUMS: libtor: c72b23da6a5d2e16173149784f11cf66156c35be libz: 83658eb2a0db785623ffdf9ce13407e6b8b5c8f9 oonimkall: 9768ce9dad18265d45d2ea972c84fb0bd5237cc3 + Sentry: f8374b5415bc38dfb5645941b3ae31230fbeae57 sqlite3: f163dbbb7aa3339ad8fc622782c2d9d7b72f7e9c -PODFILE CHECKSUM: b06fce1e10c83d22148bcb93b3b75ca57d3bff2b +PODFILE CHECKSUM: b49ba8d6a4e50f7a2ff0d0e0311fe97c8511e6e9 COCOAPODS: 1.15.2