Skip to content

阶段 3:Langfuse 与 OpenTelemetry 的关系

预计学习时间:半天
前置:建议先读 ../opentelemetry/1_base_concept.md2_traces.md 的前两节


目录

  1. 一句话总结
  2. 生活类比:快递系统
  3. 概念映射表
  4. 数据流架构
  5. 两种接入方式
  6. 该选哪种方式
  7. SDK 版本说明
  8. 常见问题 QA
  9. 学习检查

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. 概念映射表

OpenTelemetryLangfuse说明
TraceTrace共享同一个 trace_id
SpanObservationLangfuse 把 OTel Span 包装成 Observation
Root SpanTrace 容器第一个 Span 定义整条 Trace
Span AttributesObservation metadata通过特定 attribute key 映射
Span (LLM 类型)Generation额外有 model、usage、cost 字段
Resource项目/环境信息service.name 等
SpanProcessor + ExporterSDK 上报管道异步批量发送

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. 数据流架构

Langfuse 与 OpenTelemetry 关系

路径 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. 该选哪种方式

场景推荐方式
个人项目 / 学习 DemoLangfuse 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
                           → Langfuse

Q3: 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