-
-
Notifications
You must be signed in to change notification settings - Fork 427
/
SentryNavigationIntegration.kt
83 lines (74 loc) · 3.12 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
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.NavDestination
import androidx.navigation.NavHostController
import androidx.navigation.Navigator
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 when 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
}
@Composable
public fun rememberNavController(vararg navigators: Navigator<out NavDestination>): NavHostController {
return androidx.navigation.compose.rememberNavController(navigators = navigators)
.withSentryObservableEffect()
}