open-telemetry / open-telemetry/opentelemetry-java-instrumentation
Ktor 3 client auto-instrumentation does not propagate trace context when used inside Ktor server
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 2.6k
- Forks
- 1.2k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 228
Description
Describe the bug
When using the OpenTelemetry Java Agent with a Ktor 3 application, outgoing requests made via HttpClient inside a Ktor server handler do not propagate the trace context.
- Context.current() and Span.current() are valid inside the server handler
- However, the outgoing Ktor client request does not include a traceparent header
- No CLIENT span is created for the outgoing request
The Ktor client instrumentation module is applied according to debug logs.
Steps to reproduce
Minimal JUnit test:
@Test
fun `ktor client inside ktor server does send traceparent`() = testApplication {
var receivedTraceparent: String? = null
val stubPort = 9090
val stubServer = embeddedServer(CIO, port = stubPort) {
routing {
get("/tracing-test") {
receivedTraceparent = call.request.headers["traceparent"]
call.respond(HttpStatusCode.OK)
}
}
}.start(wait = false)
val outboundClient = HttpClient(CIO)
try {
application {
routing {
get("/trigger") {
val currentSpan = Span.current()
val traceparent = Context.current()
println("Current span valid: ${currentSpan.spanContext.isValid}")
println("Current traceId: ${currentSpan.spanContext.traceId}")
println("Current traceparent: $traceparent")
outboundClient.get("http://localhost:$stubPort/tracing-test")
call.respond(HttpStatusCode.OK)
}
}
}
val testClient = createClient {}
testClient.get("/trigger")
println("Received traceparent: $receivedTraceparent")
assertNotNull(receivedTraceparent, "traceparent should be propagated")
} finally {
outboundClient.close()
stubServer.stop(1_000, 2_000)
}
}
Expected behavior
- A CLIENT span should be created for the outgoing Ktor request
- The traceparent header should be injected automatically
Actual behavior
- No CLIENT span is created
- No traceparent header is sent
Javaagent or library instrumentation version
2.26.1, 2.27.0
Environment
JDK: 21
Kotlin: 2.3.21
Ktor: 3.4.3
Additional context
No response
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal JUnit test in the issue and reproduce the request using Ktor 3's HttpClient inside a Ktor server handler. Check the Ktor client instrumentation behavior when the server context is active, using the debug logs and assertions for the CLIENT span and traceparent header. Done means the outgoing request creates a CLIENT span and propagates traceparent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, kotlin
- Domain
- backend, observability-sre
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100