You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python OpenTelemetry中为异步后台任务创建顶级Span

问题描述

在Python服务中接入OpenTelemetry后,手动追踪用户请求与子任务的功能已正常工作,可在Jaeger中查看对应的Span。但请求过程中启动的异步后台任务,其Span默认作为已结束请求Span的子Span,需要将这些后台任务的Span设置为无父级的顶级Span。

解决方案

核心是在启动后台任务的Span时,使用空上下文切断与请求Span的关联,避免继承父Span信息。不要使用模块加载时提前获取的ROOT_CONTEXT,因为该上下文可能包含进程级别的初始信息,无法保证完全无父。

修改后的代码示例:

from opentelemetry import trace
from opentelemetry import context
import asyncio

tracer = trace.get_tracer(__name__)
tasks = set()

async def background_task(some_req_info):
    # 传入空上下文创建顶级Span,不继承任何父Span
    with tracer.start_as_current_span("background task", context=context.create_empty_context()):
        # 后台任务逻辑
        await asyncio.sleep(2)
        print(f"后台任务处理完成: {some_req_info}")

async def request(some_req_info):
    with tracer.start_as_current_span("request"):
        # 请求处理逻辑
        print(f"处理请求: {some_req_info}")
        task = asyncio.create_task(background_task(some_req_info))
        tasks.add(task)
        task.add_done_callback(tasks.discard)
        return "请求已接收"

# 测试执行
async def main():
    await request("user_123")
    await asyncio.sleep(3)

if __name__ == "__main__":
    asyncio.run(main())
关键说明
  • context.create_empty_context():生成完全空的上下文,确保后台任务的Span没有父级,成为独立的顶级Span。
  • 避免模块级提前获取上下文:模块加载时的上下文并非真正的“无父”环境,可能携带进程初始化时的其他上下文数据,导致Span仍存在隐含关联。
  • 显式传入空上下文:asyncio.create_task默认会继承当前请求的上下文,因此必须在后台任务内部启动Span时,显式指定空上下文来切断关联。

内容的提问来源于stack exchange,提问作者chaos.ct

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:30:13