From dfb3bbacc6c7a49db370899189c30637e52da00f Mon Sep 17 00:00:00 2001 From: Nelson Osacky Date: Tue, 20 Oct 2026 19:47:25 +0200 Subject: [PATCH] test(async-profiler): Add an end-to-end test of a profiled transaction ContinuousProfilerEndToEndTest starts a sampled transaction with the TRACE profile lifecycle and checks that its profile chunk reaches MockSentryServer, linked to the transaction by the profiler ID. It ports the profiling part of the console sample's system test. The profiler rejects a traces path with a dot anywhere in its absolute form, so the test puts it in the temp dir. Co-Authored-By: Claude Opus 5.5 (1M context) --- sentry-async-profiler/build.gradle.kts | 1 + .../ContinuousProfilerEndToEndTest.kt | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 sentry-async-profiler/src/test/java/io/sentry/asyncprofiler/ContinuousProfilerEndToEndTest.kt diff --git a/sentry-async-profiler/build.gradle.kts b/sentry-async-profiler/build.gradle.kts index 3bcdefd1d82..fbb4a8fc353 100644 --- a/sentry-async-profiler/build.gradle.kts +++ b/sentry-async-profiler/build.gradle.kts @@ -32,6 +32,7 @@ dependencies { // tests testImplementation(kotlin(Config.kotlinStdLib)) testImplementation(projects.sentryTestSupport) + testImplementation(libs.google.truth) testImplementation(libs.kotlin.test.junit) testImplementation(libs.mockito.kotlin) testImplementation(libs.mockito.core) diff --git a/sentry-async-profiler/src/test/java/io/sentry/asyncprofiler/ContinuousProfilerEndToEndTest.kt b/sentry-async-profiler/src/test/java/io/sentry/asyncprofiler/ContinuousProfilerEndToEndTest.kt new file mode 100644 index 00000000000..25f8d0b9940 --- /dev/null +++ b/sentry-async-profiler/src/test/java/io/sentry/asyncprofiler/ContinuousProfilerEndToEndTest.kt @@ -0,0 +1,48 @@ +package io.sentry.asyncprofiler + +import com.google.common.truth.Truth.assertThat +import io.sentry.ProfileLifecycle +import io.sentry.Sentry +import io.sentry.test.MockSentryServer +import io.sentry.test.initForTest +import io.sentry.test.profileChunk +import io.sentry.test.transaction +import kotlin.test.AfterTest +import kotlin.test.Test + +/** Profiles a transaction with the async profiler and sends both over the real HTTP transport. */ +class ContinuousProfilerEndToEndTest { + private val server = MockSentryServer() + + @AfterTest + fun teardown() { + Sentry.close() + server.close() + } + + @Test + fun `a transaction starts a profile whose chunk reaches Sentry`() { + initForTest { + it.dsn = server.dsn + it.tracesSampleRate = 1.0 + it.profileSessionSampleRate = 1.0 + it.profileLifecycle = ProfileLifecycle.TRACE + // The profiler rejects a traces path with a dot anywhere in it, which the module's absolute + // path can have. + it.profilingTracesDirPath = + "${System.getProperty("java.io.tmpdir")}/sentry-profiler-end-to-end-test" + } + + val transaction = Sentry.startTransaction("transaction name", "op") + val span = transaction.startChild("child") + Thread.sleep(100) + span.finish() + transaction.finish() + + val sent = + server.awaitEnvelope { it.transaction()?.transaction == "transaction name" }.transaction()!! + val profilerId = sent.contexts.profile?.profilerId + assertThat(profilerId).isNotNull() + server.awaitEnvelope(timeoutMillis = 30_000) { it.profileChunk()?.profilerId == profilerId } + } +}