Skip to content
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

Kotlin extension - coroutines example #188

Merged
merged 11 commits into from
Jul 31, 2023

Conversation

LikeTheSalad
Copy link
Contributor

This is an example of how to use the Context.asContextElement extension function provided in the OTel Java Kotlin extension library in order to preserve a Span context across a coroutine, even if its thread changes.

@LikeTheSalad LikeTheSalad requested review from a team as code owners July 28, 2023 13:59
Copy link
Contributor

@breedx-splk breedx-splk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. Seems like a clear example to me. Just offered a few suggestions.

Comment on lines 51 to 53
val finishedSpanItems = inMemoryExporter.finishedSpanItems
println("First child's trace id: ${finishedSpanItems[1].traceId}") // The same as the root span's.
println("Second child's trace id: ${finishedSpanItems[2].traceId}") // The same as the root span's.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would have a restructure a little bit, but what about moving this to the main method after the latch is awaited? That feels a bit more "finalized" to me and also more clearly shows that this is the demonstrated example output.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add the thread.id as an attribute to the spans and print it here? I guess there's no simple way to force the execution to be on a different thread, but it would be a nice visual verification that it works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've made some changes to it to clean it up a bit and to move the verification part outside of the coroutine block. I also like the idea of printing the thread.id, so that's added now as well.

settings.gradle Outdated Show resolved Hide resolved
// Bonus: If we wanted to launch a coroutine in a separate thread (not IO, which is the one set in the scope) while
// keeping the Span context too, we could do so like this:
// scope.launch(Dispatchers.Main + Context.current().asContextElement())
scope.launch(Context.current().asContextElement()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a kotlin dev so sorry if I have misunderstood it, but couldn't you just use the Job returned from scope.launch and call join on it to wait for the coroutine to complete? Then you could move everything that comes after createChildrenSpans out of the coroutine. Closing a scope on a thread different from the one that opened it doesn't really work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great point, thanks. I wanted to make it easy to read even for non kotlin devs, though it certainly looked a bit strange so I just applied your suggestion and it looks cleaner now.

@trask
Copy link
Member

trask commented Jul 31, 2023

/easycla

@trask trask merged commit c34bfc5 into open-telemetry:main Jul 31, 2023
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants