Open
Description
Describe your environment
OS: Ubuntu
Python version: 3.11.0
Package version:
opentelemetry-api==1.34.1
opentelemetry-sdk==1.34.1
opentelemetry-instrumentation-fastapi==0.55b1
What happened?
When having a sync route in FastAPI and launching a background task, the changes done to the context do not appear in the context of the background task.
Steps to Reproduce
from fastapi import BackgroundTasks, FastAPI
from opentelemetry import context, trace
from opentelemetry.context import set_value
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
app = FastAPI()
# =========================================================================== #
# Optional: Bug is reproducible with or without setuping the resource, tracer
# provider and FastAPI instrumentor,
resource = Resource.create(attributes={SERVICE_NAME: "pricing-recommendation-engine"})
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)
# provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
FastAPIInstrumentor().instrument_app(app)
# =========================================================================== #
def my_background_task():
print(context.get_current())
def add_test_value_to_context():
ctx = context.get_current()
ctx = set_value("test_key", "test_value", context=ctx)
context.attach(ctx)
@app.get("/sync-endpoint")
def sync_endpoint(background_tasks: BackgroundTasks):
print(context.get_current())
add_test_value_to_context()
print(context.get_current())
background_tasks.add_task(my_background_task)
return "Hello, World!"
@app.get("/async-endpoint")
async def async_endpoint(background_tasks: BackgroundTasks):
print(context.get_current())
add_test_value_to_context()
print(context.get_current())
background_tasks.add_task(my_background_task)
return "Hello, World!"
uvicorn fastapi_context_bug:app
On endpoint /sync-endpoint
, we get this:
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /sync-endpoint", context=SpanContext(trace_id=0x3d1bdba09cbb92564db952045e92ab94, span_id=0x93ec8565cd311ed4, trace_flags=0x01, trace_state=[], is_remote=False))}
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /sync-endpoint", context=SpanContext(trace_id=0x3d1bdba09cbb92564db952045e92ab94, span_id=0x93ec8565cd311ed4, trace_flags=0x01, trace_state=[], is_remote=False)), 'test_key': 'test_value'}
INFO: 127.0.0.1:45994 - "GET /sync-endpoint HTTP/1.1" 200 OK
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /sync-endpoint", context=SpanContext(trace_id=0x3d1bdba09cbb92564db952045e92ab94, span_id=0x93ec8565cd311ed4, trace_flags=0x01, trace_state=[], is_remote=False))}
On endpoint /async-endpoint
, we get this:
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /async-endpoint", context=SpanContext(trace_id=0xf1009be126c6edf441c7f465fcc05e7e, span_id=0xfa1e818754376b97, trace_flags=0x01, trace_state=[], is_remote=False))}
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /async-endpoint", context=SpanContext(trace_id=0xf1009be126c6edf441c7f465fcc05e7e, span_id=0xfa1e818754376b97, trace_flags=0x01, trace_state=[], is_remote=False)), 'test_key': 'test_value'}
INFO: 127.0.0.1:48510 - "GET /async-endpoint HTTP/1.1" 200 OK
{'current-span-b13884d6-004f-41b3-84b0-8704e8205ff6': _Span(name="GET /async-endpoint", context=SpanContext(trace_id=0xf1009be126c6edf441c7f465fcc05e7e, span_id=0xfa1e818754376b97, trace_flags=0x01, trace_state=[], is_remote=False)), 'test_key': 'test_value'}
Expected Result
The sync route should behave as the async route.
Actual Result
See above.
Additional context
No response
Would you like to implement a fix?
None