diff --git a/sentry-async-profiler/build.gradle.kts b/sentry-async-profiler/build.gradle.kts index 17454baa662..b96629c3aba 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.inline) 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 } + } +}