Replies: 3 comments 5 replies
-
The use of the "active span concept" is not recommended for asynchronous code. This is because the active span relies on thread-local context for its management, but asynchronous code may operate across multiple threads internally. Your best bet would be to pass the parent span id across the async code (by capturing in lambda or other means) and explicitly set it while creating child span.
I know languages like Rust, JS, Python, .Net support propagating context across the async/await calls or the futures. C++ doesn't have any such mechanism supported. |
Beta Was this translation helpful? Give feedback.
-
An old thread but lifting this issue(s) again as initially my concern was about active Span and logging. But I can now see the same problem in the Carrier concept as well. Consider the example code:
Together with Boost Beast multiple asynchronous clients using co_await: Injecting traceparent into every As I understands it(might be wrong here) the Carrier concept relies on picking up the Context using But it feels like a forced construction passing around both Span and Context object. It sure would be nice if you can get the Context from your Span object. @lalitb any thoughts about my concerns regarding the Carrier concept? |
Beta Was this translation helpful? Give feedback.
-
Hi @nic-godz , sorry if my messge is off topic, but I'm trying to implement asynchronous code in my project, what did you do?, there's no documentation around the ENABLE_ASYNC_EXPORT flag. |
Beta Was this translation helpful? Give feedback.
-
I have been using opentelemetry-cpp for tracing & logging for a while now. The metrics part is still to be used(have been testing it)
All C++ applications, using otel-cpp, is asynchronous and based on Boost Asio. My experience is that setting spans to active when you have a lot of asynchronous operations going can can really mess up parent-child span connections.
For instance if an outgoing request is divided into several asynchronous operations and a span is created and set active until reply is received. The scope object is kept as well for the lifetime of the request. Some nested spans are created for DNS resolve, connection, write, ...
But when parallel requests are created the same way, things start to go bad as suddenly other requests starts getting active and child spans will get the wrong connections to parents. Same goes for Logs connected to a specific span context.
My experience is to avoid setting spans to active and instead explicitly set parent span like:
options.parent = parent_span->GetContext();
And if WithActiveSpan(span) is used, the scope should never exist over asynchronous operations. But if you are using Boost Asio with stackful coroutines async code looks like sync code(thats the point) and you can easily forget that execution will leave in the middle of a function and continue later. So if a span scope is a stack variable it will survive over multiple asynchronous operation.
Whats your take on this? I have really no good ideas here. I guess it all boils down to the execution of ::RuntimeContext::GetCurrent() ? But there is really no magic you can use here to solve this. How is this handled in other languages?
Beta Was this translation helpful? Give feedback.
All reactions