-
-
Notifications
You must be signed in to change notification settings - Fork 427
/
SentryNavigationIntegration.kt
90 lines (81 loc) · 3.33 KB
/
SentryNavigationIntegration.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package io.sentry.compose
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.NonRestartableComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.navigation.NavController
import androidx.navigation.NavHostController
import io.sentry.Breadcrumb
import io.sentry.ITransaction
import io.sentry.SentryOptions
import io.sentry.android.navigation.SentryNavigationListener
internal class SentryLifecycleObserver(
private val navController: NavController,
private val navListener: NavController.OnDestinationChangedListener =
SentryNavigationListener()
) : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event == Lifecycle.Event.ON_RESUME) {
navController.addOnDestinationChangedListener(navListener)
} else if (event == Lifecycle.Event.ON_PAUSE) {
navController.removeOnDestinationChangedListener(navListener)
}
}
fun dispose() {
navController.removeOnDestinationChangedListener(navListener)
}
}
/**
* A [DisposableEffect] that captures a [Breadcrumb] and starts an [ITransaction] and sends
* them to Sentry for every navigation event when being attached to the respective [NavHostController].
*
* @param enableNavigationBreadcrumbs Whether the integration should capture breadcrumbs for
* navigation events.
* @param enableNavigationTracing Whether the integration should start a new [ITransaction]
* with [SentryOptions.idleTimeout] for navigation events.
*/
@Composable
@NonRestartableComposable
public fun NavHostController.withSentryObservableEffect(
enableNavigationBreadcrumbs: Boolean = true,
enableNavigationTracing: Boolean = true
): NavHostController {
val enableBreadcrumbsSnapshot by rememberUpdatedState(enableNavigationBreadcrumbs)
val enableTracingSnapshot by rememberUpdatedState(enableNavigationTracing)
// As described in https://developer.android.com/codelabs/jetpack-compose-advanced-state-side-effects#6
val lifecycle = LocalLifecycleOwner.current.lifecycle
DisposableEffect(lifecycle, this) {
val observer = SentryLifecycleObserver(
this@withSentryObservableEffect,
navListener = SentryNavigationListener(
enableNavigationBreadcrumbs = enableBreadcrumbsSnapshot,
enableNavigationTracing = enableTracingSnapshot
)
)
lifecycle.addObserver(observer)
onDispose {
observer.dispose()
lifecycle.removeObserver(observer)
}
}
return this
}
/**
* A [DisposableEffect] that captures a [Breadcrumb] and starts an [ITransaction] and sends
* them to Sentry for every navigation event when being attached to the respective [NavHostController].
*
* Used by the sentry android gradle plugin for Jetpack Compose instrumentation.
*
*/
@Composable
internal fun NavHostController.withSentryObservableEffect(): NavHostController {
return withSentryObservableEffect(
enableNavigationBreadcrumbs = true,
enableNavigationTracing = true
)
}