From a4b908bc181b0e1f7a58c868ebad3e09eaa115c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Tue, 16 Dec 2025 16:52:08 +0100 Subject: [PATCH] Integrate the new use case with Sentry We'll upload the store sizes as different fields so we can later use them to filter transaction/issues --- libraries/core/build.gradle.kts | 1 + .../sentry/build.gradle.kts | 2 ++ .../sentry/SentryAnalyticsProvider.kt | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/libraries/core/build.gradle.kts b/libraries/core/build.gradle.kts index e25ae62c95..d04efaa40e 100644 --- a/libraries/core/build.gradle.kts +++ b/libraries/core/build.gradle.kts @@ -24,6 +24,7 @@ kotlin { dependencies { implementation(libs.coroutines.core) + implementation(libs.coroutines.test) testImplementation(libs.test.junit) testImplementation(libs.test.truth) } diff --git a/services/analyticsproviders/sentry/build.gradle.kts b/services/analyticsproviders/sentry/build.gradle.kts index 780e97a2d5..5f8ec01996 100644 --- a/services/analyticsproviders/sentry/build.gradle.kts +++ b/services/analyticsproviders/sentry/build.gradle.kts @@ -51,5 +51,7 @@ dependencies { implementation(libs.sentry) implementation(projects.libraries.core) implementation(projects.libraries.di) + implementation(projects.libraries.matrix.api) implementation(projects.services.analyticsproviders.api) + implementation(projects.services.appnavstate.api) } diff --git a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt index 84167b52c3..395e2eab25 100644 --- a/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt +++ b/services/analyticsproviders/sentry/src/main/kotlin/io/element/android/services/analyticsproviders/sentry/SentryAnalyticsProvider.kt @@ -16,16 +16,22 @@ import im.vector.app.features.analytics.itf.VectorAnalyticsEvent import im.vector.app.features.analytics.itf.VectorAnalyticsScreen import im.vector.app.features.analytics.plan.SuperProperties import im.vector.app.features.analytics.plan.UserProperties +import io.element.android.libraries.core.data.ByteUnit import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildType import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.analytics.GetDatabaseSizesUseCase import io.element.android.services.analyticsproviders.api.AnalyticsProvider import io.element.android.services.analyticsproviders.api.AnalyticsTransaction +import io.element.android.services.analyticsproviders.api.AnalyticsUserData import io.element.android.services.analyticsproviders.sentry.log.analyticsTag +import io.element.android.services.appnavstate.api.AppNavigationStateService +import io.element.android.services.appnavstate.api.currentSessionId import io.sentry.Breadcrumb import io.sentry.Sentry import io.sentry.SentryOptions import io.sentry.android.core.SentryAndroid +import kotlinx.coroutines.runBlocking import timber.log.Timber @ContributesIntoSet(AppScope::class) @@ -33,6 +39,8 @@ import timber.log.Timber class SentryAnalyticsProvider( @ApplicationContext private val context: Context, private val buildMeta: BuildMeta, + private val getDatabaseSizesUseCase: GetDatabaseSizesUseCase, + private val appNavigationStateService: AppNavigationStateService, ) : AnalyticsProvider { override val name = SentryConfig.NAME @@ -48,6 +56,20 @@ class SentryAnalyticsProvider( SentryAndroid.init(context) { options -> options.dsn = dsn options.beforeSend = SentryOptions.BeforeSendCallback { event, _ -> event } + options.beforeSendTransaction = SentryOptions.BeforeSendTransactionCallback { transaction, _ -> + val sessionId = appNavigationStateService.appNavigationState.value.navigationState.currentSessionId() + if (sessionId != null) { + // This runs in a separate thread, so although using `runBlocking` is not great, at least it shouldn't freeze the app + // Also, the method is fairly quick, so the blocking shouldn't take longer than a few ms + val databaseSizes = runBlocking { getDatabaseSizesUseCase(sessionId) }.getOrNull() + + databaseSizes?.stateStore?.let { transaction.setExtra(AnalyticsUserData.STATE_STORE_SIZE, it.into(ByteUnit.MB)) } + databaseSizes?.eventCacheStore?.let { transaction.setExtra(AnalyticsUserData.EVENT_CACHE_SIZE, it.into(ByteUnit.MB)) } + databaseSizes?.mediaStore?.let { transaction.setExtra(AnalyticsUserData.MEDIA_STORE_SIZE, it.into(ByteUnit.MB)) } + databaseSizes?.cryptoStore?.let { transaction.setExtra(AnalyticsUserData.CRYPTO_STORE_SIZE, it.into(ByteUnit.MB)) } + } + transaction + } options.tracesSampleRate = 1.0 options.isEnableUserInteractionTracing = true options.environment = buildMeta.buildType.toSentryEnv()