使用OpenTelemetry时如何基于现有trace id显式创建子Span?
OpenTelemetry基于自定义traceid关联链路实现指引
OpenTelemetry提供了和OpenTracing extract能力完全对应的实现,归属于上下文传播(Context Propagation) 模块,你可以通过两种方案实现需求:
方案1:从请求体自定义字段提取traceid构造链路(适配你的场景)
你的场景中traceid存放在请求Body的traceid字段,需要手动构造父Span上下文关联链路,Python实现代码如下:
import os from opentelemetry import trace from opentelemetry.trace import SpanContext, TraceFlags from fastapi import Request @app.post("/api/doit") def post_doit(request: Request): get_json = async_to_sync(request.json) data = get_json() # 从请求体获取十六进制格式的traceid trace_id_hex = data['traceid'] trace_id = int(trace_id_hex, 16) # 构造父Span上下文 # 注:如果请求中同时携带父spanid、采样标记,直接替换对应参数即可 parent_span_context = SpanContext( trace_id=trace_id, # 无上游spanid时可随机生成,有则替换为上游传递的spanid转整数结果 span_id=int.from_bytes(os.urandom(8), byteorder="big"), is_remote=True, trace_flags=TraceFlags(0x01) # 0x01表示采样,可根据业务规则调整 ) # 生成绑定了父上下文的OTel上下文 parent_context = trace.set_span_in_context(trace.NonRecordingSpan(parent_span_context)) tracer = trace.get_tracer(__name__) # 启动span时传入父上下文 with tracer.start_as_current_span("/api/doit", context=parent_context): # 该请求会自动作为子Span挂载到对应traceid的链路上 request.post("some-outgoing-call") return {"status": "SUCCESS"}
方案2:标准传播协议直接提取
如果你的trace信息是通过标准协议(如W3C TraceContext、B3)放在HTTP头传递,可以直接用OTel内置的extract方法,无需手动构造上下文:
from opentelemetry.propagate import extract # 直接从HTTP头提取父上下文 parent_context = extract(carrier=request.headers) with tracer.start_as_current_span("/api/doit", context=parent_context): # 后续业务逻辑
补充说明
- OpenTelemetry中对应OpenTracing extract的能力就是
opentelemetry.propagate.extract方法,默认支持多种主流传播协议,也可以自定义Propagator适配任意自定义传播格式。 - 要保证后续的对外请求自动生成子Span,需要先开启对应HTTP客户端的OTel Instrumentation埋点。
内容的提问来源于stack exchange,提问作者Trondh
相关产品推荐
相关产品推荐

