Skip to content

Commit d877a7b

Browse files
committed
Address Max's comments
1 parent dc803d2 commit d877a7b

8 files changed

Lines changed: 51 additions & 25 deletions

File tree

‎sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackConverter.kt‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,19 @@ internal class BackStackConverter<T : Any>(
7272
return NormalizedSentryBackStackEntry(UNKNOWN_ENTRY_NAME)
7373
}
7474

75+
if (info == null) {
76+
return NormalizedSentryBackStackEntry(UNKNOWN_ENTRY_NAME)
77+
}
78+
7579
val arguments = info.arguments?.let(sanitizer::sanitizeEntry) ?: emptyMap()
7680
val formattedName = NormalizedSentryBackStackEntry.formatName(info.name)
77-
if (formattedName.isBlank()) {
81+
82+
return if (formattedName.isBlank()) {
7883
warningState.logInvalidNameWarning(logger)
79-
return NormalizedSentryBackStackEntry(UNKNOWN_ENTRY_NAME, arguments)
84+
NormalizedSentryBackStackEntry(UNKNOWN_ENTRY_NAME, arguments)
85+
} else {
86+
NormalizedSentryBackStackEntry(formattedName, arguments)
8087
}
81-
82-
return NormalizedSentryBackStackEntry(formattedName, arguments)
8388
}
8489

8590
/**

‎sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt‎

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ public class SentryBackStackEntry(
7777
*
7878
* **Names fall back to "/unknown"**
7979
*
80-
* If [map] throws or returns a blank [name][SentryBackStackEntry.name], Sentry records the
81-
* destination as "/unknown". Doing so signals that name extraction needs to be fixed while avoiding
82-
* misleading gaps in navigation data.
80+
* If [map] throws, returns `null`, or returns a blank [name][SentryBackStackEntry.name], Sentry
81+
* records the destination as "/unknown". Doing so signals that name extraction needs to be fixed
82+
* while avoiding misleading gaps in navigation data.
8383
*
8484
* For instance, if a user navigates from `/home -> /detail -> /settings`, but the mapper for
8585
* `/detail` throws, the back stack record will be `/home -> /unknown -> /settings` rather than
@@ -109,8 +109,8 @@ public class SentryBackStackEntry(
109109
*
110110
* **Arguments fall back to `toString()` or nothing**
111111
*
112-
* All non-supported argument types are stringified via `toString()`. If [map] throws, no arguments
113-
* are recorded for that back stack entry.
112+
* All non-supported argument types are stringified via `toString()`. If [map] throws or returns
113+
* `null`, no arguments are recorded for that back stack entry.
114114
*
115115
* **Using kotlinx.serialization**
116116
*
@@ -123,14 +123,15 @@ public class SentryBackStackEntry(
123123
* ```kotlin
124124
* @Serializable
125125
* @SerialName("Home")
126-
* data object Home(userName: String) : NavKey
126+
* data class Home(userName: String) : NavKey
127127
*
128128
* @Serializable
129129
* @SerialName("ProductDetail")
130130
* data class ProductDetail(userName: String, productId: String, tab: Tab) : NavKey
131-
* ```
132-
* ```kotlin
133-
* val backStackItemMapper = BackStackEntryMapper<Any> { entry ->
131+
*
132+
* ...
133+
*
134+
* val backStackItemMapper = BackStackEntryMapper<NavKey> { entry ->
134135
* when (entry) {
135136
* is Home -> SentryBackStackEntry(Home.serializer().descriptor.serialName)
136137
* is ProductDetail -> SentryBackStackEntry(
@@ -139,14 +140,15 @@ public class SentryBackStackEntry(
139140
* // or non-performant.
140141
* arguments = mapOf("product_id" to entry.productId, "tab" to entry.tab)
141142
* )
143+
* ...
142144
* }
143145
* }
144146
* ```
145147
*/
146148
@ApiStatus.Experimental
147149
@ApiStatus.Internal
148150
public fun interface BackStackEntryMapper<T : Any> {
149-
public fun map(backStackEntry: T): SentryBackStackEntry
151+
public fun map(backStackEntry: T): SentryBackStackEntry?
150152
}
151153

152154
/**
@@ -165,7 +167,7 @@ public fun interface BackStackEntryMapper<T : Any> {
165167
internal class ForwardingBackStackEntryMapper<T : Any>(
166168
private val currentMapper: () -> BackStackEntryMapper<T>
167169
) {
168-
fun map(backStackEntry: T): SentryBackStackEntry = Snapshot.withoutReadObservation {
170+
fun map(backStackEntry: T): SentryBackStackEntry? = Snapshot.withoutReadObservation {
169171
currentMapper().map(backStackEntry)
170172
}
171173
}

‎sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavEffect.kt‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import org.jetbrains.annotations.ApiStatus
2121
*
2222
* // Place SentryNavEffect in the same composable as your NavDisplay and call
2323
* // the effect first. Doing so ensures the effect's lifecycle matches your
24-
* // NavDisplay, and that any Sentry data produced by your nav destinations
25-
* // get attributed to the appropriate nav transaction.
24+
* // NavDisplay, and that any Sentry data produced by your initial nav
25+
* // destination get attributed to the appropriate nav transaction.
2626
* SentryNavEffect(
2727
* backStack = navBackStack,
2828
* backStackEntryMapper = { entry ->
@@ -65,6 +65,10 @@ import org.jetbrains.annotations.ApiStatus
6565
* gestures. That means that spans produced by predictively rendered composables can show up under
6666
* the current destination's transaction.
6767
*
68+
* Multiple simultaneously active `SentryNavEffect` instances writing to the same Sentry scope are
69+
* not supported. Violating this restriction can result in interleaved breadcrumbs, clobbered screen
70+
* names and back stacks, and transactions that interfere with one another.
71+
*
6872
* @param backStack The navigation backstack to observe.
6973
* @param backStackEntryMapper Maps each entry of the [backStack] to a name and optional arguments
7074
* for display in Sentry. See the [BackStackEntryMapper] KDoc for best practices.

‎sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavOptions.kt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ private const val DEFAULT_MAX_CAPTURED_BACK_STACK_ENTRIES = 10
1313
* Instances are immutable; create one with the SentryNavOptions DSL:
1414
* ```kotlin
1515
* val options = SentryNavOptions {
16-
* captureBackStack = false
16+
* enableNavigationBreadcrumbs = false
1717
* maxCapturedBackStackEntries = 5
1818
* }
1919
* ```
@@ -110,7 +110,7 @@ private constructor(
110110
* Creates [SentryNavOptions]. Optionally configure it via [configure]. E.g.:
111111
* ```kotlin
112112
* val options = SentryNavOptions {
113-
* captureBackStack = false
113+
* enableNavigationBreadcrumbs = false
114114
* maxCapturedBackStackEntries = 5
115115
* }
116116
* ```

‎sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/BackStackConverterTest.kt‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class BackStackConverterTest {
3232

3333
private val defaultEntryMapper =
3434
BackStackEntryMapper<Any> { entry ->
35-
SentryBackStackEntry(entry::class.simpleName ?: "unknown")
35+
SentryBackStackEntry(entry::class.simpleName ?: "<unknown>")
3636
}
3737

3838
private fun getSut(
@@ -44,7 +44,7 @@ class BackStackConverterTest {
4444
)
4545

4646
private fun entryInfo(entry: Any, arguments: Map<String, Any?>? = null): SentryBackStackEntry =
47-
SentryBackStackEntry(entry::class.simpleName ?: "unknown", arguments)
47+
SentryBackStackEntry(entry::class.simpleName ?: "<unknown>", arguments)
4848

4949
private fun BackStackConverter<Any>.convert(entry: Any): NormalizedSentryBackStackEntry =
5050
convert(listOf(entry), RetentionPolicy.KEEP_FIRST).single()
@@ -300,6 +300,14 @@ class BackStackConverterTest {
300300
)
301301
}
302302

303+
@Test
304+
fun `convert returns unknown name without arguments if mapper returns null`() {
305+
val sut = getSut(entryMapper = { null })
306+
307+
assertThat(sut.convert(HomeScreen()))
308+
.isEqualTo(NormalizedSentryBackStackEntry(UNKNOWN_ENTRY_NAME))
309+
}
310+
303311
@Test
304312
fun `convert returns unknown name without arguments if mapper throws`() {
305313
val sut = getSut(entryMapper = { error("boom") })

‎sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/BackStackObserverTest.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class BackStackObserverTest {
4646
private class Fixture {
4747
private val defaultEntryMapper =
4848
BackStackEntryMapper<Any> { entry ->
49-
SentryBackStackEntry(entry::class.simpleName ?: "unknown")
49+
SentryBackStackEntry(entry::class.simpleName ?: "<unknown>")
5050
}
5151

5252
val logger = mock<ILogger>()

‎sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/ForwardingBackStackEntryMapperTest.kt‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ class ForwardingBackStackEntryMapperTest {
3131
BackStackEntryMapper<HomeScreen> { SentryBackStackEntry(it.id) }
3232
}
3333

34-
assertThat(sut.map(HomeScreen())).isEqualTo(SentryBackStackEntry("home"))
35-
assertThat(sut.map(HomeScreen()).arguments).isNull()
34+
val mapped = sut.map(HomeScreen())
35+
assertThat(mapped).isEqualTo(SentryBackStackEntry("home"))
36+
assertThat(mapped?.arguments).isNull()
37+
}
38+
39+
@Test
40+
fun `mapper forwards null results`() {
41+
val sut = ForwardingBackStackEntryMapper<HomeScreen> { BackStackEntryMapper { null } }
42+
assertThat(sut.map(HomeScreen())).isNull()
3643
}
3744

3845
@Test

‎sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/SentryNavEffectTest.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ class SentryNavEffectTest {
337337
val entryMapper =
338338
mutableStateOf<BackStackEntryMapper<Any>>(
339339
BackStackEntryMapper { entry ->
340-
SentryBackStackEntry(entry::class.simpleName ?: "unknown")
340+
SentryBackStackEntry(entry::class.simpleName ?: "<unknown>")
341341
}
342342
)
343343

0 commit comments

Comments
 (0)