Skip to content

Commit 63719a5

Browse files
authored
fix: beforeBreadcrumb (#105)
* Fix iOS beforeBreadcrumb discarding breadcrumbs if the callback is not set * Update changelog * Apply formatting * Fix test * Add additional beforeBreadcrumb tests * Update CHANGELOG.md * Update changelog
1 parent 2361547 commit 63719a5

File tree

8 files changed

+234
-3
lines changed

8 files changed

+234
-3
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- fix: beforeBreadcrumb discarding if hook is not set ([#105](https://github.com/getsentry/sentry-kotlin-multiplatform/pull/105))
8+
39
## 0.2.0
410

511
### Features

sentry-kotlin-multiplatform/src/commonAppleMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.apple.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ internal fun CocoaSentryOptions.applyCocoaBaseOptions(options: SentryOptions) {
6767
PrivateSentrySDKOnly.setSdkName(sdkName, sdkVersion)
6868

6969
beforeBreadcrumb = { cocoaBreadcrumb ->
70-
cocoaBreadcrumb?.toKmpBreadcrumb()
71-
?.let { options.beforeBreadcrumb?.invoke(it) }?.toCocoaBreadcrumb()
70+
if (options.beforeBreadcrumb == null) {
71+
cocoaBreadcrumb
72+
} else {
73+
cocoaBreadcrumb?.toKmpBreadcrumb()
74+
?.let { options.beforeBreadcrumb?.invoke(it) }?.toCocoaBreadcrumb()
75+
}
7276
}
7377

7478
enableCaptureFailedRequests = options.enableCaptureFailedRequests
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.sentry.kotlin.multiplatform
2+
3+
import io.sentry.kotlin.multiplatform.extensions.applyCocoaBaseOptions
4+
import io.sentry.kotlin.multiplatform.extensions.toKmpBreadcrumb
5+
import io.sentry.kotlin.multiplatform.protocol.Breadcrumb
6+
7+
actual class BreadcrumbConfigurator {
8+
private val cocoaBreadcrumb = CocoaBreadcrumb()
9+
actual val originalBreadcrumb: Breadcrumb = cocoaBreadcrumb.toKmpBreadcrumb()
10+
11+
actual fun applyOptions(optionsConfiguration: OptionsConfiguration): Breadcrumb? {
12+
val kmpOptions = SentryOptions()
13+
optionsConfiguration.invoke(kmpOptions)
14+
return applyOptions(kmpOptions)
15+
}
16+
17+
actual fun applyOptions(options: SentryOptions): Breadcrumb? {
18+
val cocoaOptions = CocoaSentryOptions()
19+
cocoaOptions.applyCocoaBaseOptions(options)
20+
val cocoaModifiedBreadcrumb = cocoaOptions.beforeBreadcrumb?.invoke(cocoaBreadcrumb)
21+
return cocoaModifiedBreadcrumb?.toKmpBreadcrumb()
22+
}
23+
}

sentry-kotlin-multiplatform/src/commonJvmMain/kotlin/io/sentry/kotlin/multiplatform/extensions/SentryOptionsExtensions.jvm.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ internal fun JvmSentryOptions.applyJvmBaseOptions(options: SentryOptions) {
4141
maxAttachmentSize = options.maxAttachmentSize
4242
maxBreadcrumbs = options.maxBreadcrumbs
4343
setBeforeBreadcrumb { jvmBreadcrumb, _ ->
44-
options.beforeBreadcrumb?.invoke(jvmBreadcrumb.toKmpBreadcrumb())?.toJvmBreadcrumb()
44+
if (options.beforeBreadcrumb == null) {
45+
jvmBreadcrumb
46+
} else {
47+
options.beforeBreadcrumb?.invoke(jvmBreadcrumb.toKmpBreadcrumb())?.toJvmBreadcrumb()
48+
}
4549
}
4650
setBeforeSend { jvmSentryEvent, hint ->
4751
if (options.beforeSend == null) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.sentry.kotlin.multiplatform
2+
3+
import io.sentry.Hint
4+
import io.sentry.kotlin.multiplatform.extensions.applyJvmBaseOptions
5+
import io.sentry.kotlin.multiplatform.extensions.toKmpBreadcrumb
6+
import io.sentry.kotlin.multiplatform.protocol.Breadcrumb
7+
8+
actual class BreadcrumbConfigurator {
9+
private val jvmBreadcrumb = JvmBreadcrumb()
10+
actual val originalBreadcrumb: Breadcrumb = jvmBreadcrumb.toKmpBreadcrumb()
11+
12+
actual fun applyOptions(optionsConfiguration: OptionsConfiguration): Breadcrumb? {
13+
val kmpOptions = SentryOptions()
14+
optionsConfiguration.invoke(kmpOptions)
15+
return applyOptions(kmpOptions)
16+
}
17+
18+
actual fun applyOptions(options: SentryOptions): Breadcrumb? {
19+
val jvmOptions = JvmSentryOptions()
20+
jvmOptions.applyJvmBaseOptions(options)
21+
val jvmHint = Hint()
22+
val jvmModifiedBreadcrumb = jvmOptions.beforeBreadcrumb?.execute(jvmBreadcrumb, jvmHint)
23+
return jvmModifiedBreadcrumb?.toKmpBreadcrumb()
24+
}
25+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package io.sentry.kotlin.multiplatform
2+
3+
import io.sentry.kotlin.multiplatform.utils.fakeDsn
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
import kotlin.test.assertNotNull
7+
import kotlin.test.assertNull
8+
9+
class BeforeBreadcrumbIntegrationTest {
10+
private val breadcrumbConfigurator = BreadcrumbConfigurator()
11+
12+
@Test
13+
fun `breadcrumb is not null if KMP beforeBreadcrumb callback config is null`() {
14+
val breadcrumb = breadcrumbConfigurator.applyOptions {
15+
it.dsn = fakeDsn
16+
}
17+
assertNotNull(breadcrumb)
18+
}
19+
20+
@Test
21+
fun `breadcrumb is null if KMP beforeBreadcrumb callback config returns null`() {
22+
val breadcrumb = breadcrumbConfigurator.applyOptions {
23+
it.dsn = fakeDsn
24+
it.beforeBreadcrumb = {
25+
null
26+
}
27+
}
28+
assertNull(breadcrumb)
29+
}
30+
31+
@Test
32+
fun `breadcrumb is not null if KMP beforeBreadcrumb callback config returns not null`() {
33+
val breadcrumb = breadcrumbConfigurator.applyOptions {
34+
it.dsn = fakeDsn
35+
it.beforeBreadcrumb = { breadcrumb ->
36+
breadcrumb
37+
}
38+
}
39+
assertNotNull(breadcrumb)
40+
}
41+
42+
@Test
43+
fun `breadcrumb level is not modified if KMP beforeBreadcrumb callback config does not modify it`() {
44+
val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb
45+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
46+
it.dsn = fakeDsn
47+
it.beforeBreadcrumb = { breadcrumb ->
48+
breadcrumb
49+
}
50+
}
51+
assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level)
52+
}
53+
54+
@Test
55+
fun `breadcrumb level is modified if KMP beforeBreadcrumb callback config modifies it`() {
56+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
57+
it.dsn = fakeDsn
58+
it.beforeBreadcrumb = { breadcrumb ->
59+
breadcrumb.level = SentryLevel.WARNING
60+
breadcrumb
61+
}
62+
}
63+
assertEquals(SentryLevel.WARNING, modifiedBreadcrumb?.level)
64+
}
65+
66+
@Test
67+
fun `breadcrumb category is not modified if KMP beforeBreadcrumb callback config does not modify it`() {
68+
val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb
69+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
70+
it.dsn = fakeDsn
71+
it.beforeBreadcrumb = { breadcrumb ->
72+
breadcrumb
73+
}
74+
}
75+
assertEquals(originalBreadcrumb.category, modifiedBreadcrumb?.category)
76+
}
77+
78+
@Test
79+
fun `breadcrumb category is modified if KMP beforeBreadcrumb callback config modifies it`() {
80+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
81+
it.dsn = fakeDsn
82+
it.beforeBreadcrumb = { breadcrumb ->
83+
breadcrumb.category = "category"
84+
breadcrumb
85+
}
86+
}
87+
assertEquals("category", modifiedBreadcrumb?.category)
88+
}
89+
90+
@Test
91+
fun `breadcrumb type is not modified if KMP beforeBreadcrumb callback config does not modify it`() {
92+
val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb
93+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
94+
it.dsn = fakeDsn
95+
it.beforeBreadcrumb = { breadcrumb ->
96+
breadcrumb
97+
}
98+
}
99+
assertEquals(originalBreadcrumb.type, modifiedBreadcrumb?.type)
100+
}
101+
102+
@Test
103+
fun `breadcrumb type is modified if KMP beforeBreadcrumb callback config modifies it`() {
104+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
105+
it.dsn = fakeDsn
106+
it.beforeBreadcrumb = { breadcrumb ->
107+
breadcrumb.type = "type"
108+
breadcrumb
109+
}
110+
}
111+
assertEquals("type", modifiedBreadcrumb?.type)
112+
}
113+
114+
@Test
115+
fun `breadcrumb message is not modified if KMP beforeBreadcrumb callback config does not modify it`() {
116+
val originalBreadcrumb = breadcrumbConfigurator.originalBreadcrumb
117+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
118+
it.dsn = fakeDsn
119+
it.beforeBreadcrumb = { breadcrumb ->
120+
breadcrumb
121+
}
122+
}
123+
assertEquals(originalBreadcrumb.level, modifiedBreadcrumb?.level)
124+
}
125+
126+
@Test
127+
fun `breadcrumb message is modified if KMP beforeBreadcrumb callback config modifies it`() {
128+
val modifiedBreadcrumb = breadcrumbConfigurator.applyOptions {
129+
it.dsn = fakeDsn
130+
it.beforeBreadcrumb = { breadcrumb ->
131+
breadcrumb.message = "message"
132+
breadcrumb
133+
}
134+
}
135+
assertEquals("message", modifiedBreadcrumb?.message)
136+
}
137+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.sentry.kotlin.multiplatform
2+
3+
import io.sentry.kotlin.multiplatform.protocol.Breadcrumb
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
7+
class BeforeBreadcrumbTest {
8+
@Test
9+
fun `beforeBreadcrumb drops breadcrumb`() {
10+
val options = SentryOptions()
11+
options.beforeBreadcrumb = {
12+
null
13+
}
14+
15+
val breadcrumb = options.beforeBreadcrumb?.invoke(Breadcrumb())
16+
17+
assertEquals(null, breadcrumb)
18+
}
19+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.sentry.kotlin.multiplatform
2+
3+
import io.sentry.kotlin.multiplatform.protocol.Breadcrumb
4+
5+
/**
6+
* This class deals with configuring and modifying a Breadcrumb.
7+
* It is used to test any code that can alter a Breadcrumb.
8+
*/
9+
expect class BreadcrumbConfigurator() {
10+
val originalBreadcrumb: Breadcrumb
11+
fun applyOptions(optionsConfiguration: OptionsConfiguration): Breadcrumb?
12+
fun applyOptions(options: SentryOptions = SentryOptions()): Breadcrumb?
13+
}

0 commit comments

Comments
 (0)