Add some performance metrics for Sentry (#5760)
- Add `AnalyticsService.startTransaction(...)` to start a logging transaction that can be uploaded to Sentry if the user enabled the analytics upload. - Add `AnalyticsTransaction` wrapper to abstract the Sentry ones. - Added several helper methods to improve the UX around these transactions. - Then measure: - Time until the first sync, and how it ended. - Time until the first rooms are displayed. - Time to load a room or a preview. - Time to load a timeline.
This commit is contained in:
parent
de3ffca1af
commit
c6c2f4a267
25 changed files with 245 additions and 41 deletions
|
|
@ -20,4 +20,6 @@ interface AnalyticsProvider : AnalyticsTracker, ErrorTracker {
|
|||
fun init()
|
||||
|
||||
fun stop()
|
||||
|
||||
fun startTransaction(name: String, operation: String? = null): AnalyticsTransaction?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.analyticsproviders.api
|
||||
|
||||
interface AnalyticsTransaction {
|
||||
fun startChild(operation: String, description: String? = null): AnalyticsTransaction
|
||||
fun setData(key: String, value: Any)
|
||||
fun isFinished(): Boolean
|
||||
fun finish()
|
||||
}
|
||||
|
||||
inline fun <T> AnalyticsTransaction.recordChildTransaction(operation: String, description: String? = null, block: (AnalyticsTransaction) -> T): T {
|
||||
val child = startChild(operation, description)
|
||||
try {
|
||||
val result = block(child)
|
||||
return result
|
||||
} finally {
|
||||
child.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ 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.services.analyticsproviders.api.AnalyticsProvider
|
||||
import io.element.android.services.analyticsproviders.api.AnalyticsTransaction
|
||||
import io.element.android.services.analyticsproviders.posthog.log.analyticsTag
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -122,6 +123,8 @@ class PosthogAnalyticsProvider(
|
|||
}
|
||||
return withSuperProperties.takeIf { it.isEmpty().not() }
|
||||
}
|
||||
|
||||
override fun startTransaction(name: String, operation: String?): AnalyticsTransaction? = null
|
||||
}
|
||||
|
||||
private fun Map<String, Any?>.keepOnlyNonNullValues(): Map<String, Any> {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ 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.services.analyticsproviders.api.AnalyticsProvider
|
||||
import io.element.android.services.analyticsproviders.api.AnalyticsTransaction
|
||||
import io.element.android.services.analyticsproviders.sentry.log.analyticsTag
|
||||
import io.sentry.Breadcrumb
|
||||
import io.sentry.Sentry
|
||||
|
|
@ -51,6 +52,7 @@ class SentryAnalyticsProvider(
|
|||
options.isEnableUserInteractionTracing = true
|
||||
options.environment = buildMeta.buildType.toSentryEnv()
|
||||
}
|
||||
Timber.tag(analyticsTag.value).d("Sentry was initialized correctly")
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
|
|
@ -87,6 +89,10 @@ class SentryAnalyticsProvider(
|
|||
override fun trackError(throwable: Throwable) {
|
||||
Sentry.captureException(throwable)
|
||||
}
|
||||
|
||||
override fun startTransaction(name: String, operation: String?): AnalyticsTransaction? {
|
||||
return SentryAnalyticsTransaction(name, operation)
|
||||
}
|
||||
}
|
||||
|
||||
private fun BuildType.toSentryEnv() = when (this) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.analyticsproviders.sentry
|
||||
|
||||
import io.element.android.services.analyticsproviders.api.AnalyticsTransaction
|
||||
import io.sentry.ISpan
|
||||
import io.sentry.Sentry
|
||||
|
||||
class SentryAnalyticsTransaction private constructor(span: ISpan) : AnalyticsTransaction {
|
||||
constructor(name: String, operation: String?) : this(Sentry.startTransaction(name, operation.orEmpty()))
|
||||
private val inner = span
|
||||
|
||||
override fun startChild(operation: String, description: String?): AnalyticsTransaction = SentryAnalyticsTransaction(
|
||||
inner.startChild(operation, description)
|
||||
)
|
||||
override fun setData(key: String, value: Any) = inner.setData(key, value)
|
||||
override fun isFinished(): Boolean = inner.isFinished
|
||||
override fun finish() = inner.finish()
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ 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.services.analyticsproviders.api.AnalyticsProvider
|
||||
import io.element.android.services.analyticsproviders.api.AnalyticsTransaction
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeAnalyticsProvider(
|
||||
|
|
@ -32,4 +33,5 @@ class FakeAnalyticsProvider(
|
|||
override fun updateUserProperties(userProperties: UserProperties) = updateUserPropertiesLambda(userProperties)
|
||||
override fun trackError(throwable: Throwable) = trackErrorLambda(throwable)
|
||||
override fun updateSuperProperties(updatedProperties: SuperProperties) = updateSuperPropertiesLambda(updatedProperties)
|
||||
override fun startTransaction(name: String, operation: String?): AnalyticsTransaction? = null
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue