AI 平台工程 / 可观测性与可靠性

GenAI 可观测性与故障恢复实验台

用 OpenTelemetry SDK、Collector、Jaeger、持久队列和可控故障代理验证 GenAI trace 合同、业务结果关联、重复投递、partial success、容量、磁盘与恢复边界。

2026-07 - 持续迭代当前代码
  • OpenTelemetry SDK
  • OpenTelemetry Collector
  • Jaeger
  • Node.js
  • Docker Compose
  • bbolt
  • Linux device-mapper

Reuse contract

复用合同

已独立复现JSON 清单
最近核验
2026/07/18
固定版本
83952b3bae58
代码入口
project-kits/genai-observability-recovery-lab/README.md公开副本固定源码

输入

  • 固定 GenAI trace fixture、semantic convention 合同、合成价格与业务结果
  • 固定镜像 digest、Collector/Jaeger 配置、稳定 trace/span ID 和 payload hash
  • 响应丢失、partial success、下游停机、队列满、max_size、ENOSPC、只读与 EIO 故障合同

输出

  • trace 结构、隐私、token、合成成本、失败层与业务终态的合同违规列表
  • Collector accepted/refused/sent/failed、queue、storage 与恢复阶段指标
  • Jaeger 最终 unique、duplicate、missing span 以及重放和 volume 身份证据

可执行命令

trace-test测试
npm run lab:trace:test
平台
macOS、Linux 或 Windows;离线 Node.js
权威输出
TAP stdout;trace 拓扑、隐私、token、成本、失败层与业务终态合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 trace fixture
trace-capture采集
npm run lab:trace:capture
平台
macOS 或 Linux;离线 Node.js
权威输出
/tmp/younis-ai-lab-genai-traces.json
副作用
会修改运行环境
前置条件
  • Node.js >=22.12.0
  • POSIX /tmp 可写
otel-integration-test测试
npm run lab:otel-integration:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;SDK batching、采样、属性治理、exporter 故障与最终查询合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录已安装锁定 OpenTelemetry 依赖
otel-integration-run运行
npm run lab:otel-integration:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-genai-otel-integration.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像 digest
  • POSIX /tmp 可写且实验端口可用
otel-recovery-test测试
npm run lab:otel-recovery:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;SIGKILL、named volume、queue drain 与 Jaeger 终态合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定结果与 Compose 配置
otel-recovery-run运行
npm run lab:otel-recovery:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-persistent-recovery.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定 Collector/Jaeger 镜像
  • 专用端口和 named volumes 可创建
otel-saturation-test测试
npm run lab:otel-saturation:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;queue capacity、503、拒绝账本、恢复与定向重放合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定结果与配置
otel-saturation-run运行
npm run lab:otel-saturation:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-queue-saturation.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • 专用端口和 named volumes 可创建
otel-ambiguity-test测试
npm run lab:otel-ambiguity:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;commit 后响应丢失、字节一致重试与 Jaeger 去重终态
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定代理结果
otel-ambiguity-run运行
npm run lab:otel-ambiguity:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-commit-ambiguity.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • 故障代理和实验端口可用
otel-partial-test测试
npm run lab:otel-partial:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;HTTP 200 partial success、Collector metrics 与缺失 span 合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 partial-success 结果
otel-partial-run运行
npm run lab:otel-partial:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-partial-success.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • partial-success 代理和实验端口可用
otel-drain-test测试
npm run lab:otel-drain:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;12 批顺序、排空速率、queue 指标和 bbolt 文件增长合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 drain 结果
otel-drain-run运行
npm run lab:otel-drain:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-drain-rate.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • 专用 volume、端口与 POSIX /tmp
otel-storage-full-test测试
npm run lab:otel-storage-full:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;bbolt max_size、queue gauge 漂移、恢复与重放合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 max_size 结果
otel-storage-full-run运行
npm run lab:otel-storage-full:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-storage-full.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • 专用 volume、端口与 POSIX /tmp
otel-enospc-test测试
npm run lab:otel-enospc:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;物理 ENOSPC、字节一致复制、恢复和定向重放合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 ENOSPC 结果
otel-enospc-run运行
npm run lab:otel-enospc:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-enospc-recovery.json
副作用
会修改运行环境
前置条件
  • Docker Compose、固定镜像与 tmpfs volume 支持
  • 专用端口和 POSIX /tmp
otel-readonly-test测试
npm run lab:otel-readonly:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;rw-ro-rw、启动 fail closed、queue 恢复与重放合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定只读恢复结果
otel-readonly-run运行
npm run lab:otel-readonly:run
平台
macOS Docker Desktop 或 Linux Docker
权威输出
/tmp/younis-ai-lab-otel-readonly-storage.json
副作用
会修改运行环境
前置条件
  • Docker Compose 与固定镜像
  • 可切换挂载模式的专用 volume 和端口
otel-eio-test测试
npm run lab:otel-eio:test
平台
macOS、Linux 或 Windows;离线 fixture
权威输出
TAP stdout;linear-error-linear、health/OTLP 分叉、fsck、恢复与重放合同
副作用
不修改状态
前置条件
  • Node.js >=22.12.0
  • 仓库根目录中的固定 EIO 结果
otel-eio-run运行
npm run lab:otel-eio:run
平台
Linux amd64/arm64;需要 privileged device-mapper
权威输出
/tmp/younis-ai-lab-otel-runtime-eio.json
副作用
会修改运行环境
前置条件
  • Linux root、Docker、device-mapper、loop device 与 ext4 工具
  • 专用块设备、端口和 POSIX /tmp

可直接复用

  • 为 GenAI Agent 定义不记录原始 prompt 的低基数 trace 与业务结果 join 合同
  • 验证 Collector 持久队列在进程崩溃、容量耗尽和存储故障下的真实终态
  • 设计稳定 ID、拒绝账本、定向重放、磁盘水位和 queue age 告警

明确边界

  • 输入主要是合成 span 和确定性故障,结果不是生产 trace 样本、模型质量或用户满意度证据。
  • 多数容器实验运行在单机 Docker Desktop;不覆盖节点丢失、跨节点故障转移、真实 SSD 损坏或长期负载。
  • Jaeger/Collector 对重复 span、partial success、health 和错误码的行为与固定版本相关,升级后必须重新验收。

固定结果工件

  • GenAI trace 合同校准结果trace-contract-result
    仓库路径
    labs/genai-trace-contract/results/2026-07-15-results.json
    SHA-256
    8f877139c703ba19020b5e39042db5ee30b8fb44b3f2745d318093a72519a82b
    生成/验证命令
    trace-capture
  • SDK 到 Collector/Jaeger 集成结果otel-integration-result
    仓库路径
    labs/genai-otel-integration/results/2026-07-15-results.json
    SHA-256
    f97f23147880aa0e437b93750e800290c7fb14afb62e9e7f6db5801c04e779a9
    生成/验证命令
    otel-integration-run
  • SIGKILL 持久队列恢复结果otel-recovery-result
    仓库路径
    labs/otel-persistent-recovery/results/2026-07-15-results.json
    SHA-256
    7e9c5f17cc28b6ceb7522e45b8b78f541fd695085a19eff36be20fd39ee9f053
    生成/验证命令
    otel-recovery-run
  • 队列饱和与定向重放结果otel-saturation-result
    仓库路径
    labs/otel-queue-saturation/results/2026-07-15-results.json
    SHA-256
    002a85a03d15555fd36105149038977a43d92c158f1efe62bdd9400feb2ae13a
    生成/验证命令
    otel-saturation-run
  • 后端 commit ambiguity 结果otel-ambiguity-result
    仓库路径
    labs/otel-commit-ambiguity/results/2026-07-15-results.json
    SHA-256
    0f467578e373ff928791e46cd6870f4cd98ffabf2de9833d28d59efe380aeab3
    生成/验证命令
    otel-ambiguity-run
  • OTLP partial success 结果otel-partial-result
    仓库路径
    labs/otel-partial-success/results/2026-07-15-results.json
    SHA-256
    ef3981e27f13ac26ec33dc4bbff5c498bffa4d0c7b23f0e7e9a6e43a8616d5c3
    生成/验证命令
    otel-partial-run
  • 队列排空与磁盘增长结果otel-drain-result
    仓库路径
    labs/otel-drain-rate/results/2026-07-15-results.json
    SHA-256
    169580ecc1c700f6a551143bb3f15b190b8a31f689838a5426a31a859310e236
    生成/验证命令
    otel-drain-run
  • bbolt max_size 满盘结果otel-storage-full-result
    仓库路径
    labs/otel-storage-full/results/2026-07-15-results.json
    SHA-256
    319b1bbaee0458ee1e4b7a164c76ba32a38439230d722da56a089d5474d155be
    生成/验证命令
    otel-storage-full-run
  • tmpfs ENOSPC 异卷恢复结果otel-enospc-result
    仓库路径
    labs/otel-enospc-recovery/results/2026-07-15-results.json
    SHA-256
    294a7776647affe5b847b182b701a4a7f9a0059b18d3981e31f1ed5f760302ba
    生成/验证命令
    otel-enospc-run
  • 只读队列启动恢复结果otel-readonly-result
    仓库路径
    labs/otel-readonly-storage/results/2026-07-16-results.json
    SHA-256
    01a0e7be8e4e105e81beae1848d8cf661d1de8fa94bad15c8407d059f3a82725
    生成/验证命令
    otel-readonly-run
  • 运行期 device-mapper EIO 结果otel-eio-result
    仓库路径
    labs/otel-runtime-eio/results/2026-07-16-results.json
    SHA-256
    cbb2006ee1481ac7ce0437b804a19c9043fdfbd0463fdc75517839bd964b8a6b
    生成/验证命令
    otel-eio-run

项目范围

Agent 可观测性不能只回答“模型调用有没有报错”。一条可交付链路还需要回答:失败发生在 model、retrieval 还是 tool;token 与成本属于哪个业务尝试;技术 span 成功是否真的对应业务完成;Collector 已接受的数据最终是否进入后端;持久队列在响应丢失、容量和存储故障下还能恢复哪些批次。

项目用 11 个独立 lab 把这些问题拆成可判定合同。每个容器实验固定镜像、输入文件哈希、稳定 trace/span ID、故障窗口和最终 Jaeger 查询;结果 JSON 保存原始合同的结构化摘要,而不是只保留终端截图。

Trace 与业务结果

genai-trace-contract 使用仓库内 fixture 校准 Agent、chat、retrieval 与 tool 父子结构、错误归因、token、合成价格、隐私负例和业务结果 join。6 条校准轨迹全部通过,12 条负向控制全部被识别;5 个 chat span 汇总 4,940 input、620 output tokens 和 0.02414 美元合成成本。这里的价格是 fixture,不是供应商账单。

genai-otel-integration 使用真实 OpenTelemetry SDK,经 OTLP/HTTP 发往 Collector 和 Jaeger。24 个 span 分 5 批送达,20/20 条预期 trace 可由 API 查询;实验同时验证 50% head sampling 的固定 drop、receiver 不可达、六类属性治理、技术成功但业务 rejected,以及 memory Jaeger 重建后数据丢失的保留边界。

九组投递与存储故障

Lab 受控变量 权威验收
otel-persistent-recovery Jaeger 停机后 SIGKILL 并删除 Collector/Jaeger 原 volumes 恢复 7 unique queued spans,0 duplicate
otel-queue-saturation queue capacity 固定为 2 batches 第 3 批 503;恢复两批,显式重放后 3/3
otel-commit-ambiguity Jaeger 200 后代理重置响应 Collector 重投相同 payload;后端最终 3 unique、0 duplicate
otel-partial-success 4 spans 中只转发 2 个并返回 HTTP 200 partial success Collector sent=4/failed=0,但 Jaeger 2 present、2 missing
otel-drain-rate 12 批积压、单 consumer、后端每次延迟 250 ms 3.8342 spans/s 排空;queue 归零后 bbolt 仍为 262,144 bytes
otel-storage-full bbolt max_size 65,536 bytes,queue capacity 20 4 批可恢复、2 批被拒;定向重放后 6 unique
otel-enospc-recovery 64 KiB tmpfs 真实写满 异卷字节一致复制恢复 5 批,只重放第 6 批
otel-readonly-storage replacement 只读挂载原 queue volume 启动失败且数据库哈希不变;恢复读写加载 3 批并重放第 4 批
otel-runtime-eio 运行期 device-mapper 从 linear 切到 error health 仍 200 但第 4 批 503;修复与重放后 4 unique

这些实验共同说明 HTTP 200、Collector accepted、queue gauge、health endpoint 和 Jaeger exporter metrics 都不是单独的业务成功证明。恢复决策至少需要稳定 ID、拒绝批次账本、磁盘与 queue 指标、后端最终查询和明确的 replay 规则。

运行方式

纯合同实验可以直接执行 Node 测试;容器实验需要 Docker Engine、Compose、各 README 列出的空闲本机端口,以及 EIO 实验所需的 Docker Desktop LinuxKit privileged device-mapper 能力。

npm run lab:trace:test
npm run lab:otel-integration:test
npm run lab:otel-recovery:test
npm run lab:otel-saturation:test
npm run lab:otel-ambiguity:test
npm run lab:otel-partial:test
npm run lab:otel-drain:test
npm run lab:otel-storage-full:test
npm run lab:otel-enospc:test
npm run lab:otel-readonly:test
npm run lab:otel-eio:test

对应 :run:capture 命令会重建受控环境并写新报告。运行脚本只应操作各自 Compose project、named volume、tmpfs 或专用 loop-backed device;不要把结果工件与 Docker 临时目录混用。

复用原则

先复用 trace contract 和 stable identity,再按系统风险选择故障实验。没有持久队列的系统可先做 exporter failure 与 partial success;已启用 file storage 的系统必须继续验证 max_size、底层容量、只读、恢复挂载和排空速率。每次 Collector、Jaeger、存储或 SDK 升级都应冻结新镜像 identity 并重跑最终状态断言。

生产设计还需增加 queue age、磁盘实际水位、refused/enqueue failed、partial success 和后端查询抽样。拒绝请求只能按稳定业务 ID 定向重放;无法确定后端是否 commit 的批次不能无条件重发。

证据边界

11 个 lab 均为 reproduced,不是生产持续运行数据。单机 Docker host 上保留 volume 的恢复不等于节点丢失恢复,device-mapper error 不等于所有真实磁盘故障,固定 Jaeger 行为也不等于任意后端 exactly-once。项目证明的是可重放的故障合同和观察方法,生产结论必须在目标版本、目标存储与真实流量约束下重新验证。

Research links

关联文章

这些文章分别提供问题背景、设计依据、实验验证或运行证据。

  1. 本文定义 Agent、model、retrieval 与 tool span 合同,并校准隐私、token、合成成本、失败层和业务结果关联。

  2. 本文验证真实 OpenTelemetry SDK 导出的 24 个 span 穿过 Collector 后可由 Jaeger API 查询,并覆盖采样、属性治理和 exporter 故障。

  3. 本文验证 Collector 与 Jaeger 被 SIGKILL 并删除后,保留 named volumes 可恢复 7 个 queued span,最终 7 unique、0 duplicate。

  4. 本文证明 2-batch 队列在第 3 个请求返回 503,恢复只包含已接收两条,显式重放稳定 ID 后才达到 3/3。

  5. 本文制造 Jaeger 已写入但响应被重置的 commit ambiguity,观察 Collector 重投相同 payload 与后端最终去重状态。

  6. 本文验证 HTTP 200 partial success 下 Collector sent=4 仍可能只有 2 个 span 到达 Jaeger,缺失必须由响应与终态共同识别。

  7. 本文记录 12 批积压的排空时间、顺序和 bbolt 文件增长;在固定版本、配置与本次进程生命周期内,queue 归零后文件尺寸保持不变。

  8. 本文验证 bbolt max_size 先于 queue capacity 拒绝写入,并证明 queue gauge 可高估可恢复 batch 数。

  9. 本文在 64 KiB tmpfs 制造真实 ENOSPC,执行字节一致异卷复制,恢复已接受五批并只重放被拒第六批。

  10. 本文把原 queue volume 只读挂载给 replacement,验证进程 fail closed、数据库未变,恢复读写后加载三批并定向重放。

  11. 本文在线切换 device-mapper error target,证明 health 仍为 200 时 OTLP 已 503;修复、fsck、重启与定向重放后终态完整。