从 request_id 到可视化 trace:Langfuse 全链路追踪实战(O02)

0 阅读4分钟

从 request_id 到可视化 trace:Langfuse 全链路追踪实战(O02)

系列《AI 应用生产化手册》第 7 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/…

一、先看问题:看日志 = 脑内拼图

O01 有了结构化日志,但马上撞到天花板:

  1. 看日志 = 脑内拼图——request_id 能串起链路,但你要在终端翻几十行 key=value 才拼出"这次请求经历了什么"。
  2. 一次问答不是一次调用——RAG 是"检索→重排→生成",Agent 是十几轮工具调用,文本日志没法展示这种结构。
  3. "看看这个 trace 长什么样"——没有可视化,无法快速回答"哪一步最慢、模型看到了什么、哪一步失败"。

解法:上追踪平台——把 request_id 升级为可视化 trace,一次请求变成一棵 span 树。

核心认知:日志是"细节",追踪是"结构",指标是"聚合"——三者分工不同。追踪回答的是"这一次请求内部到底发生了什么",是排查线上问题最快的入口。

二、原理

OpenTelemetry 四个核心概念(30 秒版)

概念是什么类比
Trace一次完整请求的全链路一次"旅程"
SpanTrace 里的一个环节(名字/耗时/属性)旅程中的一站
Parent/ChildSpan 的父子关系站与站之间的嵌套
Context Propagation把 trace 上下文传给下游旅行中的"接力棒"

平台选型

平台优势短板
LangfuseLLM 专项(generation 记录 prompt/tokens)、自带提示词管理与评测面板、OpenAI SDK 包装器一行接入自托管要 postgres
PhoenixOpenTelemetry 原生、可做在线评测LLM 专项功能少
自建(OTel Collector + Grafana)可控性最强成本高、维护重,学习阶段不建议

选型结论:用 Langfuse——可观测、看板、提示词管理一个平台管三件事。

一次问答的 span 树

POST /api/chat                          ← root span(路由)
├── chat_request                        ← 请求入口(O01 日志同步打)
└── llm_call (generation)               ← Langfuse 自动记录
    ├── input = 问题全文
    ├── output = 答案全文
    ├── model = deepseek-chat
    └── usage: in_tokens=69 out_tokens=85
(RAG 接入后)├── retriever.search  └── reranker.rerank
(Agent 接入后)└── agent.loop ├── tool.call(...) └── llm_call(第二轮)

每多一层能力,span 树就多一层——所以"先搭追踪再上复杂功能"是正确顺序。

追踪 vs 日志 vs 指标

粒度回答的问题
追踪一次请求"这次请求内部发生了什么、哪一步慢/错"
日志一条事件"某个时刻的细节文本是什么"
指标聚合"整体表现如何、有没有退化"

排查路径:指标发现异常 → 追踪定位请求 → 日志看细节。

三、动手:本地起 Langfuse 并接入追踪

git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
cp .env.example .env && docker compose up -d postgres langfuse litellm

# 1. 验证 Langfuse 健康
curl http://localhost:3000/api/public/health

# 2. 一键验证"可观测链路打通"(脚本会写入一条 trace 并查回)
LANGFUSE_PUBLIC_KEY=pk-local-demo LANGFUSE_SECRET_KEY=sk-local-demo \
  LANGFUSE_HOST=http://localhost:3000 python scripts/check_langfuse.py
# [1/3] health: 200 {"status":"OK","version":"2.95.11"}
# [2/3] POST trace: 200
# [3/3] 查询最近 trace: 命中 check_langfuse ✓

# 3. 启动应用,发一次请求
uvicorn app.main:app --port 8000
curl -X POST http://localhost:8000/api/chat -H "Content-Type: application/json" \
  -d '{"question":"什么是 RAG?"}'
# 打开 http://localhost:3000 看 trace(项目 default-project,Key 已预置)

优雅降级验证(生产纪律)

# 不配置 LANGFUSE_SECRET_KEY 时,应用照常运行(追踪自动关闭)
LANGFUSE_SECRET_KEY= uvicorn app.main:app --port 8001
curl http://localhost:8001/health   # 正常返回,不报错

可观测是增强不是依赖——追踪平台挂了不能拖垮业务。

四、真实踩坑(都踩过)

  1. (实测)Langfuse 起不来:必须配 NEXTAUTH_SECRET 和 SALT,否则容器反复重启
  2. (实测)postgres 竞态:Langfuse 比 postgres 先就绪 → Prisma 报 P1001: Can't reach database server 直接退出——postgres 起来后重启一次 langfuse 即可(生产用 healthcheck + depends_on)
  3. (实测)SDK API 变了:langfuse 4.x 移除了 start_trace,改用装饰器/上下文模型——验证脚本改用 Public API 直写 trace,不依赖 SDK 版本
  4. (实测)健康端点格式想当然:/health/liveliness 返回纯文本 "I'm alive!" 不是 JSON;/spend/logs 有的版本直接返回 list——脚本要兼容
  5. public key 和 secret key 混淆:SDK 接入用 secret key(服务端写入用),public key 是展示用
  6. host 没配:SDK 默认连云端 cloud.langfuse.com,自托管必须设 LANGFUSE_HOST
  7. 隐私:trace 记录 prompt/输出全文——生产要对输入做脱敏/截断(学习阶段全量记录)

五、小结

  • OTel 四概念:Trace / Span / 父子 / 上下文传播
  • 三层分工:指标发现异常 → 追踪定位请求 → 日志看细节
  • 优雅降级:追踪平台挂了,业务照常——这是生产纪律

明天(O03):《质量与成本监控》——用指标 + 看板把"整体表现"可视化(含真实的 P95 vs 平均数对比)。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。