24.4 观察与告警契约
监控系统不会自动知道“什么对用户重要”。它只会忠实地计算你交给它的数值。
因此告警规则之前要有 observation contract:
本节产出第 25 章的实现合同,而不提前声称指标和 page 已经部署。
24.4.1 每个 SLI 的数据源、查询、维度和缺失语义
一个 SLI 需要哪些字段
最小 observation contract:
| 字段 | 问题 |
|---|---|
objective_id |
它实现哪个 SLO/control? |
source |
谁产生原始事实? |
metric_type |
counter、histogram、gauge 还是 event? |
good_selector |
哪些事件进入分子? |
total_selector |
哪些事件进入分母? |
dimensions |
按哪些有界维度分解? |
query_template |
如何从窗口计算? |
missing_semantics |
series 消失代表什么? |
fallback |
主 observation path 失败后看什么? |
metric_status |
已存在、待实现还是 deprecated? |
少一个字段就可能改变结论。
本章的五个来源
| objective | source | type | 状态 |
|---|---|---|---|
| availability | pg36_shop_request_outcomes_total |
counter | 应用待实现 |
| latency | pg36_shop_request_duration_seconds |
histogram | 应用待实现 |
| freshness | pg36_shop_commit_visibility_probes_total |
counter | synthetic probe 待实现 |
| correctness | pg36_shop_reconciliation_mismatches |
gauge | 核对任务待实现 |
| restore readiness | pg36_shop_restore_evidence_age_seconds |
gauge | 证据导出器待实现 |
这些是本书定义的应用 metric contract,不是 Pigsty 内置指标。metric_status
故意保留“to implement”,防止目录文档冒充运行事实。
availability query
原始 counter:
bad ratio 模板:
unknown 在核对前不进入 good,所以会消耗预算。后续事件若核对为 committed
once,可通过事件管道作有审计的最终分类;不能在 dashboard 手工改值。
clamp_min 只防除零,不解决 telemetry missing。no traffic、counter absent 和
ingestion broken 要由独立 freshness/metamonitoring 判断。
latency query
histogram 需要 le="0.25" bucket:
这里示意把快速失败留在 denominator 而不进入 good bucket。实际 instrumentation 也可以统一用 outcome counter 与 duration histogram 通过 recording rule 对齐, 但必须有自动测试证明:
否则两个 SLO 使用不同分母,会产生无法解释的预算。
freshness query
每个 probe:
bad ratio:
probe absence:
不能用 pg_last_xact_replay_timestamp() 填补,因为它没有对应当前 commit。
correctness query
需要配套:
last_success_timestamp;- reconciliation input boundary;
- rule/query version;
- invariant;
- result hash。
只导出 0 而不监控 job freshness,会在核对任务停摆后永远显示“零差异”。
missing semantics:
restore evidence age
阈值 90 天:
导出器必须只接受验证通过且完整性 hash 正确的 restore manifest。不能因为目录中 有一个新文件,就把 evidence age 归零。
PostgreSQL statistics 用于解释原因
PostgreSQL 18 提供:
pg_stat_activity:backend、状态、query/transaction 时间;pg_stat_database:transaction、block、tuple 与 session 统计;pg_stat_replication:sender、state、LSN 与同步状态;pg_stat_wal_receiver:standby receiver;pg_stat_archiver:归档成功/失败;pg_stat_io:按 backend/object/context 的 I/O;pg_stat_ssl:连接 TLS;- lock 与 progress views。
完整目录见 PostgreSQL Monitoring Database Activity。
这些视图回答:
不直接回答:
访问统计应使用 pg_monitor 等受控预定义角色或更窄授权,而不是让 exporter
成为 superuser。预定义角色边界见
Predefined Roles。
Pigsty v4.5 的实现层
当前 Pigsty 监控栈:
| 组件 | 职责 |
|---|---|
| VictoriaMetrics | 时序 ingestion、storage、query |
| VictoriaLogs | 结构化日志 |
| VMAlert | 规则评估 |
| Alertmanager | 聚合、抑制、路由、通知 |
| Grafana | dashboard 与调查入口 |
| exporter/agent | 暴露数据库、主机和组件事实 |
Pigsty v4 已从旧的 Prometheus/Loki 存储迁到 VictoriaMetrics/VictoriaLogs; VMAlert 仍使用 PromQL-compatible 规则。不要复制旧文档后声称 v4 仍以 Prometheus server 存储时序。当前架构见 Monitoring System。
PostgreSQL、PgBouncer、host、load balancer 尽量通过:
关联,详见 PGSQL Monitoring。
维度:服务与组件分别建模
应用 SLI:
组件 telemetry:
连接方式:
不要强行把 service 填成 ins,也不要把所有 database metric 复制一份
customer label。
cardinality 是可靠性和隐私问题
禁止 label:
customer_id;tenant_id;order_id;- raw SQL;
- error message;
- stack trace。
原因:
- series 数无界增长;
- query 和 rule 变慢;
- monitoring storage 自身失稳;
- 用户数据进入广泛可见系统;
- label 变化让 aggregation 不可靠。
使用:
- bounded error class;
- normalized SQL fingerprint;
- exemplar/correlation token;
- 受控日志查明具体事件。
missing-data truth table
| traffic/probe | SLI series | 结论 |
|---|---|---|
| 有预期流量 | 存在 | 计算 SLI |
| 有预期流量 | 缺失 | observation failure |
| 无真实流量 | synthetic 存在 | limited synthetic evidence |
| 无真实流量 | synthetic 缺失 | unknown |
| exporter 存在 | app SLI 缺失 | component observable, service unknown |
| app SLI 存在 | Alertmanager canary 失败 | health known, notification path broken |
“没有错误 series”与“error counter value is zero”不是一回事。
24.4.2 告警必须绑定用户影响、首个安全动作和所有者
page 的门槛
Prometheus 官方 alerting practices 总结为:
- 保持简单;
- 对症状告警;
- 用良好 console 定位原因;
- 避免无事可做的 page。
本章把 page 定义为:
缺一项就应考虑 dashboard、ticket 或删除。
一个 alert contract
每个 accepted alert 至少包含:
这比:
多出来的内容,正是值班可行动性的来源。
user impact 要具体
差:
好:
差:
好:
first safe action 不是最终修复
fast-burn availability page:
它没有假设根因。之后 Runbook 才检查应用、入口、pool、PostgreSQL、锁和拓扑。
correctness page:
不能先运行“修复 SQL”,否则会覆盖事故证据。
metamonitoring page:
监控断了时先恢复观察,不要凭空重启数据库。
owner 必须有 route
owner_function=service 仍不够。规则要带:
route 要用 canary 验证:
不能只看 Alertmanager 进程 up。
for 防短暂抖动,但会增加检测延迟
Prometheus/VMAlert 风格规则可以使用:
条件必须持续 2 分钟才 firing。它适合滤除短 blip,但不是越大越好:
correctness mismatch 可以 for: 0m,因为单个已确认 mismatch 的后果不同。
当前 Prometheus 规则语义还支持 keep_firing_for,用于条件短暂消失后继续
firing 一段时间;使用前要确认 VMAlert 当前版本的兼容和行为,并通过 rule
test 验证。官方字段见
Alerting rules。
silence 不是关闭问题
silence 必须有:
- incident/change id;
- owner;
- reason;
- exact matcher;
- start/end;
- replacement observation;
- review。
禁止:
计划维护也应尽量使用 route/inhibition 和用户 SLO 的明确政策,而不是让所有 信号消失。
verification 决定何时恢复
fast-burn 恢复:
只看到 alert resolved 可能是:
- series 消失;
- label 改变;
- rule reload 失败;
- traffic 归零;
- silence;
- query error。
Runbook 必须检查 missing semantics 和用户结果。
alert 要有生命周期
规则不是写完永存:
orphaned route 或过期 runbook 应使 CI/治理 review 失败。
24.4.3 症状告警、原因告警与容量预测分开
症状 page
症状直接表示用户或数据后果:
- availability fast burn;
- latency fast burn;
- commit-correlated freshness violation;
- correctness mismatch;
- imminent durability loss;
- observation path loss 导致服务状态不可知。
它回答:
原因 telemetry
原因帮助定位:
- CPU;
- disk latency;
- lock waits;
- pool queue;
- replica WAL distance;
- cache hit ratio;
- autovacuum backlog;
- connection count;
- Patroni member state。
同一用户症状可能有多个原因;同一原因也可能被 redundancy 吸收而没有用户 影响。若每个原因都 page:
值班收到五个 notification,却没有更多信息。
原因应进入:
- linked dashboard;
- diagnostic annotation;
- bounded ticket;
- automatic enrichment。
两个允许越过“用户症状”的例外
完整性/保密性
一条跨租户数据或 confirmed corruption 即使用户尚未报告,也需要立即处理。
迫近耐久性
例如所有可恢复副本/备份路径都失效且继续运行会导致不可恢复数据风险。此时 page 的依据是已定义的 durability control,不是随意的 component threshold。
例外仍要 owner、Runbook、action 和 verification。
容量是有期限的 ticket
容量预测:
通常不是当前 user incident,因此:
- 创建 owned ticket;
- 带 forecast confidence;
- 检查 demand/query mix/retention;
- 给 due date;
- 不在凌晨 page。
若容量已经造成 latency/availability,则症状 SLO 会 page;capacity facts 作为 诊断。
本章候选:
metamonitoring
监控系统也会失败:
- exporter 停止;
- agent 无法发送;
- VictoriaMetrics ingestion/query 失败;
- VMAlert rule evaluation error;
- Alertmanager route 失败;
- receiver 不可达;
- dashboard query 误导。
有效 metamonitoring:
Prometheus alerting practices 也建议用贯穿 PushGateway/Prometheus/ Alertmanager/email 的 blackbox 测试,而不是只盯每个组件进程。Pigsty v4 中要 把这个思想映射到 VictoriaMetrics/VMAlert/Alertmanager。
分类矩阵
| signal | class | route | 例子 |
|---|---|---|---|
| user event bad ratio | symptom | page/ticket by burn | availability |
| data invariant mismatch | integrity | page | duplicate/cross-tenant |
| WAL distance | cause | dashboard | replication diagnosis |
| pool queue | cause | dashboard | latency diagnosis |
| CPU | cause | dashboard/ticket | capacity/diagnosis |
| days-to-full | capacity | ticket | disk/storage |
| notification canary overdue | metamonitoring | page | blind operation |
本章明确拒绝的 page
候选:
被拒绝,因为:
- 一台 instance 可因 offline maintenance 合理下线;
- redundancy 可能仍满足服务;
- 没有声明用户影响;
- 没有 owner;
- 没有 Runbook;
- 没有第一安全动作。
替代:
validator 会故意把它的 decision 改成 accepted,并确认合同拒绝。
24.4.4 产出供 ch25 实现的告警规则清单
七个 accepted candidates
1. PG36ShopAvailabilityFastBurn
对 99.9%:
即两个窗口 bad ratio 都高于 1.44%。
2. PG36ShopAvailabilitySlowBurn
阈值 0.6% bad ratio。
3. PG36ShopAvailabilityBudgetTicket
用于慢性消耗,不打扰夜间值班。
4. PG36ShopCorrectnessMismatch
不使用 burn rate。
5. PG36ShopFreshnessFastBurn
不要把所有 read traffic 永久移到 primary;这是有界安全动作,恢复后再评审 read policy。
6. PG36ShopCapacityHorizon
预测没有足够历史时,创建 evidence-quality ticket,而不是编造 forecast。
7. PG36MonitoringPathBroken
rule skeleton
第 25 章可从下面开始,但必须使用 recording rules 和测试后的真实 label:
这段只是规则语义骨架,不能直接部署,因为:
- recording rules 尚未实现;
- production environment/region labels 尚未固定;
- route 与 receiver 仍是教学标识;
- real owner 尚未批准;
- rule evaluation interval 尚未纳入检测时间;
- test fixture 尚未建立。
第 25 章必须交付什么
Instrumentation
- counters/histograms 的真实采集;
- eligible/good classifier tests;
- commit token probe;
- reconciliation freshness;
- restore evidence exporter;
- bounded labels。
Recording rules
- 5m、30m、1h、6h、3d 等窗口;
- label-preserving aggregation;
- reset 和 counter semantics;
- no-traffic/missing 分支;
- rule unit tests。
Alert rules
- 七个 accepted candidates;
- actionless candidate 保持 rejected;
for和 evaluation delay;- route/inhibition/silence;
- review expiry。
Dashboards
- SLI、target、budget remaining;
- numerator/denominator;
- eligible classification;
- recent changes;
- component cause drill-down;
- missing telemetry state。
Delivery tests
- synthetic rule firing;
- label/annotation assertions;
- Alertmanager grouping;
- notification canary;
- acknowledgement;
- resolved 与 missing 的区分。
交接门槛
在实现规则前逐项确认:
- objective id 与 SLO policy 一致;
- metric status 从“待实现”变更有 evidence;
- good/total selector 经过代码测试;
- histogram 有目标 bucket;
- unknown outcome 不会被算 good;
- missing series 有独立规则;
- labels 有界且不泄露数据;
- Pigsty identity 使用
cls/ins/ip; - component facts 不冒充 user SLI;
- multiwindow 使用 AND;
- page 有 owner、route、Runbook、action 和 verification;
- capacity 进入 ticket;
- cause 进入 dashboard;
- correctness/durability 例外有独立 control;
- notification path 自身被测试;
- real pager 测试获得明确授权;
- sandbox 规则没有被称为 production-approved。
完整输入见:
下一节处理这些指标、变更和操作留下的证据:证据必须足够证明决定,却不能把 秘密和个人数据无边界地复制到治理系统。
上一节:SOP、Runbook 与变更治理 · 返回本章目录 · 下一节:证据、审计与合规 · 查看全书目录 · 查看索引中心