Skip to content

Commit e07735d

Browse files
runningcodeclaude
andcommitted
test(core): Add an end-to-end test of the core APIs over the HTTP transport
SentryEndToEndTest reports through the APIs an app uses without integrations and checks what reaches MockSentryServer: messages at the scope's and an explicit level, an exception with its feature flag, an event with a fingerprint, breadcrumbs from an event processor and a beforeBreadcrumb callback, ten events in a row, a transaction with a child span, and metrics with the scope's attributes. It ports the core part of the console sample's system test, which ran the sample's JAR against the Python mock server. The sample's profiling and Kafka parts follow in their own modules. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 9f9979b commit e07735d

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package io.sentry
2+
3+
import com.google.common.truth.Truth.assertThat
4+
import io.sentry.protocol.Message
5+
import io.sentry.test.MockSentryServer
6+
import io.sentry.test.event
7+
import io.sentry.test.hasFlag
8+
import io.sentry.test.hasMetric
9+
import io.sentry.test.hasMetricWithAttribute
10+
import io.sentry.test.initForTest
11+
import io.sentry.test.metrics
12+
import io.sentry.test.transaction
13+
import kotlin.test.AfterTest
14+
import kotlin.test.Test
15+
16+
/** Reports through the APIs an app uses without integrations, over the real HTTP transport. */
17+
class SentryEndToEndTest {
18+
private val server = MockSentryServer()
19+
20+
@AfterTest
21+
fun teardown() {
22+
Sentry.close()
23+
server.close()
24+
}
25+
26+
@Test
27+
fun `events, a transaction and metrics reach Sentry`() {
28+
initForTest {
29+
it.dsn = server.dsn
30+
it.tracesSampleRate = 1.0
31+
it.beforeBreadcrumb = SentryOptions.BeforeBreadcrumbCallback { breadcrumb, _ ->
32+
if (breadcrumb.message == "bad breadcrumb") null else breadcrumb
33+
}
34+
}
35+
Sentry.addBreadcrumb("bad breadcrumb")
36+
Sentry.configureScope {
37+
it.addEventProcessor(
38+
object : EventProcessor {
39+
override fun process(event: SentryEvent, hint: Hint): SentryEvent = event.apply {
40+
if ((level?.ordinal ?: 0) > SentryLevel.INFO.ordinal) {
41+
addBreadcrumb(Breadcrumb("Processed by the event processor"))
42+
}
43+
}
44+
}
45+
)
46+
}
47+
48+
Sentry.withScope {
49+
it.level = SentryLevel.FATAL
50+
Sentry.captureMessage("Fatal message!")
51+
}
52+
Sentry.captureMessage("Some warning!", SentryLevel.WARNING)
53+
Sentry.addFeatureFlag("my-feature-flag", true)
54+
Sentry.setAttribute("user.type", "admin")
55+
Sentry.setAttribute("feature.version", 2)
56+
Sentry.metrics().count("countMetric")
57+
Sentry.metrics().gauge("gaugeMetric", 5.0)
58+
Sentry.metrics().distribution("distributionMetric", 7.0)
59+
Sentry.captureException(RuntimeException("Some error!"))
60+
Sentry.captureEvent(
61+
SentryEvent().apply {
62+
message = Message().apply { message = "Detailed event" }
63+
fingerprints = listOf("NewClientDebug")
64+
level = SentryLevel.DEBUG
65+
}
66+
)
67+
repeat(10) { i ->
68+
Sentry.captureEvent(
69+
SentryEvent().apply { message = Message().apply { message = "event $i" } }
70+
)
71+
}
72+
val transaction = Sentry.startTransaction("transaction name", "op")
73+
transaction.startChild("child").finish()
74+
transaction.finish()
75+
Sentry.flush(5000)
76+
77+
val fatal =
78+
server.awaitEnvelope { it.event()?.message?.formatted == "Fatal message!" }.event()!!
79+
assertThat(fatal.level).isEqualTo(SentryLevel.FATAL)
80+
assertThat(fatal.breadcrumbs!!.map { it.message }).contains("Processed by the event processor")
81+
assertThat(fatal.breadcrumbs!!.map { it.message }).doesNotContain("bad breadcrumb")
82+
83+
val warning =
84+
server.awaitEnvelope { it.event()?.message?.formatted == "Some warning!" }.event()!!
85+
assertThat(warning.level).isEqualTo(SentryLevel.WARNING)
86+
87+
val error =
88+
server
89+
.awaitEnvelope { it.event()?.exceptions?.any { e -> e.value == "Some error!" } == true }
90+
.event()!!
91+
assertThat(error.hasFlag("my-feature-flag", true)).isTrue()
92+
93+
val detailed =
94+
server.awaitEnvelope { it.event()?.message?.message == "Detailed event" }.event()!!
95+
assertThat(detailed.fingerprints).containsExactly("NewClientDebug")
96+
assertThat(detailed.level).isEqualTo(SentryLevel.DEBUG)
97+
98+
repeat(10) { i -> server.awaitEnvelope { it.event()?.message?.message == "event $i" } }
99+
100+
val sent =
101+
server.awaitEnvelope { it.transaction()?.transaction == "transaction name" }.transaction()!!
102+
assertThat(sent.spans.map { it.op }).contains("child")
103+
104+
val metrics = server.awaitEnvelope { it.metrics() != null }.metrics()!!
105+
assertThat(metrics.hasMetric("countMetric", "counter", 1.0)).isTrue()
106+
assertThat(metrics.hasMetric("gaugeMetric", "gauge", 5.0)).isTrue()
107+
assertThat(metrics.hasMetric("distributionMetric", "distribution", 7.0)).isTrue()
108+
assertThat(metrics.hasMetricWithAttribute("countMetric", "user.type", "admin")).isTrue()
109+
assertThat(metrics.hasMetricWithAttribute("countMetric", "feature.version", 2)).isTrue()
110+
}
111+
}

0 commit comments

Comments
 (0)