-
Notifications
You must be signed in to change notification settings - Fork 898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spans not nesting correctly when calling auto-instrumented functions from manually instrumented Kotlin coroutines #7124
Comments
Probably the issue is that
|
I may be naive, but I thought that the purpose of That said, using your suggestion does work to some degree. Changing suspend fun pingMixedAsync() = withSpan {
coroutineContext.getOpenTelemetryContext().makeCurrent().use {
pingSync()
}
pingAsync()
coroutineContext.getOpenTelemetryContext().makeCurrent().use {
slowPingSync()
}
slowPingAsync()
} However, this is rather inconvenient to have to wrap every possible auto-instrumented call when called in the context of a coroutine. I tried to make it this instead with the hopes of moving it into suspend fun pingMixedAsync() = withSpan {
coroutineContext.getOpenTelemetryContext().makeCurrent().use {
pingSync()
pingAsync()
slowPingSync()
slowPingAsync()
}
} With the setup, To make it a little more concrete, take something like this: class MyHandler {
private val client = OkHttpClient()
private fun getFromApi(): String {
val request = Request.Builder()
.url("https://some.remote.resource.json")
.build();
return client.newCall(request).execute().use {
it.body?.string() ?: ""
}
}
@WithSpan
fun getFromApiAuto(): String {
// some work before fetching data
return getFromApi()
}
suspend fun getFromApiSuspend() = withSpan {
// some work that suspends before fetching data
getFromApi()
}
} Calling |
Same issue as #6502 (comment) |
I think the problem is in kotlin coroutine instrumentation, disabling it with |
Just to clarify @laurit, are you saying that it should work with kotlin coroutine instrumentation enabled but it's not so there is a bug to fix there, or that we should not be using the kotlin coroutine instrumentation when trying to trace around coroutines? (I'm assuming the former, but I'm fairly new to this world or OpenTelemetry and struggling to read between the lines) |
@mpeyper I believe that there is a bug. |
When you disable coroutine instrumentation it is possible that you'll need to use something like |
Yes, the traces are as I expect them with the instrumentation disabled: Note that I did not have to change any of the code shared above to get these traces, I just added I guess the obvious question is what are we missing by disabling the kotlin coroutine instrumentation? While these traces are now accurate, will there be others that aren't, or previously working cases that will now need manual instrumentation? |
When coroutine instrumentation is disabled you may need to manually propagate the parent span that is outside of the coroutine with |
@trask @laurit I finally got around to making the repro for you: https://github.com/mpeyper/open-telemetry-coroutine-tracing-repro Let me know if there is anything else I can do to help. |
Hopefully resolves #7124 Our kotlin coroutine instrumentation relies on a shaded copy of `opentelemetry-extension-kotlin`. This doesn't work well when application also uses `opentelemetry-extension-kotlin`, because the shaded and unshaded copy store opentelemery context under different key. This pr attempts to fix this by instrumenting `opentelemetry-extension-kotlin` provided by the application so that it would delegate to the one shaded inside the agent. Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
@trask I ran by repro test with the opentelemetry-javaagent-1.21.0-20221206.221310-88.jar build and the traces are produced correctly 🎉 Results can be seen here. |
Describe the bug
There are existing issues about
@WithSpan
not working with Kotlin Coroutines (#6502, #6542, #6776, #6887), but I think this issue is slightly different than those. Perhaps they are the same or similar issues, but I don't know enough to be sure.Essentially, I've got an auto-instrumented span (
io.opentelemetry.netty
) calling a GRPC handler that calls a coroutine that has been manually instrumented withKotlinContextElement
(io.opentelemetry.extension.kotlin
) and within that coroutine it calls some regular functions that have been auto-instrumented with@WithSpan
(io.opentelemetry.instrumentation.annotations
).When the spans are reported, the coroutine spans are correctly nested under the root netty span, however, the
@WithSpan
span is not nesting under the coroutine span, instead appearing as a sibling under the netty span.If the code is change to remove coroutines and just use
@WithSpan
the the nesting behaves correctly. Similarly, if the coroutines call other manually instrumented coroutines, the nesting also works as expectedSteps to reproduce
This is a contrived example, but this class demonstrates the issue:
where
withSpan
andtraceBlocking
look like this:and calling it like this:
Note: this was added to a private codebase using Armeria and GRPC for debugging, but if it's not helpful in this form, I can try to set up a smaller reproduction for you.
What did you expect to see?
Given the calls above I would expect to see traces nested something like this:
What did you see instead?
Any
...Sync
span that should be nested below an...Async
span is instead a sibling instead of a child.Note that only
pingMixedAsync
is different from what I expect here. The others work correctly as far as I can tell, I just left them in for completeness of what I have attempted.What version are you using?
opentelemetry-javaagent: 1.19.2
Environment
Compiler: openjdk 17.0.2 2022-01-18
OS: MacOS Ventura 13.0
Additional context
N/A
The text was updated successfully, but these errors were encountered: