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. 四种可观测性方案横向对比

image

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 每一步在想什么、做了什么"。两者都解决"为什么慢了 / 为什么错了",只是观测的镜头不一样。

image

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_idtenant_idsegment_typerule_id 等高基数字段,而不是只有 levelmodule

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 件事:

  1. 可观测性 = 日志 + 指标 + 追踪三支柱,先想清楚「回答什么问题」再选工具
  2. 万悟用 OpenTelemetry + Coze Loop 做"请求维度"链路可观测;WorkBuddy 用传感器 + Audit 回放做"行为维度"可观测
  3. 两种可观测轴线不同但互补:链路看清"这次怎么了",评测看清"整体有没有变差"

📌 本文小结

  • 日志回答"某个模块做了什么",Trace 回答"一个请求从头到尾经历了什么",Metrics 回答"系统整体怎么样"——三者互补,缺一不可
  • 万悟用 OpenTelemetry + Coze Loop 自动插桩,把可观测做进框架,跨 11 微服务 + Go/Python 自动串联
  • WorkBuddy用传感器矩阵 + Audit 回放做"Agent 行为可观测",并用 Bench 论文把评测做成抗污染、可复现的方法论
  • LLM 调用不是黑盒——输入长度、token 数、finish_reason、latency 都是可追踪的关键属性
  • 全量追踪的成本远低于"找不到那条 trace"的排查成本;而评测是"可观测"的最高形态之一

📚 参考资料

  1. OpenTelemetry Documentation — opentelemetry.io(Concepts → Signals 与 Specification → Trace)
  2. Charity Majors et al., Observability Engineering, O'Reilly, 2022(第 3 章 Structured Events、第 7 章 Distributed Tracing)
  3. Uber Engineering, Distributed Tracing at Uber Scale, 2024 — uber.com/blog(Jaeger 大规模实践)
  4. Grafana Labs, Loki + Tempo + Mimir: Unified Observabilitygrafana.com/docs
  5. Honeycomb, Observability is a Many-Splendored Thinghoneycomb.io/blog
  6. Anne《从模型到 Harness:WorkBuddy 如何把 Agent 做成可用产品》(腾讯技术工程,2026-07-24)— 反馈层 / 周期性传感器、Audit 回放
  7. 汪晟杰《从一个人到一支队伍,AI 如何重写生产力》(腾讯新闻,2026-07-22,WAIC)— Agent OS 基础设施"监控运维" + 引擎层"Eval" + 治理后台"质量看板"
  8. Tencent WorkBuddy Bench(arXiv:2607.20911,2026-07-23)— 抗污染可复现评测方法论,一级信源

📖 下一篇预告

第三季·第 4 篇:数据治理与记忆边界

一份文档从上传到销毁,经过几双手?明文存在哪里、加密存在哪里、谁能看、谁能删、删了之后备份里还有没有?当客户说"我要行使被遗忘权"时,你的系统能在 72 小时内彻底清除所有副本吗?更棘手的是:Agent 自己记下的"记忆"——它该记住什么、忘记什么、谁能改?下一篇,我们聊聊"数据不是存进去就完了,它有自己的生老病死;记忆也不是记下来就完了,它有清晰的边界"。


📱 关注公众号,追更不迷路

本系列文章首发于微信公众号「农夫三拳有点癫」,每周更新源码拆解与架构实战。

在微信扫描下方二维码即可关注:

账号二维码

posted @ 2026-09-01 08:23  老羅  阅读(18)  评论(0)    收藏  举报