25.6 从告警到诊断包
告警只告诉你一个合同条件成立。它不是事故报告,也不是根因分析。
值班最先丢失的往往不是 metric,而是上下文:
诊断包的任务,是在不增加事故的前提下,自动保存一个有界、脱敏、带身份与 时间语义的起点:
它不能承诺:
机器可读合同:
diagnostic-pack-contract.json。
25.6.1 自动保存时间窗、拓扑、变更与关键查询
诊断包从 manifest 开始
任何包先记录:
没有 manifest 的截图无法回答:
- 哪次事件;
- 哪个环境;
- 哪一版 query;
- 谁采集;
- 何时采集;
- 是否做了 mutation;
- 是否后来被改。
target 要通过多源确认
本章正式采集没有相信工作站 SSH alias,而是:
如果其中冲突:
连接成功不是身份验证。
时间窗要覆盖 onset 前后
本章合同默认:
这不是 universal window。选择应考虑:
- 最长 burn window;
- scrape/evaluation/group delay;
- release duration;
- query/log retention;
- incident severity;
- 存储成本。
至少保存:
如果 after window 尚未完成,可以:
- 先保存 initial pack;
- 15 分钟后补一个 immutable supplement;
- 不覆盖 initial;
- manifest 建立 parent/child。
保存 event count,不只保存 ratio
同样 10% bad ratio:
动作和置信度不同。SLO section 保存:
- good/bad/eligible count 或 rate;
- long/short window;
- threshold;
- burn;
- low-traffic flag;
- missing/freshness;
- independent probe;
- objective version。
不要只截图红线。
topology 是事件时刻拓扑
保存:
不自动保存:
- client address;
- password;
- connection URI;
- inventory secret。
IP 是否允许进入私密包取决于政策;本章公开摘要只保留教学网络身份。
变更时间线
收集:
每个 event:
不要直接收集个人聊天全文作为唯一 change log。
PostgreSQL section
本章自动保存:
为什么 activity 只自动聚合:
- 完整 query text 敏感;
- PID 列表可能很大;
- 一次 current sample 很快过时;
- 自动证据的目标是安全起点。
若 incident 需要 blocker graph,runbook 再用受限角色采集二级包。
SQL query controls
采集连接先执行:
并禁止:
READ ONLY 不是绝对安全证明:
- SELECT 仍可很贵;
- function 可能具有副作用,具体取决于实现与权限;
- 系统视图查询可拿锁;
- external extension 可能访问资源。
因此同时使用 allowlisted query、timeout 和 least privilege。
queryid-level top list
自动保存:
限制:
top 50 不是完整 workload。manifest 要写:
平台 section
保存:
- exporter/target freshness;
- VictoriaMetrics health/series;
- VMAlert groups/rules/error/missed iteration;
- Alertmanager failure counter;
- node resource trend;
- 日志 query count,不含 body;
- component versions。
本章公开摘要包括:
它是采集时刻 baseline,不能事后覆盖。
文件布局
建议:
正文和 body 类材料如确需保存,放在更严格的 evidence tier,不与常规诊断包 混合。
分区大小上限
本章每 section:
超限时:
- 不应无限截断而不标记;
- 记录
truncated=true; - 保存 total count;
- 使用 top-N;
- 提供 restricted source link;
- 按需发起二级采集。
初始包与后续包
不要让 T0 自动化拥有 T2 权限。
source hash 与可重放
保存:
- collector version;
- query template hash;
- rule/config hash;
- upstream governance run id;
- output hash;
- capture parameters。
这样以后能回答:
hash 证明 byte identity,不证明内容真实或政策正确;仍需身份和 source trust。
25.6.2 区分首发症状、伴随现象与根因证据
先写 timeline,不先写故事
事实表:
| 时间 | 来源 | 事实 | 置信度 |
|---|---|---|---|
| 10:01:30 | release event | version B 完成 | high |
| 10:03:00 | user SLI | latency short window 超阈值 | high |
| 10:04:00 | PgBouncer metric | wait queue 增长 | medium/high |
| 10:04:20 | trace sample | pool wait 占主要时间 | sampled |
| 10:05:00 | PG activity | active/wait 未显著变化 | point sample |
先不要写:
事实支持的初步说法:
四种状态标签
诊断包中的每条观察带 role,避免相关线自动升级成 root cause。
首发症状不是第一个 dashboard spike
“first observed” 受:
- scrape interval;
- evaluation interval;
- threshold;
- 日志延迟;
- 时钟;
- 采样;
- dashboard refresh
影响。可以说:
不要说“绝对第一个事件”,除非证据支持。
假设要写预测与反证
模板:
这比“看起来像连接池”更可执行。
反例一:CPU 同时升高
可能机制:
- 应用 retry storm 让 CPU 高;
- slow query 让 CPU 高并导致错误;
- batch 与 outage 巧合;
- monitoring query 自身;
- 另一 process。
需要:
CPU 是 correlate,不是自动 cause。
反例二:replica gap 与 stale read
强候选,但仍检查:
- probe 确实走 replica;
- token commit 已确认;
- clock;
- route;
- cache;
- transaction snapshot;
- replica state/timeline。
如果切 primary path 后新 token 立即满足,而 gap 回落后 replica path 恢复, 机制更强。
反例三:归档失败计数
时间线:
结论:
这是 falsification:反驳“非零 counter = 当前故障”。
反例四:锁已经消失
用户 latency 曾受 lock 影响,但初始包晚到:
不能因为 current view 空就否认历史;也不能因为日志有等待就证明当前仍阻塞。 timeline 必须保留各自时间语义。
修复验证要回到症状
如果动作是 cancel blocker:
只是组件验证。还要:
- user burn short/long window;
- event outcome;
- unknown writes reconciliation;
- correctness;
- pool/entry;
- 副作用;
- recurrence。
动作可能同时让 query 消失和用户失败增加。
recovery 不是瞬时绿
fast rule 的两个窗口恢复速度不同:
关闭事件政策可要求:
- 短窗恢复;
- 长窗下降趋势/低于阈值;
- independent probe;
- correctness check;
- no new unknown outcome;
- repair stable for observation period。
不要等所有长窗完全归零,也不要一个样本就关。
counterfactual
root cause review 要问:
不能真实重放生产时,可以:
- staging reproduction;
- synthetic fixture;
- plan/config diff;
- canary;
- independent domain evidence。
明确证据强度。
诊断包不是 postmortem
诊断包:
postmortem:
不要在自动包里预填 root_cause=database。
25.6.3 证据采集本身的负载和权限边界
observer effect
采集会:
- 建立连接;
- 拿
AccessShareLock; - 读取 shared stats;
- 执行 sort/aggregate;
- 查询 storage;
- 扫描日志;
- 占网络与磁盘;
- 出现在
pg_stat_activity/pg_stat_statements; - 影响被观察系统。
目标是有界,不是声称零影响。
风险分级
| 采集 | 风险 | 默认 |
|---|---|---|
| health/version/small metric | L0 | 自动 |
| bounded system-view aggregate | L0 | 自动 |
| top queryid without text | L0 | 自动,有 timeout |
| blocker graph/PID detail | L0/L1 data-sensitive | incident role |
| bounded log body | sensitive | 二级授权 |
| raw SQL/bind export | high data risk | 禁止自动 |
EXPLAIN |
low/moderate | 评估 function/lock |
EXPLAIN ANALYZE |
executes statement | 禁止自动 |
| statistics reset | destructive observation | 禁止 |
| load/fault injection | mutation | 隔离演练 |
EXPLAIN ANALYZE 会执行
对 DML:
真的执行 DELETE,除非在可回滚事务中且没有外部副作用;即便 rollback,也会:
- 运行 trigger/function;
- 拿锁;
- 产生 WAL/side effect;
- 消耗资源;
- 影响 sequence/external service 等。
诊断自动化不得把它当只读。
function 与 extension
SELECT 可以调用:
- volatile function;
- security definer;
- external API;
- advisory lock;
- file/extension;
- sleep。
allowlist system catalog/view query,不接受 incident 参数拼任意 SQL。
query timeout
本章:
timeout 后:
- 记录 section incomplete;
- 保存 error class;
- 不在 tight loop 重试;
- 不自动提高 timeout;
- 交给 operator 决定替代 source。
并发限制
对 100 个 database 同时执行 catalog query,单条很轻也会形成 load spike。
策略:
log query cost
无界:
会拖慢 VictoriaLogs,也可能返回大量敏感正文。
有界:
metric query cost
危险模式:
- regex 匹配所有 metric;
- 高基数 query label 长窗口;
- subquery 小 step;
topk前未聚合;- cross join;
- dashboard 多 panel 同时 refresh;
- incident automation 重复相同查询。
记录:
- expression hash;
- start/end/step;
- series count;
- duration;
- result size;
- timeout/error。
权限
数据库:
监控平台:
不应是一个万能账号。
evidence 文件权限
本章 private bundle:
reviewer 检查所有文件 mode。公共仓库只放 allowlist summary:
- 版本;
- 计数;
- pass/fail;
- declared gaps;
- run id;
- production gate。
evidence secret scan
自动扫描:
- SCRAM verifier;
- private key;
- credential-bearing URI;
- authorization header;
- clear password JSON;
query/raw_sql/sql_text字段。
扫描通过不证明绝对无秘密:
- 未知格式;
- encoded value;
- 业务 PII;
- hash 可重识别;
- file name。
仍要 data classification 与人工 review。
retention
本章 private evidence 教学默认 30 天;生产需独立政策。决定:
- 事件/合规需求;
- 敏感程度;
- 调查周期;
- 删除;
- legal hold;
- backup;
- 访问 audit;
- hash/manifest。
不要因为是“监控证据”永久保存。
完整性与可更新性
原始 initial pack 不覆盖。修正错误时:
公开摘要可以更新展示,但应保留 underlying immutable run reference。
failure-safe behavior
若 capture 失败:
本章 validator 对 application SLI absence 就是:
而不是失败或绿色。
自动化权限不能随事故升级
事故 severity 变高,不代表 collector 自动获得:
- superuser;
- SSH root;
- raw log body;
- query text export;
- failover;
- terminate;
- restore。
需要新 authority 的动作必须停下来进入 SOP/change plan。
诊断入口输出
给第 31 章的输入:
第 31 章再按症状分支:
本节验收
你应当能说明:
- 诊断包为什么先有 manifest;
- target 为什么要多源确认;
- 为什么同时保存 alert、collector 和 database clock;
- ratio 为什么必须带 event count;
- topology 与 change event 为什么要保存事件时刻版本;
- automatic pack 为什么只保存 queryid 聚合;
- T0/T1/T2/T3 四层 evidence 权限如何分开;
- symptom/correlate/hypothesis/cause 的措辞差异;
- 假设为什么必须带预测与反证;
- repair 为什么要回到 user/control signal 验证;
EXPLAIN ANALYZE为什么不能自动运行;- timeout/limit/concurrency 如何让采集 fail-safe;
0700/0600与 public allowlist 各解决什么;- secret scan 为什么仍不能替代数据分类;
- 采集失败为什么必须是 incomplete/unknown 而不是 healthy。
上一节:Pigsty 可观测体系 · 返回本章目录 · 下一节:实战:实现并演练观察契约 · 查看全书目录 · 查看索引中心