跳转至

LiteLLM 全链路追踪(Trace ID / Session ID)文档

本系列文档完整描述 LiteLLM 代理服务中 trace_id 的流动路径:从 HTTP 请求到达、Header / Body 解析,到 access log、应用 JSON 日志、PostgreSQL SpendLogs.session_id、S3 完整日志正文、UI Logs 页搜索的全部出口与一一对应关系。

适用场景:

  • 接入方(公司内部 mirror / model-adapter 服务):透传 X-Trace-Id 后能在哪里看到自己的请求。
  • 运维:拿到一个 trace_id 后该去哪几个地方查(pgsql、UI、S3、ELK)。
  • 排查 bug:当 access log 有 trace_id 但 SpendLogs.session_id 是 UUID 时如何定位。

文档目录

文件 内容
01-input-channels.md trace_id 的 4 种输入入口(x-litellm-trace-id / x-trace-id / body litellm_trace_id / 自动 UUID)及其优先级、代码位置
02-output-destinations.md trace_id 的 6 个出口:响应头、access log、应用 JSON 日志、SpendLogs.session_id、S3 日志正文、UI Logs 页
03-ui-session-search.md UI Logs 页 Session ID 过滤搜索(前缀匹配)、抽屉 session 模式与"顶部搜索框只搜当前页"的坑
04-debugging.md end-to-end 验证脚本 scripts/trace-id/test_trace_id_behavior.py、SQL 速查、常见故障定位 checklist

整体链路一览

flowchart TD
    subgraph 上游
        U1[mirror / model-adapter] -->|"X-Trace-Id: T123"| HTTP
    end

    HTTP[HTTP 请求到达 LiteLLM]

    subgraph 链路A["链路 A:access log 通道(应用日志层)"]
        HTTP --> A1[AccessLogMiddleware<br/>middleware/access_log_middleware.py:50]
        A1 -->|"x-litellm-trace-id 或<br/>x-trace-id 或<br/>uuid()"| A2[set_request_trace_id<br/>request_context.py ContextVar]
        A2 --> A3[litellm/_logging.py:166<br/>注入到 JSON 日志]
        A3 --> A4[(应用 JSON 日志<br/>stdout / litellm.log)]
        A1 --> A5[(access log 文件<br/>access.log)]
        A1 -->|"响应头回写"| RESP1[x-litellm-trace-id<br/>x-trace-id]
    end

    subgraph 链路B["链路 B:SpendLogs 通道(计费层)"]
        HTTP --> B1[litellm_pre_call_utils.py:572<br/>同样读两个 header]
        B1 -->|"data['litellm_trace_id'] = T123"| B2[Logging.litellm_trace_id<br/>litellm_logging.py:349]
        B2 --> B3[StandardLoggingPayload.trace_id]
        B3 --> B4[_get_session_id_for_spend_log<br/>spend_tracking_utils.py:499]
        B4 --> B5[("SpendLogs.session_id<br/>(pgsql)")]
        B3 --> B6[("S3 日志正文<br/>trace_id 字段")]
        B5 --> B7[UI Logs 页<br/>Session ID 列 / 过滤]
    end

    style 链路A fill:#e8f4ff,stroke:#5b9bd5
    style 链路B fill:#fff4e8,stroke:#ed7d31

关键认知:链路 A 与链路 B 是两条独立的传播通道。

历史上踩过的坑:早期版本 litellm_pre_call_utils.py 只把 header 写进 metadata_from_headers["trace_id"]没有data["litellm_trace_id"],导致链路 A 一切正常(响应头有 trace_id、access log 有 trace_id),但链路 B 拿不到,SpendLogs.session_id 永远是随机 UUID。详见 04-debugging.md


速查表:拿到 trace_id 之后去哪查

出口 位置 命令 / 操作
响应头 HTTP response curl -i ... \| grep -i trace-id
access log 容器/Pod 文件 access.log grep T123 /var/log/litellm/access.log
应用 JSON 日志 stdout / litellm.log ELK 按 trace_id: "T123" 检索
SpendLogs(精确) PostgreSQL SELECT * FROM "LiteLLM_SpendLogs" WHERE session_id = 'T123'
SpendLogs(前缀) UI Logs 页 Filter → Session ID → 输入前缀
S3 日志正文 S3 兼容存储 s3_path_components 配置定位文件,正文 JSON 含 trace_id 字段

速查表:trace_id 输入优先级

litellm_pre_call_utils.py 的实际查找顺序(决定 SpendLogs.session_id):

  1. HTTP header x-litellm-trace-id(LiteLLM 原生)
  2. HTTP header x-trace-id(公司内部 mirror / Confluence 规范)
  3. 请求 body 字段 litellm_trace_id
  4. 自动 UUID(最终兜底)

如果业务方既要满足公司规范又要带备选,统一推荐发 X-Trace-Id——这是公司 Confluence 文档约定的 header 名。

⚠️ 链路 A(access log)的优先级与链路 B 相同,且代码各自独立读取 header;但请避免一个请求里 x-litellm-trace-idx-trace-id 传不同的值,否则两条链路会各取所长。


想做某件事?快速入口

你想做的事 看哪篇
接入方调用前要怎么发 header 01-input-channels.md
运维拿到 trace_id 想全链路查询 02-output-destinations.md
在 UI 上根据 Session ID 过滤日志 03-ui-session-search.md
接入完成后想验证全链路通了 04-debugging.md
修改了 trace_id 相关代码想本地回归 04-debugging.md