主题
阶段 3:Langfuse 与 OpenTelemetry 的关系
预计学习时间:半天
前置:建议先读../opentelemetry/1_base_concept.md和2_traces.md的前两节
目录
1. 一句话总结
OpenTelemetry 是「通用追踪标准 + 采集工具」;Langfuse 是「专门展示和分析 LLM 追踪数据的平台」。
Langfuse 底层兼容 OpenTelemetry,但 UI 和业务模型是为 LLM 定制的。
2. 生活类比:快递系统
想象你要把包裹从工厂送到客户手里:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 工厂 │ │ 快递标准 │ │ 收货仓库 │
│ (你的应用) │ ──→ │ (OpenTelemetry)│ ──→ │ (Langfuse) │
│ │ │ 统一面单格式 │ │ 专业分拣中心 │
└─────────────┘ └─────────────┘ └─────────────┘- 工厂(你的 LLM 应用):生产包裹(产生追踪数据)
- 快递标准(OpenTelemetry):规定面单格式(Span、trace_id、attributes),任何快递公司都认
- 收货仓库(Langfuse):不只存包裹,还能按「生鲜」「电子产品」专门分拣——对应 LLM 的 token、prompt、evaluation
你也可以不用快递标准,直接送货上门(Langfuse SDK 直写)——对小包裹更方便。
3. 概念映射表
| OpenTelemetry | Langfuse | 说明 |
|---|---|---|
| Trace | Trace | 共享同一个 trace_id |
| Span | Observation | Langfuse 把 OTel Span 包装成 Observation |
| Root Span | Trace 容器 | 第一个 Span 定义整条 Trace |
| Span Attributes | Observation metadata | 通过特定 attribute key 映射 |
| Span (LLM 类型) | Generation | 额外有 model、usage、cost 字段 |
| Resource | 项目/环境信息 | service.name 等 |
| SpanProcessor + Exporter | SDK 上报管道 | 异步批量发送 |
Langfuse 专用 Span Attributes
当走 OTel 通路时,Langfuse 通过特定 attribute 识别语义,例如:
langfuse.trace.name → Trace 名称
langfuse.observation.type → observation 类型(generation/tool/...)
langfuse.user.id → user_id
langfuse.session.id → session_id
gen_ai.request.model → 模型名(OTel 语义约定)
gen_ai.usage.input_tokens → 输入 token生活类比:快递面单上除了通用字段(寄件人、收件人),还有「易碎品」「冷链」等特殊标签——Langfuse 靠这些标签知道这是 LLM 包裹。
4. 数据流架构
路径 A:Langfuse SDK 直写(推荐新手)
你的 Python 代码
│
▼
Langfuse SDK (langfuse.trace / .generation / .span)
│
▼ 异步批量
Langfuse Server (Cloud 或自托管)
│
▼
Langfuse Web UI路径 B:OpenTelemetry 桥接(推荐框架集成)
你的应用 / Agent 框架
│
▼
OpenTelemetry SDK(自动或手动埋点)
│
▼
OTLP Exporter(HTTP/gRPC)
│
▼
Langfuse OTLP Endpoint
│
▼
Langfuse Server → Web UI路径 C:旁路解析(本仓库 Claude Code 方案)
Claude Code 写 jsonl transcript
│
▼
Hook / Watcher 解析
│
▼
Langfuse SDK v2 有状态 API 上报这不是 OTel 标准路径,但胜在零侵入 Claude Code 本体。
5. 两种接入方式
5.1 Langfuse SDK 直写
python
from langfuse import Langfuse
lf = Langfuse()
trace = lf.trace(name="chat", user_id="u1")
gen = trace.generation(
name="gpt-call",
model="gpt-4o",
input="你好",
output="您好!",
)
gen.end()
lf.flush()优点:API 直观,LLM 字段开箱即用
缺点:与 Langfuse 耦合(但数据模型简单)
5.2 OpenTelemetry → Langfuse
python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor
import base64, os
# Langfuse OTLP 端点
LF_HOST = os.environ["LANGFUSE_HOST"]
PK = os.environ["LANGFUSE_PUBLIC_KEY"]
SK = os.environ["LANGFUSE_SECRET_KEY"]
auth = base64.b64encode(f"{PK}:{SK}".encode()).decode()
exporter = OTLPSpanExporter(
endpoint=f"{LF_HOST}/api/public/otel/v1/traces",
headers={"Authorization": f"Basic {auth}"},
)
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("my-app")
with tracer.start_as_current_span("my-operation") as span:
span.set_attribute("langfuse.observation.type", "generation")
span.set_attribute("gen_ai.request.model", "gpt-4o")优点:与框架无关,tRPC-Agent 等框架走这条路
缺点:需要理解 OTel attribute 映射规则
6. 该选哪种方式
| 场景 | 推荐方式 |
|---|---|
| 个人项目 / 学习 Demo | Langfuse SDK 直写 |
| LangChain / LlamaIndex 集成 | 框架自带 Langfuse callback 或 OTel |
| 公司已有 OTel 基础设施 | OTel → Langfuse |
| tRPC-Agent / 自研 Agent 框架 | OTel 桥接(见 6_integration_cases.md) |
| 无法改应用代码(Claude Code) | 旁路 jsonl 解析 |
决策口诀:
- 手搓小应用 → SDK 直写
- 框架已集成 OTel → OTel 桥接
- 改不了源码 → 旁路解析
7. SDK 版本说明
Langfuse Python SDK 有两个时代的 API,初学者容易混淆:
| 版本 | API 风格 | 特点 |
|---|---|---|
v2.x (langfuse>=2,<3) | 有状态:trace() → generation() → end() | 直观,本仓库 Claude Code 方案使用 |
| v3/v4 | 基于 OpenTelemetry | 原生 OTel Span,observation type 更丰富 |
本学习笔记 示例以 v2 为主(更易上手)。若你用最新 SDK,语法会偏向 observe() 装饰器和 OTel context,但概念层完全一致。
8. 常见问题 QA
Q1: 学了 OpenTelemetry 还要学 Langfuse 吗?
要。OTel 教你「怎么采集」;Langfuse 教你「LLM 场景下怎么看、怎么评、怎么管 Prompt」。互补关系。
Q2: 数据能同时发到 Jaeger 和 Langfuse 吗?
可以。OTel Collector 配置多个 exporter 即可:
App → OTel SDK → Collector → Jaeger
→ LangfuseQ3: Langfuse 兼容哪些 OTel 版本?
Langfuse Server 提供 OTLP HTTP 接收端点(/api/public/otel/v1/traces),兼容标准 OTLP 格式。
Q4: 为什么 tRPC-Agent 不直接用 Langfuse SDK?
框架层面统一用 OTel 埋点,换后端(Jaeger / Langfuse / 其他)只需换 Exporter,符合「厂商中立」原则。
9. 学习检查
- [ ] 能用「快递系统」类比解释 OTel 和 Langfuse 的分工
- [ ] 能说出 OTel Span 对应 Langfuse 的什么概念
- [ ] 知道 SDK 直写和 OTel 桥接各自的适用场景
- [ ] 理解本仓库 Claude Code 方案是第三种「旁路」路径
下一章 → 4_sdk_quickstart.md