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

FastAPI集成OpenTelemetry如何获取Jaeger可识别Trace ID写入响应头

问题根因

你现有代码拿不到Jaeger可检索的Trace ID,是两个错误导致的:

  • 格式不匹配:span.get_span_context().trace_id 返回的是128位整数类型的ID,直接转字符串得到的是十进制数字串,而Jaeger UI检索使用的是32位小写十六进制格式的Trace ID,也就是你看到的类似8eddc793de380fa76c54557af09538e3的格式。
  • 取错了上下文对象:你手动创建了一个名为dummy-span的临时Span,这个Span在实际请求处理(call_next)执行前就已经退出上下文结束了,拿到的是这个孤立临时Span的Trace ID,和当前请求实际生成、上报到Jaeger的链路Trace ID完全无关,自然搜不到结果。
正确实现方法

不要手动创建无意义的临时Span,直接从OpenTelemetry的当前活跃上下文中获取请求绑定的根Span,再将Trace ID转换为Jaeger兼容的十六进制格式即可。
首先确保你已经正确完成OpenTelemetry FastAPI的埋点初始化,然后使用如下中间件实现:

from starlette.middleware.base import BaseHTTPMiddleware
from fastapi import Request
from opentelemetry import trace

class EnrichOpenTelemetryId(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        # 先执行后续请求处理逻辑
        response = await call_next(request)
        # 获取当前请求链路绑定的活跃Span
        current_span = trace.get_current_span()
        # 将整数格式的Trace ID转换为32位小写十六进制格式,自动补前导零
        trace_id = format(current_span.get_span_context().trace_id, "032x")
        # 写入响应头
        response.headers["X-Trace-Id"] = trace_id
        return response
配置注意事项
  • 中间件注册顺序必须正确:先注册OpenTelemetry提供的FastAPI instrumentation中间件,再注册上述自定义Trace ID注入中间件。如果顺序颠倒,请求进入自定义中间件时OTel还未创建链路根Span,会拿到全0的无效Trace ID。
  • 上述转换得到的32位十六进制Trace ID完全兼容W3C Trace Context标准,除Jaeger外可直接在Zipkin、Grafana Tempo等所有主流链路追踪后端检索使用。
  • 不要在中间件里手动创建额外Span取ID,既会产生多余的无意义链路节点,也无法保证拿到请求实际使用的Trace ID。

内容的提问来源于stack exchange,提问作者omer bar lev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:48:24