OpenTelemetry 入门:面向 AI 应用与 AI Agent 开发者的通俗指南

写在前面

刚开始开发 AI 应用时,你往往只关心“模型能不能回答”。系统进入真实环境后,问题会迅速变成:

  • 这次请求为什么失败?
  • 是检索、模型、工具还是数据库出了问题?
  • Agent 为什么重复调用工具?
  • 哪一步最慢、最贵?
  • 一次用户任务跨越 API、队列和 Worker 后,怎样把整个过程串起来?

OpenTelemetry 就是为这类问题提供统一观测基础设施的开放标准与工具体系。


1. 一句话理解 OpenTelemetry

OpenTelemetry(简称 OTel)是一套用于产生、关联、处理和导出遥测数据的开放标准与工具链。

这里的“遥测数据(Telemetry)”就是程序运行时产生、用于理解系统状态的数据。OpenTelemetry 当前成熟度较高的核心信号是 Trace、Metric 和 Log;Baggage 用于跨服务传播上下文信息;Profile 则仍处于 Alpha 阶段:

  • Trace:一次请求完整经历了什么;
  • Metric:一段时间内系统整体表现如何;
  • Log:某个时刻具体发生了什么事件;
  • Baggage:哪些上下文信息需要随调用链传播;
  • Profile:程序的 CPU、内存等资源具体消耗在哪里,目前仍在发展中。

OpenTelemetry 本身通常不负责长期存储、查询和展示数据。它更像一套统一的“采集规范、SDK 和运输系统”;Langfuse、LangSmith、Phoenix、Grafana Tempo、Prometheus、Loki、Datadog 等才是最终接收、存储、分析或展示数据的后端平台。


2. 用“快递系统”理解 OpenTelemetry

把一次 AI Agent 请求产生的观测数据想象成包裹:

OpenTelemetry 概念快递系统类比实际作用
Instrumentation(插桩)给商品打包并贴单在程序中加入采集逻辑
Trace / Metric / Log不同类型的包裹不同类型的遥测信号
API标准寄件接口规定业务代码如何创建遥测数据
SDK快递公司的实际执行系统采样、处理、聚合并导出数据
Exporter发货车辆把数据发送出去
OTLP运输协议规定遥测数据如何编码和传输
Collector分拣中心接收、脱敏、过滤、采样、批处理和转发
Backend仓库与控制台存储、查询、可视化和分析
Trace Context快递追踪号码跨服务维持同一条调用链
Resource寄件人信息标识数据由哪个服务、版本和环境产生
Semantic Conventions统一字段字典统一属性和操作的命名方式

最重要的认知是:

OpenTelemetry 不是一个监控网页,也不是 Langfuse 的同类产品。它是连接应用和各种可观测后端的标准化中间层。


3. OpenTelemetry 在 AI Agent 架构中的位置

一个常见架构如下:

用户请求
FastAPI / Web 服务
AI Agent / RAG Pipeline
├── 查询改写
├── Retriever
├── Reranker
├── LLM
├── Tool Call
└── 数据库 / 外部 API

应用内部:
├── 自动插桩:HTTP、FastAPI、数据库、Redis 等
├── 手动插桩:Agent、RAG、LLM、Tool 等业务步骤
├── Metrics:请求量、延迟、错误率、Token 等
└── Structured Logs:结构化日志
          ↓ OTLP
OpenTelemetry Collector
├── 脱敏
├── 过滤
├── 采样
├── 批处理与重试
└── 多后端分发
       ├── Langfuse / LangSmith / Phoenix:AI Trace 与评估
       ├── Tempo / Datadog:通用分布式追踪
       ├── Prometheus / Grafana:指标与告警
       └── Loki / 日志平台:日志查询

可以把它拆成两个平面:

  1. 插桩平面(Instrumentation Plane):位于应用内部,负责产生数据。
  2. 管道平面(Pipeline Plane):通常由 Collector 承担,负责搬运和处理数据。

4. 最容易混淆的核心组件

4.1 Specification:规范

规范是 OpenTelemetry 的“规则书”,定义 Trace、Metric、Log、Context、OTLP 等概念应当如何工作。它不是代码,而是各语言 SDK 和工具实现时应遵守的共同标准。

4.2 API:业务代码使用的接口

API 定义“怎样创建遥测数据”。例如:

tracer.start_as_current_span("rag.retrieve")

API 尽量稳定、轻量。一个库可以只依赖 API,而不决定数据最终发到哪里。

4.3 SDK:真正执行采集和导出的实现

SDK 负责把 API 产生的数据真正处理起来,包括:

  • 创建 Provider;
  • 采样;
  • 聚合 Metric;
  • 批处理;
  • 调用 Exporter;
  • 配置 Resource;
  • 控制数据是否以及怎样导出。

可以理解为:

API:你用什么方法描述“我要记录数据”
SDK:这些数据如何被真正处理和发送

4.4 Instrumentation 与 Instrument 不是一回事

这是最容易混淆的一对术语。

Instrumentation(插桩):给代码加入观测能力的整个过程。

with tracer.start_as_current_span("tool.weather"):
    result = call_weather_tool()

Instrument(指标工具):专属于 Metrics 的对象,例如 Counter、Histogram、ObservableGauge。

request_counter = meter.create_counter("agent.requests")

所以:

Instrumentation = 给程序加入观测逻辑
Instrument = 用于记录某类 Metric 的工具对象

4.5 Provider、Tracer 和 Meter

TracerProvider 是 Tracer 的总入口与配置中心;Tracer 用于创建 Span。

TracerProvider → Tracer → Span

MeterProvider 是 Meter 的总入口与配置中心;Meter 用于创建 Metric Instrument。

MeterProvider → Meter → Counter / Histogram / Gauge

Provider 通常在应用启动时初始化一次,而不是每个请求重新创建。

4.6 Exporter

Exporter 负责把遥测数据发送到外部,例如:

OTLP Exporter → Collector
Console Exporter → 终端
Prometheus Exporter → Prometheus 兼容端点

Exporter 是应用或 Collector 内部的“输出适配器”,不是存储系统。

4.7 OTLP

OTLP 是 OpenTelemetry Protocol,负责规定 Trace、Metric、Log 等数据怎样在应用、Collector 和后端之间传输。

应用 --OTLP--> Collector --OTLP/其他协议--> 后端

OTLP 是协议,不是服务,也不是数据库。

4.8 Collector

OpenTelemetry Collector 是一个独立运行的遥测数据服务。它的典型流水线是:

Receiver → Processor → Exporter
  • Receiver:接收数据;
  • Processor:批处理、过滤、采样、脱敏、补标签;
  • Exporter:把数据发送给一个或多个后端。

Collector 还可以使用 Connector 连接不同管道,使用 Extension 提供健康检查、认证等辅助能力。

4.9 Backend

Backend 是最终保存、查询、展示或分析数据的平台。例如:

  • Langfuse:AI/LLM/Agent Trace、成本、评估与数据集;
  • LangSmith:Agent Tracing 与 Evaluation;
  • Phoenix:AI Observability 与 Evaluation;
  • Tempo:Trace 存储和查询;
  • Prometheus:Metric 存储和查询;
  • Loki:日志存储和查询。

OpenTelemetry 与这些平台的关系通常是:

OpenTelemetry 负责生成和运输
Backend 负责存储和使用

5. OpenTelemetry 的主要观测信号

5.1 Trace:一次请求的完整执行路径

Trace 用于回答:

“这一次具体请求,按什么顺序经过了哪些步骤?”

一次 AI Agent 任务可以表示为:

Trace: agent.run
├── Span: auth.check
├── Span: session.load
├── Span: rag.retrieve
│   ├── Span: embedding.create
│   └── Span: vector_db.search
├── Span: reranker.rank
├── Span: llm.plan
├── Span: tool.weather
├── Span: llm.answer
└── Span: result.persist

Span

Span 是 Trace 中的一个工作单元,例如一次数据库查询、模型调用或工具执行。

一个 Span 通常包含:

  • name:步骤名称;
  • start/end time:开始和结束时间;
  • parent:父 Span;
  • attributes:结构化属性;
  • events:步骤内部的重要时间点;
  • status:成功或错误状态;
  • links:与其他 Trace/Span 的关联;
  • trace_id / span_id:调用链身份。

Attribute

Attribute 是附加在 Span 上的键值信息:

gen_ai.agent.name = "support-agent"
gen_ai.request.model = "example-model"
gen_ai.tool.name = "search_orders"
app.tool.success = true

前三个字段来自当前仍在演进的 GenAI 语义约定;app.tool.success 是本文为了说明业务字段而使用的自定义属性。生产项目应为自定义字段使用稳定、明确的命名空间,不要让它们看起来像 OpenTelemetry 官方字段。

Span Event

Event 是 Span 生命周期内某个重要瞬间,例如:

retry_started
rate_limit_received
fallback_model_selected

父子关系表达一次执行链中的直接延续。对于队列和异步任务,如果生产者 Context 能被消费者提取,消费者 Span 仍可延续同一条 Trace;当一个任务由多个上游共同触发、批处理合并多条消息,或不适合建立单一父子关系时,再使用 Link 表达因果关联。

Trace 适合什么场景

  • 定位一次失败请求;
  • 分析 Agent 循环;
  • 查看工具选择和参数;
  • 查看 RAG 检索与精排链路;
  • 分析哪一步最慢;
  • 串联 API、Worker、数据库和外部服务。

5.2 Metrics:大量请求聚合后的数值趋势

Metric 用于回答:

“系统最近整体表现怎么样?”

例如:

每分钟请求数
任务成功率
错误率
P95 延迟
LLM Token 总量
每次成功任务成本
当前队列长度
工具调用失败次数

Metric 的核心对象关系:

MeterProvider
Meter
Instrument
Measurement
聚合后的 Metric

Measurement

Measurement 是一次具体测量值。例如:

request_counter.add(1)
latency_histogram.record(850)

这里的 1850 都是 Measurement。

常见 Instrument

Instrument特点AI 应用示例
Counter只能累计增加请求总数、错误总数、Token 总数
UpDownCounter可以增加或减少当前正在运行的 Agent 数量
Histogram记录数值分布延迟、Token 数、文档大小
ObservableGauge定期读取当前值队列长度、当前内存、活跃任务数

Observation

Observation 是异步 Instrument 回调返回的一次观测值。它和 Python 的 async/await 不是一回事。

例如,OpenTelemetry 定期调用回调获取当前队列长度:

def observe_queue_size(options):
    yield Observation(queue.qsize(), {"queue": "rag-ingestion"})

Metric 适合什么场景

  • Dashboard;
  • 趋势分析;
  • SLO 和告警;
  • 容量规划;
  • 版本前后对比;
  • 成本与吞吐监控。

Cardinality:必须理解的 Metric 风险

Cardinality 指标签值组合的数量。

不要把这些字段直接放进 Metric Attribute(在 Prometheus 等后端中通常表现为 Label):

user_id
session_id
trace_id
完整 URL
原始 Prompt
订单号

因为每个值几乎都不同,会产生海量时间序列,导致存储和查询成本失控。高基数字段适合放进 Trace 或 Log,而不是 Metric 标签。


5.3 Logs:某个时刻发生的具体事件

Log 是带时间戳的事件记录。推荐使用结构化日志:

{
  "timestamp": "2026-07-16T12:00:00Z",
  "level": "ERROR",
  "event": "tool_call_failed",
  "tool_name": "search_orders",
  "error_type": "timeout",
  "trace_id": "...",
  "span_id": "..."
}

结构化日志的重点不是“看起来像 JSON”,而是字段命名和类型长期一致,便于机器查询。

Log 适合记录:

  • 异常堆栈;
  • 工具返回的错误详情;
  • 业务审计事件;
  • 状态变化;
  • Collector 或 Worker 的运行信息。

Trace 与 Log 最好通过 trace_idspan_id 关联:先从 Metric 发现异常,再打开 Trace 定位步骤,最后查看对应 Log 的详细错误。


5.4 Profiles:代码具体把 CPU 和内存耗在哪里

Profile 用于回答:

“程序运行时,CPU 时间、内存分配或调用栈主要消耗在哪里?”

它更偏性能工程,而且 OpenTelemetry Profiles 规范目前仍为 Alpha,不是 AI Agent 第一阶段的优先项。对于刚入门的项目,先把 Trace、Metrics 和 Logs 做好即可。


6. 四类信号怎样协作

最实用的理解是:

Metrics:发现系统整体有问题
Trace:定位某一次请求哪一步有问题
Logs:查看该步骤具体错误细节
Profiles:进一步分析代码级性能瓶颈

例如:

Metrics:P95 从 3 秒升到 12 秒
Trace:慢请求都卡在 reranker.rank
Logs:Reranker API 多次触发超时重试
Profile:本地预处理还存在 CPU 热点

它们不是互相替代,而是观察同一系统的不同角度。


7. Context Propagation:怎样把跨服务调用串成一条 Trace

AI 系统经常跨越:

FastAPI → Queue → Worker → LLM → Tool Service → Database

如果每个服务都各自创建 Trace,你只能看到很多不相关的片段。

Context Propagation 会把 trace_id 和当前 span_id 跨进程传播。HTTP 通常使用 W3C Trace Context,例如 traceparent Header;消息队列则需要把 Context 写入消息属性,再由消费者恢复。

Service A 创建 Trace
   ↓ 注入 traceparent
Service B 提取 Context
   ↓ 创建子 Span
Service C 继续传播

trace_id、session_id 和 request_id 的区别

trace_id:一次具体执行链
session_id:一段多轮对话
request_id:应用自己定义的一次 API 请求 ID

一个 Session 可以包含多条 Trace;不要用 session_id 代替 trace_id


8. Resource、Semantic Conventions 与 Baggage

Resource

Resource 描述“谁产生了这批遥测数据”:

service.name = "rag-api"
service.version = "1.4.2"
deployment.environment.name = "production"
cloud.region = "asia-northeast1"

Resource 通常在应用启动时设置,并随该 Provider 产生的遥测数据导出。具体支持哪些信号取决于所使用语言的 SDK 和信号实现。

Semantic Conventions

Semantic Conventions 是统一字段命名规则。例如各团队都按照相同约定记录 HTTP、数据库、消息队列和 GenAI 属性,后端才能统一查询和展示。

可以理解为:

语义约定不是数据运输协议,而是遥测字段的“共同词典”。

OpenTelemetry 正在为 GenAI 客户端、Agent、MCP 和部分模型提供商建设专用语义约定。截至本文发布时,这些约定已迁移到独立的 GenAI 语义约定仓库,整体仍处于 Development 状态,字段和 Span 结构可能继续变化;实现时应固定所采用的语义约定版本。

Baggage

Baggage 是会随 Context 跨服务传播的业务键值信息,例如:

tenant.tier = "enterprise"
experiment.group = "prompt-v2"

它不会自动变成 Span Attribute,需要显式读取和使用。

不要把 API Key、个人信息、完整 Prompt 等敏感数据放进 Baggage,因为它可能传播到下游甚至第三方服务。


9. OpenTelemetry 在 AI 与 Agent 系统中的特殊价值

传统 Web 请求通常是比较固定的:

HTTP → Service → Database → Response

Agent 执行路径更动态:

用户问题
→ 模型规划
→ 检索
→ 工具 A
→ 模型再次判断
→ 工具 B
→ 重试或回退
→ 最终回答

因此 AI 可观测性需要同时记录:

  • 模型与提供商;
  • Prompt 或 Prompt 版本;
  • 输入、输出和缓存 Token;
  • 模型延迟和结束原因;
  • Agent 节点与状态转换;
  • Tool 名称、参数 Schema 和执行结果;
  • Retriever、Reranker、Top K 与文档 ID;
  • Guardrail;
  • 重试、Fallback 和 Handoff;
  • 成本与业务任务结果。

OpenTelemetry 负责把这些步骤放进统一的 Trace 体系,并与 HTTP、数据库、队列等传统基础设施调用串起来。

GenAI Semantic Conventions

OpenTelemetry 的 GenAI 语义约定定义 AI 客户端、Agent、MCP、模型调用等应怎样命名 Span、Metric 和 Event。它让不同框架产生的数据更容易被统一后端理解,但目前仍处于 Development 状态,不应被当成已经完全稳定的长期契约。

OpenInference

OpenInference 是建立在 OpenTelemetry 思路之上的 AI 专用约定与插桩插件生态,覆盖 OpenAI、Anthropic、LangChain、LlamaIndex、Google ADK、MCP 等框架。它适合在某些官方 OTel GenAI 插桩尚不方便时快速获得 AI 专用 Trace。

Langfuse、LangSmith 与 Phoenix

这些属于 AI 可观测与评估后端,而不是 OpenTelemetry 的替代品。它们可以直接或间接接收 OpenTelemetry Trace,并提供更适合 LLM/Agent 的界面、成本分析、Dataset、Experiment 和 Evaluation。


10. 可观测性与 Evaluation 不是同一件事

OpenTelemetry 主要回答:

“Agent 做了什么?”

Evaluation 主要回答:

“Agent 做得好不好?”

例如:

OpenTelemetry:
调用了 search_orders
参数是 order_id=123
耗时 800ms
最终未报错

Evaluation:
是否本来就应该调用这个工具
order_id 是否正确
用户的退款任务是否真的完成
回答是否忠实于工具结果

成熟系统通常把两者连接起来:

生产 Trace
→ 规则、用户反馈或 LLM Judge 打分
→ 失败样本加入 Dataset
→ 修改 Prompt / 模型 / Workflow
→ 离线 Experiment
→ CI 回归
→ 灰度发布

Trace 是评估的数据基础,但 Trace 本身不等于质量结论。


11. AI Agent 的推荐 Trace 设计

推荐原则:一次用户任务或一次 Agent Run 对应一条 Trace。

Trace: agent.run
├── request.validate
├── context.load
├── rag.retrieve
│   ├── query.embed
│   ├── dense.search
│   ├── sparse.search
│   ├── rrf.fuse
│   └── reranker.rank
├── llm.plan
├── tool.call
├── guardrail.check
├── llm.answer
└── result.persist

只为具有诊断价值的步骤创建 Span。不要把每个小函数都变成 Span,否则 Trace 会充满噪声并增加成本。

服务身份应优先放在 Resource 中,例如:

service.version
deployment.environment.name

Agent Run 的 Span 再记录与本次执行有关的信息。已有官方约定时使用官方字段;没有官方约定时使用应用自定义命名空间,例如:

gen_ai.agent.name
gen_ai.agent.version
gen_ai.conversation.id
app.release.git_sha
app.prompt.version
app.knowledge_base.version

模型 Span 建议记录:

gen_ai.provider.name
gen_ai.request.model / gen_ai.response.model
gen_ai.usage.input_tokens / gen_ai.usage.output_tokens
gen_ai.response.finish_reasons
error.type
app.retry_count

延迟通常由 Span 自身的起止时间表达;只有确有独立聚合需求时才额外记录 Metric。缓存 Token 等扩展字段是否可用,取决于所采用的语义约定版本和具体插桩实现。

工具 Span 建议记录:

gen_ai.tool.name
gen_ai.tool.type
error.type
app.tool.version
app.tool.success

RAG Span 建议记录:

app.rag.index.name
app.rag.index.version
app.rag.top_k
app.rag.retrieved_document_ids
app.rag.reranker.name
app.rag.result_count

这里的 app.rag.* 是示例性自定义属性,不是 OpenTelemetry 官方 RAG 语义约定。

不要默认记录完整 Prompt、用户文档、Tool 返回原文或隐藏思维链。


12. 推荐的生产架构

开发阶段

Python AI App
├── OpenTelemetry 自动插桩
├── 少量手动 Agent Span
├── JSON stdout Logs
└── OTLP Exporter
Langfuse / Phoenix / LangSmith

适合快速验证,不一定需要 Collector。

准生产与生产阶段

Python AI App
   ↓ OTLP
OpenTelemetry Collector
├── memory_limiter
├── batch
├── redaction / transform
├── sampling
└── exporters(sending queue / retry)
       ├── Langfuse / LangSmith / Phoenix
       ├── Tempo / Datadog
       ├── Prometheus
       └── Logs backend

Collector 带来的关键价值:

  • 应用与厂商后端解耦;
  • 集中脱敏;
  • 集中采样;
  • 批处理和重试;
  • 一份数据发送多个平台;
  • 后端变更时减少业务代码修改。

13. 生产最佳实践

13.1 自动插桩与手动插桩结合

自动插桩覆盖 FastAPI、HTTP 客户端、数据库、Redis 等通用调用;手动插桩补充 Agent 任务、RAG、Tool、Guardrail 和业务结果。

13.2 可观测系统故障不能拖垮业务

使用批处理和异步导出;Collector 在 Exporter 上配置 Sending Queue、退避重试以及按需启用的持久化。遥测后端短暂不可用时,AI 业务应尽量继续运行,同时必须监控队列容量、丢弃量和磁盘占用。

13.3 生产环境不要无条件记录完整输入输出

敏感内容应在应用离开前脱敏,Collector 再做第二层过滤。重点保护:

Authorization / Cookie / API Key
邮箱、电话、身份证件
用户私有文档
数据库返回的敏感字段
完整 Prompt 和模型输出

13.4 不记录隐藏思维链

记录可审计的结构化结果:

selected_tool
route
state_transition
validation_result
policy_decision

不要依赖或保存模型的隐藏 Chain-of-Thought。

13.5 控制 Metric Cardinality

Metric Attribute 只使用低基数字段,例如:

model_family
environment
status
tool_name
error_type

用户 ID、Trace ID、Prompt 等高基数字段放进 Trace 或 Log。

13.6 采样不要只做固定随机抽样

开发环境可以保留 100% Trace;生产环境可以随机保留部分正常请求,并使用 Tail Sampling 优先保留:

错误 Trace
慢 Trace
高成本 Trace
高风险工具操作
异常循环

Head Sampling 在请求开始时决定是否记录,成本低;Tail Sampling 在看到更多完整 Trace 信息后决定,策略更精确,但需要 Collector 保持状态,复杂度更高。用户点踩等请求结束后才到达的反馈通常不能直接影响已经完成的 Tail Sampling 决策,应通过 Trace ID 关联到后续评估数据或独立保留策略。

13.7 统一传播 Context

HTTP 自动传播通常较成熟;队列、定时任务和数据库任务需要显式注入与提取 Context。否则 Worker Trace 会与入口请求断开。

13.8 使用 Resource 与版本信息

至少设置:

service.name
service.version
deployment.environment.name

AI 应用还应记录 gen_ai.agent.version,并使用自定义命名空间记录 app.prompt.versionapp.knowledge_base.versionapp.release.git_sha,以便比较版本回归。

13.9 监控 Collector 自身

Collector 也会出现队列堆积、内存不足、导出失败和数据丢弃。生产环境必须监控它的接收量、发送失败、队列容量和丢弃数量。


14. 一个最小 Python Trace 示例

下面展示一个可以独立运行的最小示例。先安装依赖:

pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http

示例假设本机 4318 端口已有支持 OTLP/HTTP 的 Collector 或后端。实际项目通常还会加入自动插桩、Metric、日志关联与脱敏。

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

resource = Resource.create(
    {
        "service.name": "my-rag-agent",
        "service.version": "1.0.0",
        "deployment.environment.name": "development",
    }
)

provider = TracerProvider(resource=resource)
provider.add_span_processor(
    BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint="http://localhost:4318/v1/traces",
        )
    )
)
trace.set_tracer_provider(provider)

tracer = trace.get_tracer("my-rag-agent")


def retrieve(query: str) -> list[str]:
    return [f"example document for: {query}"]


def generate_answer(query: str, documents: list[str]) -> str:
    return f"answer based on {len(documents)} document(s)"


def run_agent(query: str) -> str:
    with tracer.start_as_current_span("agent.run") as root:
        root.set_attribute("gen_ai.agent.name", "rag-agent")
        root.set_attribute("app.prompt.version", "answer-v3")

        with tracer.start_as_current_span("rag.retrieve") as span:
            documents = retrieve(query)
            span.set_attribute("app.rag.result_count", len(documents))

        with tracer.start_as_current_span("llm.generate") as span:
            answer = generate_answer(query, documents)
            span.set_attribute("gen_ai.request.model", "example-model")

        return answer


if __name__ == "__main__":
    print(run_agent("What is OpenTelemetry?"))
    provider.force_flush()

这个例子产生:

agent.run
├── rag.retrieve
└── llm.generate

后续再逐步加入 FastAPI 自动插桩、HTTPX、数据库、队列 Context、Metrics 和日志关联即可。示例中的 agent.runrag.retrievellm.generateapp.rag.result_count 是教学用的应用自定义命名;如果项目采用 GenAI 语义约定,应按所固定版本的 Span 命名和属性要求实现。


15. 初学者最常见的误解

“OpenTelemetry 就是监控平台”

错误。它主要负责标准化采集、关联、处理和导出;真正的 UI、存储和分析由后端平台完成。

“OTLP 就是 Collector”

错误。OTLP 是传输协议;Collector 是接收和处理数据的服务。

“Trace 和 Log 是同一种东西”

错误。Trace 展示一次请求的结构化执行链;Log 记录具体事件和细节。

“Metric 是很多 Trace 自动相加”

不完全正确。Metric 有独立的数据模型、Instrument 和聚合体系;可以从应用直接记录,也可以由其他数据转换而来。

“Instrument 就是插桩”

错误。Instrumentation 是插桩过程;Instrument 是 Metrics 里的 Counter、Histogram 等工具。

“Session 就是一条 Trace”

错误。一段多轮 Session 通常包含多条独立 Trace。

“有了 Trace 就完成了 Evaluation”

错误。Trace 记录执行事实;Evaluation 需要规则、Ground Truth、LLM Judge、人工反馈或真实业务结果来判断质量。


16. 建议的学习与落地顺序

第一阶段:只理解 Trace

实现:

一次 Agent Run = 一条 Trace
LLM、RAG、Tool = 子 Span

先学会在后端界面完整查看一次请求。

第二阶段:加入 Metrics 和结构化日志

添加:

请求数
错误率
延迟 Histogram
Token 和成本
JSON 日志 + trace_id/span_id

第三阶段:加入 Collector

集中实现:

批处理
脱敏
采样
重试
多后端分发

第四阶段:连接 Evaluation

把用户反馈、任务成功、工具正确率和 LLM Judge 分数关联到 Trace,并让失败案例进入 Dataset 和 CI 回归。


结语

对 AI 应用开发者来说,最重要的不是一次记住所有 OpenTelemetry 术语,而是先建立这条主线:

应用通过插桩产生 Trace、Metric 和 Log
SDK 处理并通过 OTLP 导出
Collector 统一接收、加工和分发
Langfuse、Tempo、Prometheus 等后端负责存储、展示和分析

再用一句话区分三类核心信号:

Trace:这一次请求经历了什么
Metrics:系统整体最近表现如何
Logs:某个时刻具体发生了什么

在 AI Agent 中,OpenTelemetry 的核心价值是把模型、检索、工具、数据库、队列和外部服务放进同一条可追踪链路;而 Langfuse、LangSmith、Phoenix 等平台则在此基础上进一步提供 AI 专用的分析和评估能力。

真正成熟的方案不是“把所有数据全都记录下来”,而是:

记录有诊断价值的数据,使用统一语义,保护敏感信息,控制成本,并让可观测数据持续服务于评估和改进。


官方参考资料