diff --git a/docs/platforms/android/integrations/jetpack-compose/index.mdx b/docs/platforms/android/integrations/jetpack-compose/index.mdx index 1c1111f5ceb131..ecad7963bbf0ea 100644 --- a/docs/platforms/android/integrations/jetpack-compose/index.mdx +++ b/docs/platforms/android/integrations/jetpack-compose/index.mdx @@ -356,3 +356,39 @@ SentryAndroid.init(this) { options -> }) } ``` + +## Custom Telemetry in Compose + +Composable functions can run many times during recomposition. Don't emit custom Sentry spans, messages, +breadcrumbs, or other telemetry directly from a composable body, as it can duplicate telemetry or attach it +to the wrong UI lifecycle moment. + +Prefer emitting telemetry from: + +- `LaunchedEffect`, `DisposableEffect`, or `SideEffect` (more info in [Google's developer docs](https://developer.android.com/develop/ui/compose/side-effects)) +- Event callbacks such as `onClick` when the telemetry corresponds to a user action +- APIs that run after composition, such as draw-time or layout-time lambdas, when that timing is what you want to measure + +For example, avoid capturing a message directly from the body: + +```kotlin +@Composable +fun LoginScreen() { + Sentry.captureMessage("Login screen shown") + // ... +} +``` + +Instead, capture state in the body as needed but emit it from an Effect API: + +```kotlin +@Composable +fun LoginScreen() { + val firstComposedAt = remember { Instant.now() } + + LaunchedEffect(Unit) { + Sentry.captureMessage("Login screen shown: $firstComposedAt") + } + // ... +} +``` diff --git a/docs/platforms/android/tracing/instrumentation/custom-instrumentation.mdx b/docs/platforms/android/tracing/instrumentation/custom-instrumentation.mdx index 012ea3c96b054e..af7b45d7de53d6 100644 --- a/docs/platforms/android/tracing/instrumentation/custom-instrumentation.mdx +++ b/docs/platforms/android/tracing/instrumentation/custom-instrumentation.mdx @@ -14,6 +14,14 @@ To capture transactions and spans customized to your organization's needs, you m + + +If you emit custom Sentry spans or other telemetry from Jetpack Compose code, use Compose Effect APIs such as +`LaunchedEffect`, `DisposableEffect`, or `SideEffect` instead of emitting from a composable body. Composable bodies +can run repeatedly during recomposition. See Jetpack Compose. + + +