Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is OpenTelemetry in Python safe to use with Async?

I want to use OpenTelemetry with an Async application, and I want to be 101% sure that it will work as intended. Specifically, I'm worried about what happens with the current_span when we switch back and forth between asynchronous functions. I have this fear that if I rely on tracer.start_as_current_span to set the span in each function, and then I pass execution to another function which also sets the current_span, then when execution passes back to the first function it won't be tied to the correct span anymore.

Now, I have tried testing this a bit, and found no evidence that it breaks. But I also haven't found any documentation that says it explicitly won't break. Can anyone confirm?

I've done the following basic test, but I'm worried it misses something:

async def async_span():
    with tracer.start_as_current_span(name=f"span_{uuid.uuid4}") as span:
        for x in range(1000):
            assert trace.get_current_span() == span
            await asyncio.sleep(0.0001 * randint(1, 10))

async def main():
    with tracer.start_as_current_span(name="parent"):
        await asyncio.gather(*(async_span() for _ in range(10)))
like image 344
Wyko ter Haar Avatar asked Aug 04 '26 19:08

Wyko ter Haar


2 Answers

OpenTelemetry for Python supports asynchronous code.

Went through the code for version 1.24.0/0.45b0 of opentelemetry-python. The code contains abstract context class _RuntimeContext. _RuntimeContext has single implementation ContextVarsRuntimeContext that utilizes contextvars. ContextVarsRuntimeContext is used as a default context.

like image 169
Oleksii Avatar answered Aug 07 '26 08:08

Oleksii


I hope, OpenTelemetry for Python is designed to consider asynchronous code. When you use tracer.start_as_current_span within an asynchronous context, the span becomes the current span for the duration of that context.

The key point is that the association of the current span is managed on a per-task basis. Asynchronous tasks in Python have their own context, and the asyncio event loop ensures that the task-local context is preserved when tasks switch back and forth.

like image 43
Aleksandr Avatar answered Aug 07 '26 08:08

Aleksandr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!