LLM 应用可观测性工程 2026:采样、成本与评估的三线归一
用 OpenTelemetry GenAI 语义约定统一采集、用 tail sampling 与列存扛住大负载、用价格表版本化与缓存 token 做成本归因、再用生产 trace 喂出评估集与回归门禁——采样、成本、评估三线归一,LLM 应用的可观测性才算真正闭环。
约 38 分钟阅读11,235 字2 次阅读博主

用 OpenTelemetry GenAI 语义约定统一采集、用 tail sampling 与列存扛住大负载、用价格表版本化与缓存 token 做成本归因、再用生产 trace 喂出评估集与回归门禁——采样、成本、评估三线归一,LLM 应用的可观测性才算真正闭环。

传统 APM 解决的是微服务时代的问题:调用在哪里慢、错误发生在哪一跳、依赖树里哪个节点超时。把同一套工具原样搬到 LLM 应用上,你会发现它对三类最高频的故障视而不见。
第一类是模型行为退化。同一个 prompt,模型的输出分布会随版本、温度、上下文截断策略而漂移;span 的状态码全绿,HTTP 200、耗时正常,业务结果却已经错了。传统 APM 的健康判定建立在「请求是否成功返回」上,而 LLM 应用最贵的失败恰恰是「成功返回了错误的东西」。
第二类是成本异常。一次 agent 循环可能展开成几十次模型调用:重试、级联、上下文重放,让单次用户请求的真实成本达到静态估算的数倍。更麻烦的是缓存与计费口径——命中 prompt cache 的输入 token 与未命中的输入 token 价差可以到数倍,而通用 APM 的属性模型里根本没有这个字段。
第三类是质量回归不可定位。prompt 改了一个分句、检索层换了一个 rerank 模型、基座模型升了一个小版本——任何一层动了,线上质量指标都可能在几天后缓慢劣化,但没有人能回答「是哪一层引入的」。答案不在调用栈里,而在调用内容与调用结果里。
这三类故障的共同点非常清晰:故障的「真相」由两类传统 APM 没有建模的数据构成——调用内容(prompt、消息、工具输出)与调用结果(token 用量、结束原因、人工或模型评分)。2026 年这一波 LLM 可观测性平台的密集迭代,本质上都在补同一个缺口:让这两类数据成为遥测体系的一等公民。据 GitHub 实测(截至 2026-10-24),这一赛道的头部开源项目已经完成了一轮洗牌与收敛:Langfuse 36.3k stars、promptfoo 26.4k、Opik 22.9k、Phoenix 12.0k,而 LangSmith 的 Python SDK 仓库在 2026-10-16 被正式归档拆分。本文把这些信号与 OpenTelemetry GenAI 语义约定的最新进展放在一起,给出一条从采集、传输、存储到成本归因与质量评估的完整工程路线。
把 LLM 应用的观测对象形式化为四层,后文的所有讨论都在这个坐标系上进行。
第一层:operation(操作类型)。 一次模型推理、一次 embedding、一次工具执行,对应语义约定中的 gen_ai.operation.name,其已知值集合包括 chat、embeddings、execute_tool 等。这是所有下游聚合的第一维度——「按操作类型看成本、看延迟」是 LLM 应用与普通服务最大的差异之一,因为不同操作的价差和延迟分布可以差出两个数量级。
第二层:span(跨度)。 带属性的操作实例。属性分三组:请求组(请求的模型名、温度、max_tokens、是否流式)、响应组(结束原因、响应 id、实际服务的模型版本)、用量组(输入/输出 token 数)。用量组是成本归因的原料,2026 年语义约定的一个重要变化是把缓存命中单独建模——gen_ai.usage.cache_read.input_tokens 已进入属性注册表,输入 token 还细分出文本与图像两类(gen_ai.usage.text.input_tokens、gen_ai.usage.image.input_tokens,据 semconv-genai 仓库属性注册表,2026-10-23 提交实测)。
第三层:message(消息内容)。 prompt 与输出的具体文本。这是体积最大、价值最高、也最敏感的一层。最新草案把它放在三个 span 属性里:gen_ai.system_instructions(系统指令)、gen_ai.input.messages(输入消息)、gen_ai.output.messages(输出消息)。值得注意的是,早期版本走的是 span event 路线(gen_ai.system.message 等事件),新草案收敛为 span 属性——这个变化直接决定了「内容跟 trace 走还是跟事件流走」的存储布局。
第四层:score(评分)。 人类反馈、LLM-as-judge、规则校验产出的质量分。评分必须能反向 join 回 trace,否则评估就脱离了生产现场。
这个四层模型里藏着一条核心张力:内容与指标必须分离存储。token 数是低基数数值,进时序库近乎免费;prompt 内容是高基数大文本,进时序库既贵又危险(隐私、PII、合规);评分既小又必须可关联。观察 2026 年各平台的存储设计,几乎都是这条张力的不同解法:代理层路线(Helicone 类)天然拿到完整内容;SDK 路线把内容随 span 上报,由服务端决定落地层;Phoenix 路线复用 OpenInference 规范把内容编码进 OTel span 属性。工程上没有唯一正确解,只有「你的查询模式是什么」。
采集是整条管线里对应用代码侵入性最强的一层,2026 年的主流做法收敛为三条路线,各有明确的适用边界。
路线一:SDK 内嵌 hook。 在官方 SDK(OpenAI、Anthropic 等客户端库)或其包装层上打点。OpenLLMetry(Traceloop,据 GitHub 实测 7.5k stars,Apache-2.0,最近一次 release 为 2026-09-29 的 0.62.4)与 OpenLIT(2.9k stars)都走这条路,本质是把 OTel 的 instrumentation 机制套在 LLM 客户端上。优点是零业务侵入、语义约定对齐度最高;缺点是对非标准调用(自研网关、私有化模型)需要自己写 instrumentation。
路线二:代理层。 在应用与模型 API 之间放一个代理,所有流量过网关。Helicone(6.2k stars,YC W23)是这条路线的代表。优点是应用零改造、天然拿到完整请求响应、多租户元数据注入容易;缺点是流式响应的延迟开销、对 SDK 特有参数(如函数调用本地处理)的支持不全,以及内网部署时的链路信任问题。
路线三:框架回调。 LangChain、LlamaIndex、Agent 框架普遍提供 callback/hook 机制,把整个 agent 循环(含工具调用、检索步骤)作为一个 trace 上报。优点是能拿到 agent 语义(哪一步是计划、哪一步是工具、哪一步是最终答案);缺点是框架耦合深,换框架等于换遥测。
三条路线的选型判据只有一个问题:你要在哪个粒度上回答问题。只回答「token 花了多少」——代理层最省事;要回答「这次 agent 循环为什么走了 11 步」——框架回调不可替代;要回答「全公司统一遥测」——SDK hook + OTel 是唯一能同时喂给 Grafana 与专业平台的方案。实践中成熟团队往往三条并存:代理层兜底全量、SDK 层出标准 span、框架层补 agent 语义。
采样设计是采集层的第二个决策点,也是大多数团队低估的一点。LLM 遥测的单条成本远高于普通 HTTP 遥测(一条带完整消息的 span 可以几十 KB),全量上报在日均千万级调用的应用上是一笔真金白银。可行的分层策略:客户端对成功请求按比例采样(如 10%),对错误、超时、token 异常(如输出超阈值)全量上报;采集端用 OTel Collector 的 tail_sampling 处理器做第二道过滤——按 trace 聚合后再决策,保证「一次用户请求要么整条留、要么整条丢」。另有一个常被忽略的维度:评估驱动的抽样——在线评估模块每天主动抽取固定量的生产 trace 回放评分,这部分必须全量保留,否则评估数据集会向「异常流量」偏置。
2026 年 LLM 可观测性最重要的标准化事件,是 OpenTelemetry GenAI 语义约定从主仓库拆出、独立建仓。据 GitHub 实测,open-telemetry/semantic-conventions-genai 仓库创建于 2026-05-05,截至 2026-10-24 已覆盖 spans、agent spans、events、metrics、token metrics、exceptions、MCP 以及 OpenAI/Anthropic/AWS Bedrock/Azure 等厂商特定约定;OpenTelemetry 官网的旧 GenAI 文档页已标注迁移。对生态来说这是成熟信号:约定有了独立的发版节奏和专属的治理流程,配套的 Weaver 工具链负责从 YAML 定义生成文档与代码,仓库里甚至维护了一张覆盖 LangChain、LlamaIndex、DSPy、OpenAI Agents、Claude Agent SDK、CrewAI、Pydantic AI、Google ADK、AutoGen、Haystack、LiteLLM 等十余个框架的参考实现合规矩阵。
但工程团队更该关心的是不兼容成本。本次规范演进中有三处破坏性或准破坏性变化,迁移时都会踩到。
第一处是属性改名:gen_ai.system 更名为 gen_ai.provider.name。看起来只是字段名,实际上所有按旧字段做仪表盘、告警、成本报表的历史数据都要么双写、要么断代。第二处是内容承载方式变化:消息内容从 span event 迁移为 span 属性(gen_ai.input.messages / gen_ai.output.messages)。这改变了存储引擎的选择前提——event 流与属性列在 ClickHouse、Elasticsearch 里的建模方式完全不同。第三处是用量模型细化:缓存命中 token、文本/图像 token 拆分进入注册表。这是好事(缓存经济学终于可观测了),但旧版 instrumentation 不会上报这些字段,升级前后成本数据不可比。
给工程团队的操作建议:把语义约定版本当作接口契约管理——在内部遥测封装层做一次映射(内部字段名 ↔ semconv 字段名),升级时只改映射层;对内容字段单独设开关(很多生产环境默认关闭内容上报,只在影子流量或用户授权会话开启);用 Weaver 生成的校验器在 CI 里拦截不符合当前约定的 span。这是用最小代价吃到标准化的方式。
采集之后的链路是标准的 OTel 架构,但 LLM 负载给了它几个非标约束。
标准管道长这样:应用内的 SDK/agent 把 span 吐给本机或旁路的 OTel Collector,Collector 走 receiver → processor(tail_sampling、batch、attributes 处理)→ exporter 的流水线,落到后端存储。据 GitHub 实测,collector-contrib 主仓(5.0k stars)持续高频率提交,tail_sampling 处理器已经是生产级标配。下面这张图给出参考布局:
图表加载中…
约束一:基数爆炸。 传统 APM 的 cardinality 教训(把 user_id 塞进 metric label)在 LLM 遥测里会以新形态重现:把 gen_ai.request.model 的高基数变体(带日期后缀的快照版本)、会话 id、prompt 模板 hash 直接做成标签,几天就能把时序库拖垮。治理原则不变——数值和低基数字段进 metric/列,高基数内容进对象存储或专门的内容表,在列存里只留内容指纹(hash)用于关联。
约束二:大负载。 一条带完整多轮对话的 trace 可以到几百 KB,Collector 的 batch 与内存队列要按这个量级调参;长文本建议在采集端就做截断或引用(存对象存储、span 里留指针),否则一条链路重放就能打爆默认的 4MB gRPC 上限。
约束三:隐私与驻留。 消息内容层是 PII 重灾区。可行做法是采集端做脱敏(实体替换 + 可逆映射本地保存)、按租户开关内容上报、给内容表单独设保留期(如 7 天)与访问审计。这一层没有通用答案,只有「你的合规边界在哪」。
存储选型上,2026 年的事实标准是列存。ClickHouse 对 trace 类宽表(百万列位、高压缩、按时间分区)的适配使它成为多家平台的分析底座——例如 Langfuse 的自托管部署据公开文档就引入了 ClickHouse 作为分析存储(截至 2026-10-24,部署细节以官方文档为准,本文未逐项复核版本要求)。自建团队如果没有运维 ClickHouse 的预算,退而求其次是 OTel 默认的 Jaeger/Elasticsearch 组合,代价是成本归因类聚合查询会明显吃力。
成本归因是 LLM 可观测性里投资回报最确定的一块:仪表盘建好的第一周通常就能找到 20% 以上的浪费。它由四个组件构成。
组件一:token 计量。 直接消费用量组的属性。注意流式响应的用量在最后一个 chunk 才到齐、某些厂商在流式模式下不返回 usage 字段(需要本地 tokenizer 估算并打上「估算」标记),估算值与账单值的对账差应作为一个常驻指标监控。
组件二:价格表版本化。 成本 = token × 单价,而单价是随时间变化的(降价、新版本、批量折扣、缓存价)。价格表必须带生效时间区间,成本计算按调用时刻匹配价格版本,而不是按报表生成时刻——否则历史报表会随降价悄悄「变好看」,成本趋势彻底失真。
组件三:多租户分账。 B 端 LLM 应用绕不开的问题:每个租户、每个功能、每次会话花了多少钱。span 上必须有租户维度(作为低基数字段),配合上面的 SQL 模式即可聚合:
-- 伪 SQL:按租户与操作类型聚合日成本(ClickHouse 方言示意)
SELECT
tenant_id,
gen_ai_operation_name,
sum(input_tokens) AS in_tok,
sum(cache_read_input_tokens) AS cache_tok,
sum(output_tokens) AS out_tok,
round(sum(in_tok * price_in
+ out_tok * price_out), 2) AS cost_usd
FROM otel_gen_ai_spans
WHERE ts >= today() - 1
GROUP BY tenant_id, gen_ai_operation_name
ORDER BY cost_usd DESC
组件四:缓存经济学。 这是 2026 年的新增项。prompt cache 把「输入 token」拆成了两个价位:未命中价与命中价(如 gen_ai.usage.cache_read.input_tokens 所刻画的)。这直接改变了成本优化的靶子——系统提示词越长越该稳定(命中率高),而「每个请求都带用户个性化前缀」的架构在缓存视角下是灾难。可观测性系统应把缓存命中率按 prompt 前缀模板聚合作为一等指标,它是少数几个「改架构能直接省钱」的信号。
最终要把成本归因提升到单位经济学层面:不要只看「今天花了多少钱」,要看「每次成功解决的任务花多少钱」(cost per resolved task)。后者需要把成本数据与业务结果(工单关闭、代码合入、对话完成率)join 起来——这正是可观测性数据与评估体系必须共用一套关联键的原因。
可观测性的终点不是仪表盘,是回归防线。2026 年成熟团队的共识做法是把评估做成三层漏斗,而每一层的原料都来自生产 trace。
第一层:离线评估集。 从生产 trace 里按错误类型、按租户、按难度分层抽样,脱敏后沉淀为版本化的评估数据集。关键工程点:数据集必须与 prompt 版本、模型版本一起做三元组快照——「哪份数据、对哪个 prompt、在哪个模型上跑的分数」三者锁定,否则历史分数不可比。promptfoo(26.4k stars,MIT,最近 release 0.125.0,2026-10-23)与 Opik(22.9k stars,2.2.119,2026-10-23)都把「数据集 + 断言 + CI」作为核心工作流,两者定位高度趋同。
第二层:在线抽样评估。 对生产流量做固定比例抽样,用 LLM-as-judge 打分回写。这层的核心不是算法是采样策略:均匀采样会被大租户淹没,必须按租户、按操作类型分层;新 prompt 上线后头 48 小时加密采样。judge 本身也要分层——廉价的规则校验(JSON schema、长度、引用格式)全量跑;中等成本的评分模型抽 10% 跑;昂贵的成对比较(A/B 两个版本的输出对比)只对统计上有决策价值的样本跑。Langfuse 的评估文档(2026-10-08 更新)把这条链路作为产品主线,据其文档描述,在线评估、人工标注队列与数据集评估共用同一套 score 模型。
第三层:回归门禁。 把第一层的离线数据集挂进 CI:任何 prompt、检索配置、模型版本的变更,先跑评估集,分数低于阈值就拦。这里有一个统计陷阱值得展开:LLM 输出有随机性,小评估集上的分数波动完全可能淹没真实回归。可行做法是固定采样种子做配对比较、按效应量而非绝对分差设阈值(如要求新版本在 95% 置信下不劣于旧版本超过 1 个百分点)、评估集随线上新增失败案例滚动更新。门禁的运行成本本身也要监控——评估集膨胀到跑一次几小时,它就会被工程师绕过。
三层漏斗合起来回答的是同一个问题的三个时态:门禁回答「这次变更会不会坏」,在线抽样回答「现在线上有多坏」,离线数据集回答「我们到底变好了没有」。三层的关联键统一到 trace id 上,整个体系才闭环。
把主流项目按「架构路线 × 一体化程度」摆进矩阵,全部数据为 2026-10-24 的 GitHub API 实测值:
| 项目 | 路线 | stars | 许可证 | 最新版本(发布日) | 定位要点 |
|---|---|---|---|---|---|
| Langfuse | SDK + 自托管平台 | 36,276 | NOASSERTION(仓库自定义许可文件) | v4.69.0(2026-10-23) | trace/评估/prompt 管理一体,开源 + 云双轨 |
| promptfoo | 评估 + 红队 CLI | 26,358 | MIT | 0.125.0(2026-10-23) | 断言/红队/CI 强项,轻平台重流水线 |
| Opik | 评估 + 平台 | 22,861 | Apache-2.0 | 2.2.119(2026-10-23) | Comet 出品,评估与监控并重 |
| Phoenix | OTel 原生平台 | 11,975 | NOASSERTION(Apache-2.0 附加例外,据仓库) | v20.26.0(2026-10-23) | OpenInference 规范,OTel 兼容最深 |
| OpenLLMetry | SDK instrumentation | 7,504 | Apache-2.0 | 0.62.4(2026-09-29) | Traceloop 出品,OTel 语义约定对齐 |
| Helicone | 代理网关 | 6,235 | Apache-2.0 | release 标签停在 2025-08,主分支活跃 | 网关路线,零改造接入 |
| OpenLIT | SDK instrumentation | 2,875 | Apache-2.0 | otel-gpu-collector-1.0.0(2026-10-13) | 仓库描述已转向「agent harness 工程」 |
| LangSmith | SaaS(闭源核心) | SDK 仓已归档 | SDK 为 MIT | langsmith-python v0.14.12(2026-10-21) | LangChain 官方平台,SaaS 为主 |
四个值得展开的收敛信号:
信号一:可观测性与评估正在合并成一句话的产品。 Langfuse 的仓库描述已经从 tracing 平台改写为「agent evals & observability」(据仓库描述,2026-10-24 实测);promptfoo 从「测 prompt」长出了红队扫描;Opik 干脆把 evaluate 和 monitor 并列。单一卖点的工具正在消失,因为第七节的三层漏斗天然要求 trace、评分、数据集在同一个存储里。
信号二:商业平台的仓库重组。 LangChain 的 langsmith-sdk 仓库于 2026-10-16 归档,Python 与 JS SDK 拆分为独立仓库(据仓库归档说明实测)。同属生态位观察:LangChain 主仓描述已变为「agent engineering platform」,LlamaIndex 变为「document processing platform」——基础设施层公司集体从「框架」转向「平台」,遥测是平台粘性的核心部件。
信号三:语义约定吸走了 instrumentation 层的创新。 OpenLLMetry 最近一次 release 停在 2026-09-29,而 semconv-genai 仓库当周仍在高频提交——标准化完成后,instrumentation 层的差异化空间被压缩,价值向上(平台)与向下(Collector 管道)两端迁移。未公开验证的猜想:未来两年 instrumentation 会进一步并入官方 OTel contrib,独立 SDK 项目会转向维护模式。
信号四:版本活跃度要看提交而非 release 标签。 Helicone 的 GitHub release 标签停在 2025 年 8 月,但主分支 2026-10-24 当天仍有提交(实测)——以 release 节奏判断项目生死在快速迭代的项目上并不可靠,选型时应看 commit 频率、issue 响应时长与 roadmap 公开度。
选型建议压缩成三句话:要最快见效且接受 SaaS,LangSmith 生态最顺;要数据自主且团队有运维预算,Langfuse 自托管 + OpenLLMetry 采集是当前最通用的开源组合;要评估先行的团队,promptfoo/Opik 做门禁、任意 trace 平台做生产侧,用 OTel span 属性当关联键。
十二周路线图。 第 1–2 周:接入 SDK hook 或代理,目标是让 token 用量与操作类型进库——只做这两件事,不做内容上报。第 3–4 周:上 Collector + tail sampling,建立采样策略(错误全量、成功抽样),接价格表,出第一版按租户/操作类型的成本日报。第 5–8 周:打开内容层(脱敏后),建 trace 评分回写,跑通在线抽样评估,产出首个质量周报。第 9–12 周:从生产 trace 沉淀离线评估集,接 CI 回归门禁,把缓存命中率与 cost per resolved task 做成一等指标。每一步都有独立回报,不要倒序——先做门禁没有数据集支撑,是 2026 年最常见的烂尾路径。
反模式清单。 其一,全量上报带完整内容的 span:成本一周烧穿预算,然后整个可观测性项目被砍。其二,把 prompt 全文做成 span 属性直接进时序库:基数爆炸 + PII 事故二连。其三,用「平均分」管理质量:LLM 质量分布是长尾的,平均分掩盖的恰恰是头部 5% 的灾难案例,要看分布和最差分位。其四,评估集一次生成永久冻结:模型与产品都在漂移,冻结的评估集三个月后就与线上分布脱钩。其五,把 LLM-as-judge 的分数当客观真值:judge 有自己的偏差(偏好长答案、偏好自身风格族),任何 judge 都必须用人工标注校准子集持续对表。
开放问题。 一是内容层标准化仍在流动:消息从 event 迁到 span 属性只是 2026 年的快照,多模态内容(图像、音频)的属性建模尚未稳定,此时深度绑定任一版本的序列化格式都有返工风险。二是 agent 语义的观测仍弱于调用语义:execute_tool 的 span 约定有了,但「计划—执行—反思」这类循环的拓扑表达还靠各框架自行约定,跨框架的 agent trace 目前不可比。三是成本与质量的多目标优化没有现成答案:省钱的路由策略(小模型优先)几乎必然触碰质量分布,两套指标如何在同一张报表里支持决策,业界还在摸索。
最后给一个判断:LLM 应用的可观测性正在复刻微服务可观测性的十年,但压缩成了两年——标准化先行(semconv 2026 年独立建仓)、平台快速整合(头部项目一周内集体发版)、评估与监控合流。对工程团队而言,2026 年入场不算晚,但入口必须选对:从 token 用量与操作类型这两列数据开始,而不是从「装一个酷炫的 trace 界面」开始。
gen_ai.operation.name、gen_ai.provider.name、gen_ai.input.messages 等属性定义)https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/gen-ai-spans.mdgen_ai.usage.cache_read.input_tokens、文本/图像 token 拆分,2026-10-23 提交版本实测)https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/registry/attributes/gen-ai.md2026 年 LLM 应用的可观测性已收敛为一条标准管线:用 OpenTelemetry GenAI 语义约定统一采集、用 tail sampling 与列存扛住大负载与基数爆炸、用价格表版本化与缓存 token 字段做成本归因、再用生产 trace 喂出离线评估集与在线抽样评估——采样、成本、评估三线归一,才是回归防线,而不是又一块仪表盘。
Conversation
0 条