跳转至

02 — trace_id 的输出位置

trace_id 进入 LiteLLM 后会同时往 6 个出口 流,分别由不同模块负责。本篇逐个讲清楚:是什么、在哪、怎么查。


出口一览

# 出口 链路 写入位置 检索方式
HTTP 响应头 A AccessLogMiddleware curl 看响应头
access log 文件 A 自定义 logger grep 容器内 access.log
应用 JSON 日志 A litellm/_logging.py ELK 按字段检索
SpendLogs.session_id B _get_session_id_for_spend_log pgsql SQL 查询
S3 日志正文 trace_id 字段 B s3_v2.py JSON 写入 S3 下载文件 grep
UI Logs 页 Session ID 列 B UI 拉取 SpendLogs Filter → Session ID

链路 A、B 概念见 README.md


① 响应头

字段: x-litellm-trace-idx-trace-id 同时回写(同一个值)。

写入位置: access_log_middleware.py:58-60

response.headers["x-litellm-trace-id"] = trace_id
response.headers["x-trace-id"] = trace_id

查看方式:

curl -i -X POST https://litellm.example.com/v1/chat/completions \
  -H "Authorization: Bearer sk-..." \
  -H "X-Trace-Id: T-VERIFY-001" \
  ... 2>&1 | grep -i trace-id

注意: 响应头来自链路 A,可能与 SpendLogs.session_id(链路 B)不一致,详见 01-input-channels.md


② access log 文件

每条 HTTP 请求结束后写一行 NCSA-like 格式日志。当前实现里 access log 行没有显式打 trace_id 字段——而是依赖应用 JSON 日志承载(出口 ③)。如果需要按 trace_id grep access log,请改成 ELK 走 ③ 的 JSON 字段。

写入位置: access_log_middleware.py:82-91

文件路径与切割策略:docs/operations/logging-files.md


③ 应用 JSON 日志(含 trace_id 字段)

LiteLLM 业务日志(business log)通过自定义 JSON formatter 输出,每条日志会从 ContextVar 取出当前请求的 trace_id 并注入 JSON。

写入位置: litellm/_logging.py:166-168

trace_id = get_request_trace_id()
if trace_id is not None and "trace_id" not in json_record:
    json_record["trace_id"] = trace_id

ContextVar 实现: litellm/proxy/request_context.py,由 AccessLogMiddleware.dispatch 在请求进入时 set、请求结束时 reset

启用条件: 环境变量 JSON_LOGS=true(或 config yaml 里 json_logs: true)。

ELK 检索示例:

trace_id: "SPAN-2026-04-30-abc123"

典型一行日志:

{
  "timestamp": "2026-04-30T10:13:06.123Z",
  "level": "INFO",
  "message": "Request received",
  "trace_id": "SPAN-2026-04-30-abc123",
  "...": "..."
}

LiteLLM_SpendLogs.session_id(pgsql)

每次 LLM 请求结束后会写一行 SpendLogssession_id 列即 trace_id。

写入位置: spend_tracking_utils.py:499-522

def _get_session_id_for_spend_log(kwargs, standard_logging_payload) -> str:
    if standard_logging_payload is not None and standard_logging_payload.get("trace_id") is not None:
        return str(standard_logging_payload.get("trace_id"))
    if kwargs.get("litellm_trace_id") is not None:
        return str(kwargs.get("litellm_trace_id"))
    return str(uuid.uuid4())

SQL 速查(精确匹配):

SELECT request_id, session_id, model, "startTime", spend
FROM "LiteLLM_SpendLogs"
WHERE session_id = 'SPAN-2026-04-30-abc123'
ORDER BY "startTime" DESC;

SQL 速查(前缀匹配,与 UI 行为一致):

SELECT request_id, session_id, model, "startTime", spend
FROM "LiteLLM_SpendLogs"
WHERE session_id LIKE 'SPAN-2026-04-30-%'
ORDER BY "startTime" DESC;

关联其他列:

  • metadata->>'trace_id':链路 B 也会把同一 trace_id 写入 metadata JSON(来自 metadata_from_headers["trace_id"],但实际持久化路径取决于 metadata 合并逻辑,不保证总是有,建议直接以 session_id 列为准)。
  • request_id:单次请求 ID,与 trace_id 是 N:1 关系(一个 trace 可能含多条 request)。

⑤ S3 日志正文 trace_id 字段

如果启用了 S3 日志(s3_v2 callback),每条请求会向 S3 写一份完整 JSON(含 messages、response、cache 信息等)。文件正文里 trace_id 字段即同一个 trace_id。

写入字段: StandardLoggingPayload.trace_id(与 SpendLogs.session_id 同源)。

S3 路径构造:s3_path_components 配置决定,详见 docs/billing-and-pricing/06-s3-cost-map.md 与同名集成代码 litellm/integrations/s3_v2.py

典型用法:

  1. 从 UI Logs 页或 pgsql 拿到 request_id
  2. s3_path_components 模板拼出 S3 key(含 request_id
  3. 下载 JSON 文件
  4. grep '"trace_id"' xxx.json 或直接 jq 取值

待办:把 s3_object_key 写回 SpendLogs.metadata,UI 上一键复制 S3 路径,目前未实现。


⑥ UI Logs 页 Session ID 列

LiteLLM Dashboard /ui/logs 页面的"Session ID"列即 SpendLogs.session_id

两种用法:

  • 行内点击:单元格可点击,触发抽屉的 session 模式(拉取 /spend/logs/session/ui?session_id=精确值,把同一 session 的所有 request 行平铺到右侧抽屉)。
  • 过滤检索:高级 Filter → Session ID 输入框,走 /spend/logs/ui?session_id=前缀 LIKE 匹配。

详见 03-ui-session-search.md


出口对照:上游 → 下游链路

flowchart LR
    IN[trace_id 进入] --> A[ContextVar]
    IN --> B["data['litellm_trace_id']"]

    A --> O1[① 响应头]
    A --> O3[③ 应用 JSON 日志]
    %% access log 当前不打 trace_id 字段,省略边

    B --> S[StandardLoggingPayload.trace_id]
    S --> O4[④ SpendLogs.session_id]
    S --> O5[⑤ S3 日志正文 trace_id]
    O4 --> O6[⑥ UI Logs Session ID]

只读这一张图:

  • ContextVar(链路 A)→ 响应头 + 应用 JSON 日志
  • data["litellm_trace_id"](链路 B)→ SpendLogs / S3 / UI

显式传 header 时两条链路同步;不传时两条链路各跑各的 UUID。