diff --git a/docs/platforms/android/integrations/jetpack-compose/index.mdx b/docs/platforms/android/integrations/jetpack-compose/index.mdx index 1c1111f5ceb131..2aa348b379e881 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 send 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. + +Instead, send 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 send 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..57bc14ec9bfdc8 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 send custom Sentry spans or other telemetry from Jetpack Compose code, use Compose Effect APIs such as +`LaunchedEffect`, `DisposableEffect`, or `SideEffect` instead of sending from a composable body. Composable bodies +can run repeatedly during recomposition. See Jetpack Compose. + + +