这类问题我又碰上了一次。Python 服务接 opentelemetry-sdk 1.27,Jaeger 里每个问答请求只有一条 8 秒的根 span,LLM 调用、检索、重排的子 span 一条都看不到,日志却证明这些函数确实跑过。

第一反应是「采样器是 ParentBased,父 span 没被采样时子 span 一起丢」,验证下来不成立。

真正麻烦的地方在于,几个原因的现象几乎一样。子 span 在异步任务里创建,上下文没有跨 await 传递;只装了 HTTP 的自动埋点,httpx 客户端没有插桩;导出的批处理队列满了之后静默丢弃,没有告警。

先打印当前 span 上下文看父级是否为空

python -c "from opentelemetry import trace;print(trace.get_current_span().get_span_context())"

补上 httpx 自动埋点后重启

pip install opentelemetry-instrumentation-httpx

调大导出队列并打开丢弃日志

python -c "print('OTEL_BSP_MAX_QUEUE_SIZE=2048')"

手工建一个子 span 验证能否导出

python -c "from opentelemetry import trace;t=trace.get_tracer('demo');print(t.start_span('child'))"

改完先别撤,确认这几项。Jaeger 里一次请求能看到三层以上 span,子 span 时长之和与父 span 接近,exporter 丢弃计数为 0。

提醒一点。上下文在异步边界最容易断,子 span 变孤儿时先看 parent_span_id 是不是空的,再谈采样配置。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189