Skip to content

[Bug]:trace_enabled context loss in async frameworks with uvicorn #1208

@chunterg

Description

@chunterg

Describe the bug
When using AgentScope with tracing_url configured in async frameworks like FastAPI, the trace_enabled flag stored in ContextVar may lose its value, causing the tracing
functionality to fail silently.

The issue occurs because uvicorn creates a new Context for each request, causing ContextVar values to reset to their default values. This means that even after
agentscope.init() successfully sets trace_enabled = True, the value becomes False when processing HTTP requests, resulting in tracing being disabled.

To Reproduce
Steps to reproduce the behavior:

  1. Initialize AgentScope with tracing configured:
import agentscope
agentscope.init(
    project='test-project',
    studio_url='http://localhost:3000',
    tracing_url='http://localhost:3000/v1/traces'
)
  1. Create a traced function:
from agentscope.tracing import trace

@trace(name='test_function')
async def test_function():
    print('Traced function executed')
    return 'success'
  1. Execute in FastAPI or similar async framework using asyncio.create_task():
import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get('/test')
async def test_endpoint():
    # In FastAPI, the request handler may run in a new task
    # where ContextVar context is lost
    task = asyncio.create_task(test_function())
    result = await task
    return {'result': result}
  1. Check AgentScope Studio or tracing backend
    • Expected: Trace data should be recorded
    • Actual: No trace data is recorded

Expected behavior
When tracing_url is configured during agentscope.init(), the tracing functionality should work consistently across all async tasks and concurrency patterns, regardless of whether the ContextVar context is properly inherited or not.

Error messages
No explicit error messages are thrown. The issue manifests silently as missing trace data in the tracing backend (AgentScope Studio or external OpenTelemetry backend).

Environment (please complete the following information):

  • AgentScope Version: 1.0.14 (via import agentscope; print(agentscope.__version__))
  • Python Version: 3.11.13
  • OS: macOS (Darwin 25.1.0)
  • Framework: FastAPI with uvicorn
  • Uvicorn Configuration: uvicorn.run("server:app", host="0.0.0.0", port=8080) (default settings, single worker)

Additional context
Root cause: uvicorn creates new Context for each request
Through detailed investigation, I discovered that the issue is specifically caused by uvicorn's behavior:

  1. Module-level initialization sets trace_enabled = True
  2. uvicorn starts and reimports the module, setting trace_enabled = True
  3. lifespan runs successfully with trace_enabled = True
  4. uvicorn receives a request and creates a new Context
  5. ContextVar value is reset to default value False in the new Context
  6. Request processing runs with trace_enabled = False

Suggested solution:
Add a global flag to track whether tracing has been configured, and modify _check_tracing_enabled() to check this flag first:

# In agentscope/tracing/_trace.py
def _check_tracing_enabled() -> bool:
    """Check if tracing is enabled"""
    from opentelemetry import trace
    from opentelemetry.sdk.trace import TracerProvider

    # Check if a real TracerProvider is set (not the default proxy)
    tracer_provider = trace.get_tracer_provider()
    if isinstance(tracer_provider, TracerProvider):
        # A real TracerProvider exists, which means tracing was configured
        return True

    # Fall back to ContextVar for runtime control
    return _config.trace_enabled

This ensures that once tracing is configured via init(), it remains enabled regardless of ContextVar context propagation issues, while still allowing runtime control when tracing is not configured.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions