S3-架构方法论篇-03-可观测性:让"为什么慢了"不再是玄学
🔭 可观测性:让"为什么慢了"不再是玄学
本文是《从零吃透企业级 AI 平台》第三季·架构方法论的第 3 篇
⚠️ 事实锚点速记:本篇沿用第三季事实锚点——以「万悟(Apache-2.0 开源,源码可查)↔ WorkBuddy(闭源产品,仅公开方法论)」双平台作方法论对照;完整声明、信源与"为何不把两者都当开源"见 《00 · 第三季导读》。
🎯 本文目标
读完本文,你将:
- 理解"日志 ≠ 可观测性",以及结构化日志、分布式追踪、指标三者的分工与协作
- 看清万悟如何用 OpenTelemetry 在 11 个微服务间串起 Trace / Span / Context 传播(请求维度可观测)
- 看清 WorkBuddy 如何用传感器矩阵 + Audit 回放做"Agent 行为可观测"(决策维度可观测)
- 能够为自己的系统设计一套"30 秒内定位问题"的可观测性方案
前置知识:了解基本的 HTTP 请求生命周期;了解 Trace / Span 基本概念更佳,但非必须
1. "分析结果不对"——然后呢?
一个周五下午,客户支持转来一条工单:
"文档 D-2024-08832 的分析结果明显不对,第 7 段被标为'无风险',但原文其实写了'无上限'。请解释。"
工程师打开日志系统,搜索文档 ID。找到了 47 条日志,分布在 4 个模块里:
[api-gateway] 14:32:01.003 INFO request received, doc_id=D-2024-08832
[parser-go] 14:32:01.087 INFO parsed 23 segments
[rule-engine] 14:32:01.204 INFO matched 18 rules
[llm-service] 14:32:03.891 INFO completion received, tokens=1847
[analysis-py] 14:32:04.102 INFO analysis score computed
[api-gateway] 14:32:04.115 INFO response sent, status=200
看起来一切正常。但客户说结果不对。问题出在哪里?
- 是 Parser 把第 7 段解析错了?(23 段里有没有漏掉子条款?)
- 是 RuleEngine 匹配了错误的规则?(18 条规则里哪条负责"无上限"?)
- 是 LLM 返回了错误的判断?(prompt 里传了什么上下文?)
- 是 AnalysisEngine 的基线选错了?(对比的是哪个模板?)
47 条日志,4 个模块,2 种语言,没有任何一条日志能告诉你"这个请求从头到尾经历了什么"。你只能靠时间戳猜测因果关系,然后逐个模块翻代码。
💡 关键洞察:日志回答的是"某个模块在某个时刻做了什么"。但当问题跨越模块边界时,再多日志也拼不出全貌,你需要的是"一条线把所有模块串起来"。这条线,就是分布式追踪(Distributed Trace)。
换到后厨场景:客人投诉"这道菜太咸了"。后厨的日志告诉你"厨师 A 在 14:32 放了盐""厨师 B 在 14:33 放了酱油""摆盘员在 14:35 加了装饰酱汁"。每条日志都是对的,但你无法从这些碎片中还原"这道菜从头到尾经过了几双手、每只手加了多少盐"。你需要的是一张从点单到上桌的完整流转单。
2. 四种可观测性方案横向对比

2.1 纯文本日志(print / log.info)
# 伪代码:最原始的"可观测性"
logger.info(f"parsed {len(segments)} segments")
logger.info(f"matched {len(rules)} rules")
# 问题:无结构、无关联、无法跨模块追踪
# 搜索 "D-2024-08832" 能找到日志,但不知道它们之间的因果关系
2.2 结构化日志(JSON + 统一字段)
# 伪代码:每条日志带统一上下文
logger.info("segment_parsed", extra={
"trace_id": "abc-123", # 全链路唯一 ID
"span_id": "span-001", # 当前操作 ID
"doc_id": "D-2024-08832",
"module": "parser",
"segment_index": 7,
"segment_type": "penalty",
"duration_ms": 12,
})
# 进步:可搜索、可聚合、可按 trace_id 串联
# 不足:仍然是"点",不是"线"——看不到调用拓扑和耗时分布
2.3 分布式追踪(OpenTelemetry)
# 伪代码:每个操作是一个 Span,Span 之间有父子关系
with tracer.start_span("analysis_pipeline", attributes={"doc_id": cid}) as root:
with tracer.start_span("parse", attributes={"segment_count": 23}) as parse_span:
segments = parser.parse(raw_text)
with tracer.start_span("rule_match", attributes={"matched": 18}) as rule_span:
results = rule_engine.match(segments)
with tracer.start_span("llm_review", attributes={"model": "gpt-4o", "tokens": 1847}):
llm_result = llm.review(results)
with tracer.start_span("analysis_compute") as dev_span:
score = analysis_engine.compute(llm_result)
# 产出:一条完整的调用树,每个节点有耗时、状态、属性
# 在 Jaeger/Tempo 中可视化:一眼看到哪个 Span 慢了、哪个 Span 报错了
2.4 全量录制(Replay / Session Recording)
# 伪代码:记录完整的输入输出,支持事后回放
recorder.capture(
trace_id="abc-123",
input=raw_doc_text, # 完整原文
llm_prompt=full_prompt, # 完整 prompt(含 system + user)
llm_response=full_completion, # 完整返回
rule_matches=all_rule_results, # 所有规则匹配结果
final_output=analysis_result, # 最终输出
)
# 优势:可以完整复现"为什么结果是这样"
# 代价:存储成本极高(一次分析 ~50KB),隐私合规风险
横向对比
| 纯文本日志 | 结构化日志 | 分布式追踪 | 全量录制 | |
|---|---|---|---|---|
| 回答"发生了什么" | ⚠️ 碎片化 | ✅ | ✅ | ✅ |
| 回答"为什么慢" | ❌ | ⚠️ 需手动关联 | ✅(耗时可视化) | ✅ |
| 回答"为什么结果不对" | ❌ | ⚠️ | ⚠️(知道哪步出错,不知道输入是什么) | ✅(完整复现) |
| 跨模块关联 | ❌ | ⚠️ 靠 trace_id 手动搜 | ✅(自动父子关系) | ✅ |
| 存储成本 | 低 | 低 | 中 | 极高 |
| 实现复杂度 | 零 | 低 | 中 | 高 |
| 隐私风险 | 低 | 低 | 低(只记元数据) | 高(含原文和 prompt) |
| 适合场景 | 开发调试 | 生产基础 | 生产标配 | 高合规 / 纠纷取证 |
📌 小结:三者不是互斥的,而是互补的。结构化日志是地基,分布式追踪是骨架,全量录制是"黑匣子"。通用的选择是:前两者全量开启,第三者按需采样。
3. 两个真实平台怎么选
万悟与 WorkBuddy 都认同"AI 平台必须可观测",但观测的轴线不同:万悟是"分布式链路可观测"(请求维度)——用 OpenTelemetry 在 11 个微服务间串起 Trace / Span / Context 传播;WorkBuddy 是"Agent 行为可观测"(决策维度)——用传感器矩阵 + Audit 回放看清"Agent 每一步在想什么、做了什么"。两者都解决"为什么慢了 / 为什么错了",只是观测的镜头不一样。

3.1 万悟:用 OpenTelemetry 把"请求"串成一条线
万悟可观测性以 OpenTelemetry 为基础(项目已核实),且不止于手写 Span:
- 11 微服务链路:bff / iam / model / mcp / knowledge / rag-service / assistant / agent / app / channel / operate 之间通过 OTel 传播 Trace / Span,跨 Go 与 Python(4 个 Python AI 服务)的请求用 W3C TraceContext 自动串联。
- Coze Loop 自动插桩:go.mod 确认万悟集成了字节跳动的 Coze Loop 平台(
coze-dev/cozeloop-go+eino-ext/callbacks/cozeloop),在 Eino LLM 框架的每次模型调用中自动记录 prompt / token / completion——开发者几乎零成本获得 LLM 调用观测。 - 异步链路可追踪:Kafka 消息链也有 OTel 插桩(
dnwe/otelsarama),知识库文档处理的异步流水线全程可追。 - 检索层可观测:Elasticsearch 检索指标与链路打通。
万悟的路径是"工程化链路可观测"——把可观测性做进框架(Eino 回调、OTel SDK),开发者无需手动写 Span。这正落在汪晟杰 Agent OS 基础设施层"监控运维"与引擎层"Eval 评估"上。
3.2 WorkBuddy:用传感器矩阵 + Audit 回放做"Agent 行为可观测"
WorkBuddy(闭源)的可观测聚焦 Agent 行为本身(Anne M-C-H-L,2026-07-24):
- 反馈层传感器:lint / 类型检查 / 测试 / 构建,作为 Agent 每步产出的质量闸门。
- 周期性传感器:死代码 / 覆盖率 / 依赖风险 / 延迟 / 错误率 / SLO / 日志异常,持续监控产物健康度。
- Audit Log 支持回放:每次调用(含被拒)留痕,支持"事后复现为什么结果是这样"。
- 评测即可观测:WorkBuddy Bench 论文(arXiv:2607.20911)把"评测"做成抗污染、可复现的方法论——任务由真实 commit / PR 逆向构造以阻断"搜索引擎溯源污染",数据集(任务目录 + 环境镜像 + 评测 harness + 测试 + 参考解)全量开源可审计。这本身就是"用评测数据做可观测"的极致表达。
WorkBuddy 的路径是"行为可观测"——不只看请求快慢,更看 Agent 决策链路是否健康、评测是否达标。对应汪晟杰 Agent OS 引擎层"Eval"与统一治理后台"运行观测 / 评估测评 / 质量看板"。
3.3 对照表:请求维度 vs 决策维度
| 维度 | 万悟(请求维度 / 链路可观测) | WorkBuddy(决策维度 / 行为可观测) |
|---|---|---|
| 观测对象 | 跨服务请求 Trace | Agent 行为 + 产物健康 |
| 核心技术 | OpenTelemetry + Coze Loop 自动插桩 | 传感器矩阵 + Audit 回放 |
| 跨语言 | Go + Python 自动 TraceContext 传播 | 单语言产品,无跨语言问题 |
| LLM 调用 | Eino 回调自动记 prompt / token | 反馈层传感器覆盖 |
| 异步 | Kafka OTel 插桩 | 任务级循环记录 |
| 评测 | — | Bench 抗污染可复现评测 |
| 哲学对应 | Agent OS 基础设施"监控运维" | Agent OS 引擎"Eval" + 治理后台"质量看板" |
3.4 同一问题,两种答案:P99 突然飙升
- 万悟:打开 Tempo,按
service/status维度切片,发现是某个微服务 Span 耗时异常——根因可能是 Parser 传入超长文本或某次模型调用变慢,OTel 属性(input length、model、latency)直接定位。 - WorkBuddy:看传感器矩阵的延迟 / SLO 面板 + Audit 回放,定位是哪类任务的 Agent 循环变慢、哪步工具调用拖了后腿;必要时用 Bench 回归评测确认是否模型 / 提示变更引入退化。
两者都在回答"为什么慢了",万悟用链路,WorkBuddy 用行为 + 评测。
4. 业界怎么做的
4.1 Uber:跨语言追踪的先行者
Uber 在 2024 年公开了其内部可观测性平台 M3 + Jaeger 的实践。核心经验:
"追踪的最大敌人不是技术,而是覆盖率。一个 99% 覆盖率的追踪系统,在那 1% 的盲区里,恰好是你最需要排查的问题。"
Uber 的做法是在 CI 中检查:每个新增的 HTTP handler / gRPC method 必须有对应的 Span 创建。万悟把这件事做进了框架层(Eino 回调 + OTel SDK 自动插桩),比"靠开发者自觉 + CI lint"更工程化。
4.2 Honeycomb:高基数指标 vs 传统监控
Honeycomb 的核心理念是"可观测性 ≠ 监控"。监控是预定义仪表盘("CPU > 80% 告警"),可观测性是"用任意维度切片任意问题"。实践中,每条日志都应带 doc_id、tenant_id、segment_type、rule_id 等高基数字段,而不是只有 level 和 module。
4.3 Grafana 全家桶(Loki + Tempo + Mimir)
Grafana 全家桶用一套 LogQL 把日志 / 指标 / 追踪互跳,从 Trace 一键跳到对应日志。对多语言、多模块系统,统一查询语言比"ES + Kibana + Jaeger + Prometheus"五件套的运维成本低得多。
4.4 WorkBuddy 的启示:把"评测"当成可观测的最高形态
作为闭源产品,WorkBuddy 无法让外界翻代码看它的监控系统,但它用 WorkBuddy Bench 论文(arXiv:2607.20911) 把"评测"本身做成了可复现的方法论标杆——任务逆向构造、数据集全量开源、跨模型榜可审计。这对读者的启示是:可观测性的尽头不是"看板更漂亮",而是"我能用同一份数据证明系统没退化"。万悟用 OTel 链路回答"这次请求怎么了",WorkBuddy 用 Bench 评测回答"我的 Agent 整体有没有变差"——两种可观测,互为补充。
5. Trade-off 与常见误区
5.1 这个选择的代价
| 代价 | 具体表现 | 通用应对 |
|---|---|---|
| OTel SDK 有性能开销 | 每个 Span 创建 ~2μs,高并发下累积 | 批量导出(5s 一批),非热路径才加 Span |
| 日志量增大 | 结构化日志比纯文本大 3~5 倍 | 热存储保留 30 天,之后归档 |
| 跨语言字段对齐需要纪律 | Go 用 snake_case,Python 容易写成 camelCase |
CI 中有 schema 校验脚本 |
| 录制数据的隐私合规 | 原文 + prompt 属于高敏感 | 独立加密存储,访问审计 |
5.2 三个常见误区
误区 1:"加了日志就是可观测性。"
日志是可观测性的一个支柱,不是全部。没有 Trace 的日志,在跨模块问题面前就是一堆碎片。没有 Metrics 的日志,你无法回答"系统整体健康吗"。三者缺一不可。
误区 2:"Trace 采样率设 10% 就够了。"
当客户投诉"昨天下午 3 点那次分析不对"时,恰好那条 trace 没被采样到,你就失去了关键证据。通用的选择是:核心业务请求全量追踪,内部健康检查不追踪。 全量追踪的成本远低于"找不到那条 trace"的排查成本。
误区 3:"LLM 调用是个黑盒,追踪没意义。"
LLM 的内部推理确实不可追踪,但 LLM 调用的输入和输出元数据完全可以追踪:prompt token 数、completion token 数、finish_reason、latency、model version。实践中曾通过 Trace 发现:某次 P99 飙升的根因不是 LLM 变慢,而是 Parser 传入了一个 12000 token 的超长段落(正常是 200~800),导致 LLM 处理时间从 2s 变成 14s。没有 Span 属性中的 input.length,这个根因不可能被发现。万悟正是用 Eino 回调自动记录这些属性,把"LLM 黑盒"至少变成"LLM 输入输出元数据白盒"。
5.3 一个开放问题
Trace 粒度到"模块级 Span"时,模块内部的串行逻辑(如 18 条规则的逐条匹配)如果某一条正则出现 catastrophic backtracking,Trace 只能看到"rule_match 这个 Span 耗时 5s",看不到是哪条规则慢的。要不要把粒度细化到"每条规则一个 Span"?代价是 Span 数量爆炸(一次请求可能产生 50+ Span),收益是定位更精准。这个 trade-off 的平衡点,在万悟的 OTel 体系里同样存在——自动插桩的便利,也需要配合合理的采样与聚合策略。
6. 动手练习
场景:你的 AI 文档分析系统上线 3 个月,用户量增长到 200 家企业。最近一周,客户支持收到了 5 条"分析结果不对"的投诉。你的系统目前只有 print 级别的日志,没有 Trace,没有结构化。CTO 给你 2 周时间建立可观测性体系。
任务:设计一个分阶段落地计划,覆盖以下评估维度:
| 阶段 | 时间 | 需要回答的问题 |
|---|---|---|
| 第 1 周 | Day 1~3 | 如何在不改业务代码的前提下,先让日志"可搜索"?(提示:中间件 / 装饰器) |
| 第 1 周 | Day 4~7 | 如何为跨模块调用建立 trace_id 传播?(你的系统是 Python + Node.js) |
| 第 2 周 | Day 8~10 | 如何为 LLM 调用添加关键 Span 属性?(哪些属性是"必须有"的?) |
| 第 2 周 | Day 11~14 | 如何定义 3 个 SLO 并配置告警?(告警阈值怎么定?太松没用,太松狼来了) |
双平台视角:如果预算有限,你更该先学万悟式(OTel 链路,先把"请求怎么走"看清)还是WorkBuddy 式(传感器 + 评测,先把"Agent 行为是否退化"看清)?两者能否只做其一?为什么生产环境通常需要两者叠加?
⏱️ 30 秒速览
这篇你只需要记住 3 件事:
- 可观测性 = 日志 + 指标 + 追踪三支柱,先想清楚「回答什么问题」再选工具
- 万悟用 OpenTelemetry + Coze Loop 做"请求维度"链路可观测;WorkBuddy 用传感器 + Audit 回放做"行为维度"可观测
- 两种可观测轴线不同但互补:链路看清"这次怎么了",评测看清"整体有没有变差"
📌 本文小结
- 日志回答"某个模块做了什么",Trace 回答"一个请求从头到尾经历了什么",Metrics 回答"系统整体怎么样"——三者互补,缺一不可
- 万悟用 OpenTelemetry + Coze Loop 自动插桩,把可观测做进框架,跨 11 微服务 + Go/Python 自动串联
- WorkBuddy用传感器矩阵 + Audit 回放做"Agent 行为可观测",并用 Bench 论文把评测做成抗污染、可复现的方法论
- LLM 调用不是黑盒——输入长度、token 数、finish_reason、latency 都是可追踪的关键属性
- 全量追踪的成本远低于"找不到那条 trace"的排查成本;而评测是"可观测"的最高形态之一
📚 参考资料
- OpenTelemetry Documentation — opentelemetry.io(Concepts → Signals 与 Specification → Trace)
- Charity Majors et al., Observability Engineering, O'Reilly, 2022(第 3 章 Structured Events、第 7 章 Distributed Tracing)
- Uber Engineering, Distributed Tracing at Uber Scale, 2024 — uber.com/blog(Jaeger 大规模实践)
- Grafana Labs, Loki + Tempo + Mimir: Unified Observability — grafana.com/docs
- Honeycomb, Observability is a Many-Splendored Thing — honeycomb.io/blog
- Anne《从模型到 Harness:WorkBuddy 如何把 Agent 做成可用产品》(腾讯技术工程,2026-07-24)— 反馈层 / 周期性传感器、Audit 回放
- 汪晟杰《从一个人到一支队伍,AI 如何重写生产力》(腾讯新闻,2026-07-22,WAIC)— Agent OS 基础设施"监控运维" + 引擎层"Eval" + 治理后台"质量看板"
- Tencent WorkBuddy Bench(arXiv:2607.20911,2026-07-23)— 抗污染可复现评测方法论,一级信源
📖 下一篇预告
第三季·第 4 篇:数据治理与记忆边界
一份文档从上传到销毁,经过几双手?明文存在哪里、加密存在哪里、谁能看、谁能删、删了之后备份里还有没有?当客户说"我要行使被遗忘权"时,你的系统能在 72 小时内彻底清除所有副本吗?更棘手的是:Agent 自己记下的"记忆"——它该记住什么、忘记什么、谁能改?下一篇,我们聊聊"数据不是存进去就完了,它有自己的生老病死;记忆也不是记下来就完了,它有清晰的边界"。
📱 关注公众号,追更不迷路
本系列文章首发于微信公众号「农夫三拳有点癫」,每周更新源码拆解与架构实战。
在微信扫描下方二维码即可关注:
本文来自博客园,作者:老羅,转载请注明原文链接:https://www.cnblogs.com/laoluo2025/p/22767782


浙公网安备 33010602011771号