第 25 章 望闻问切:监控体系与可观测诊断
“有监控”很容易,“知道发生了什么”很难。
一个看起来成熟的平台可能同时拥有:
26 个 PostgreSQL 仪表盘
3,000 多种指标名
数百条记录规则
几十条告警规则
集中日志
追踪后端
值班通知事故发生时却仍然只能说:
CPU 高了
连接多了
复制慢了
面板红了这些句子描述了现象,没有回答五个决定性问题:
- 用户旅程是否真的失败、变慢、读旧或产生错误结果?
- 这是首发症状、伴随现象,还是已经被证据支持的机制?
- 观察数据是零、尚未刷新、被重置、被采样,还是根本缺失?
- 哪个 owner 应采取什么首个安全动作?
- 什么证据能够证明恢复,而不是仅仅“面板变绿”?
第 24 章先定义了服务、SLI、SLO、控制目标、缺失语义和告警治理。本章做下一步:
observation contract
-> 指标、日志、事件和追踪
-> PostgreSQL 原生统计与 SQL 基线
-> Pigsty 采集、存储、规则、面板和通知
-> 可行动告警
-> 有界诊断包
-> 合成规则与离线路由演练
-> 覆盖表、盲区与生产门禁这条链的重点不是“多收集一些数据”,而是让每个结论都能说明:
question 想回答什么
source 哪个系统产生事实
semantics 值、窗口、标签、reset 和缺失是什么意思
cost 采集、查询和保留会付出什么代价
action 谁可以做什么
verification 怎样证明结论与恢复
boundary 什么仍然不知道本章目标
完成本章后,你应当能够:
- 从用户、入口、数据库和主机四层组织观察问题;
- 区分症状信号、原因信号、控制信号与监控系统自身信号;
- 说明指标、日志、事件和追踪各自适合回答什么;
- 为 label cardinality、采样、保留和查询成本建立预算;
- 把“没有数据”区分为无流量、采集故障、查询错误、延迟与真实零值;
- 正确读取
pg_stat_activity、pg_locks与 wait event; - 使用
pg_stat_database、pg_stat_io、pg_stat_wal、pg_stat_checkpointer和pg_stat_archiver; - 解释累计计数、瞬时状态、估算值和进度视图的不同时间语义;
- 区分 WAL distance、时间 lag 与 commit-correlated freshness;
- 观察 autovacuum、冻结年龄、dead tuple、对象增长和维护进度;
- 正确解释
pg_stat_statements的聚合键、reset、deallocation 与权限; - 解释为什么 normalized query text 仍不能随意进入证据;
- 为慢语句、锁等待、临时文件和错误日志设置有界政策;
- 评估
auto_explain的ANALYZE、timing、采样和参数泄露成本; - 把第 24 章 SLO 合同变成 multiwindow、multi-burn-rate 规则;
- 区分 page、ticket、diagnostic 与 proposed test route;
- 为 alert 的
for、分组、抑制、恢复和缺失语义写测试; - 防止 fast burn、slow burn 与预算工单形成重复风暴;
- 防止 metamonitoring 抑制独立用户症状或正确性告警;
- 理解 Pigsty v4 的 VictoriaMetrics、VictoriaLogs、VictoriaTraces、 VMAlert、Alertmanager、Grafana、pg_exporter 与 Vector;
- 用
cls、ins、ip、database 与 queryid 在不同粒度间下钻; - 从仪表盘回到 PostgreSQL SQL、日志和主机事实复核;
- 自动保存有界、私密、可复验的诊断包;
- 区分首发症状、相关现象、候选机制与根因;
- 限制诊断查询的 timeout、并发、结果量和权限;
- 用隔离时间序列验证 pending、firing、recovery 与 missing;
- 用空 receiver 离线验证路由,不触碰真实 pager;
- 输出覆盖矩阵,诚实标出尚未实现的应用 SLI;
- 对当前沙箱给出“机制通过、生产待决”的可审计结论。
本章不做什么
本章不是一个“复制几十条 PromQL 就上线”的规则包,也不会:
- 把当前沙箱阈值包装成所有生产环境的通用答案;
- 修改在线 VMAlert、Alertmanager、Grafana 或 PostgreSQL;
- 向在线 Alertmanager 提交合成告警;
- 接入 webhook、邮件、短信、Slack 或真实 pager;
- 运行
EXPLAIN ANALYZE、压测、统计 reset 或数据库故障注入; - 导出 query text、bind value、日志正文、client address 或凭据;
- 用
pg_up=1证明订单服务可用; - 用
pg_lag=0证明 read-your-writes; - 用
failed_count>0直接证明归档仍在失败; - 用“当前无告警”证明通知链可达;
- 用一次仪表盘相关性宣布 root cause;
- 声称
pg36_shop已经具有真实应用埋点。
实验使用 pg36_shop 这一 synthetic teaching service。应用层五种信号仍是刻意
保留的缺口:
request outcome counter
request duration histogram
commit-correlated freshness probe
domain reconciliation gauge
restore-evidence age gauge缺口不是失败的写作,而是本章必须保留的事实。如果没有应用事件,平台不能从 数据库组件指标“推算”出一个看似完整的用户 SLO。
从监控到可观测诊断
监控回答已知问题
监控通常从一个已知条件出发:
if bad_ratio_1h > threshold
and bad_ratio_5m > threshold
for 2m
then page它适合稳定、可计算、可自动执行的问题:
- SLO 是否快速燃烧;
- exporter 是否持续不可达;
- 规则是否持续报错;
- 恢复证据是否超过政策期限;
- 容量预测是否进入评审窗口。
可观测诊断解释未知状态
诊断从“不知道为什么”出发,需要沿不同证据层缩小假设:
user latency burn
-> entry queue or rejection?
-> pool saturation or connection churn?
-> PostgreSQL active wait or lock?
-> queryid cost or plan drift?
-> storage, WAL, checkpoint, vacuum or host constraint?可观测性不是一个产品名,也不是“拥有 logs + metrics + traces”自动获得的属性。 它要求系统输出足够的、语义明确的证据,让操作者能区分多个竞争解释。
诊断不等于根因
本章采用四层语言:
| 层次 | 可以说什么 | 例子 |
|---|---|---|
| 首发症状 | 最早被可靠观察到的服务偏离 | availability fast burn 先触发 |
| 伴随现象 | 与症状同窗出现 | pool queue、lock wait 同时升高 |
| 候选机制 | 现象与某机制一致 | 长事务可能阻止 vacuum 推进 |
| 根因证据 | 机制被复现/独立证实,反例被排除,修复验证闭环 | 释放特定锁后等待消失且合成路径恢复 |
“两条线一起升高”最多是相关性。要升级为根因,至少需要:
mechanism
independent corroboration or reproduction
falsification attempts
repair verification四层问题,而不是四套孤岛面板
本章把信号按问题分为四层:
| 层 | 主要问题 | 首选事实 |
|---|---|---|
| 用户 | 旅程是否成功、及时、正确、足够新鲜 | eligible events、合成探针、domain reconciliation |
| 入口 | 请求在哪排队、被路由、重试或拒绝 | 应用 edge、HAProxy、PgBouncer |
| 数据库 | PG 状态能否解释症状 | activity、locks、I/O、WAL、maintenance、queryid |
| 主机 | 资源或基础设施是否构成约束 | CPU、memory、disk、network、clock |
从下往上推断很危险:
CPU 90%
therefore users are slow # 不成立
one replica is down
therefore service is unavailable # 不成立
pg_up == 1
therefore orders are correct # 不成立从上往下诊断更稳健:
user symptom is real
-> locate affected operation and path
-> correlate entry and database evidence
-> test competing mechanisms
-> choose the least harmful action
-> verify user and control signals正确性与恢复就绪又是特殊控制:
one unexplained cross-tenant row
cannot be averaged away
old or missing restore evidence
cannot be replaced by backup job success四种信号,各有边界
| 信号 | 擅长 | 不擅长 | 必须声明 |
|---|---|---|---|
| metric | 趋势、比率、聚合、规则 | 高维上下文、单请求故事 | type、unit、label、reset、missing |
| log | 离散事件、错误上下文、状态迁移 | 完整总体比率、无界扫描 | schema、采样、脱敏、保留 |
| event | 发布、切换、配置和所有权时间线 | 单独证明因果 | actor、target、result、clock |
| trace | 单次跨组件路径 | 未采样总体、长期预算 | sample、baggage、PII、correlation |
四者不是竞争关系:
metric detects
event bounds the change window
trace follows one affected request
log explains a discrete failure
SQL verifies PostgreSQL state同样,也不应强迫每个问题都使用四种信号。一个能够由累计计数精确回答的问题, 不需要先扫描全部日志;一个需要参数上下文的问题,也不应把 error text 做成 metric label。
时间语义比数值更重要
观察数据至少有五种时间性质:
| 类型 | 示例 | 典型陷阱 |
|---|---|---|
| 当前状态 | pg_stat_activity.state | 一次采样漏掉短暂事件 |
| 累计计数 | pg_stat_database.xact_commit | 把总数当速率、忽略 reset |
| 滚动窗口 | rate(counter[5m]) | 窗口过短、采样不足 |
| 估算值 | n_dead_tup | 当成精确 bloat |
| 当前进度 | pg_stat_progress_vacuum | 没有行不等于从未运行 |
还要处理采集链延迟:
database state time
-> exporter scrape time
-> storage ingestion time
-> rule evaluation time
-> route grouping delay
-> receiver delivery time如果数据源有意延迟 30 秒,而规则在“当前时刻”查询,最新样本可能尚未可见。 VMAlert 支持 evaluation delay;正确值取决于实际采集和存储延迟,不能机械照抄。
本章的规则分层
实验生成 18 条记录规则和 13 条告警规则。它们分成三类:
第 24 章已经接受的七条
| 告警 | 路由 | 目的 |
|---|---|---|
PG36ShopAvailabilityFastBurn | page | 1h + 5m,14.4x |
PG36ShopAvailabilitySlowBurn | page | 6h + 30m,6x |
PG36ShopAvailabilityBudgetTicket | ticket | 3d + 6h,1x |
PG36ShopFreshnessFastBurn | page | commit-correlated freshness |
PG36ShopCorrectnessMismatch | page | 不允许平均稀释的正确性 |
PG36ShopCapacityHorizon | ticket | 经评审预测才进入工作队列 |
PG36MonitoringPathBroken | page | 观察或通知路径不可证明工作 |
仍待治理接受的六条
latency burn
restore evidence stale
active archive risk
long transaction horizon
freeze-age horizon
expected traffic but SLI missing它们有完整规则和测试,但统一标记:
route: test
severity: candidate
governance_status: proposed-not-accepted“代码写好了”不等于“组织接受了 page/ticket 政策”。这个显式不一致检查很重要: 第 24 章定义了 latency SLO,却没有接受 latency alert candidate。本章没有暗中 补齐生产政策,而是把它暴露为待决项。
诊断记录
复制距离、长事务、freeze age、dead tuples、exporter 状态、VMAlert rule error 和 notification failure 首先是诊断或控制输入。它们不会因为“容易写阈值”就 自动变成 page。
当前沙箱的真实快照
正式实验公共摘要:
observability-run.json。
采集时间为 2026-07-29T22:48:21Z。快照只代表该时刻:
| 项目 | 观察值 |
|---|---|
| Pigsty | v4.4.0 |
| PostgreSQL | 18.4 |
| pg_exporter | v1.4.0 |
| VictoriaMetrics | v1.148.0 |
| VictoriaLogs | v1.52.0 |
| VictoriaTraces | v0.9.4 |
| Alertmanager | 0.33.1 |
| VictoriaMetrics series | 44,842 |
| live VMAlert groups | 17 |
| live alert rules | 50 |
| live recording rules | 698 |
| live rule errors | 0 |
| current VMAlert alerts | 0 |
pg_up / pg_exporter_up instances | 4 / 4 |
pg36_shop_* application SLI series | 0 |
目标身份通过三层交叉确认:
host pg-test-1
Patroni scope pg-test
PostgreSQL cluster_name=pg-test
role primary
replication pg-test-2 + pg-test-3, async streaming
observed WAL gap 0 + 0 bytes0 bytes 是当时的发送—回放距离,不是 read-your-writes 证明。
pg_stat_statements 快照:
extension version 1.12
schema monitor
rows 194
calls 122,303
query text exported false
stats reset retained归档快照有一个关键反例:
failed_count 21
last failure 18:57:58Z
last successful archive 22:27:54Z如果规则只是:
pg_archiver_failed_count > 0它会在系统已经恢复后永久报警,直到统计被重置。候选规则因此同时检查:
15m 内出现新失败
AND 最近成功归档已经停滞再回到 pgBackRest 与恢复证据复核。累计 counter、当前故障和恢复就绪是三个 不同结论。
实验为什么分成在线与隔离两部分
在线只读基线
在线部分只做:
- HTTP health/API/metrics 读取;
- VictoriaMetrics 即时查询;
- 通过元节点进入真实
pg-test-1; - 带
statement_timeout=5s、lock_timeout=500ms的只读 SQL; - 聚合 activity、locks、I/O、WAL、checkpointer、archiver、
replication 和
pg_stat_statements; - 记录版本、reset、freshness 与缺口。
不会 reset、reload、写表、运行计划、制造负载或读取 query text。
隔离规则与路由
规则文件上传到沙箱元节点的:
/tmp/pg36-ch25.XXXXXXXX随后:
vmalert -dryRun检查规则语法;vmalert-tool启动 loopback-only VictoriaMetrics;- 注入合成时间序列;
- 验证 normal、pending、firing、recovery 和 missing;
amtool check-config检查 Alertmanager 配置;- 用八组标签离线解析到空 receiver;
- 用五个用例验证抑制边界;
- 清理临时目录并确认目录不存在。
它不会接触在线 VMAlert 或在线 Alertmanager。
本章目录
25.1 从问题选择可观测信号
25.2 PostgreSQL 核心运行信号
25.3 SQL 可观测基线
- 25.3.1
pg_stat_statements的统计口径与重置 - 25.3.2 慢语句、锁等待、临时文件与错误日志
- 25.3.3
auto_explain的采样、嵌套语句与开销 - 25.3.4 日志不得泄漏密码、令牌和敏感参数
25.4 把观察契约变成告警
25.5 Pigsty 可观测体系
25.6 从告警到诊断包
25.7 实战:实现并演练观察契约
官方资料
本章技术语义优先回到原始文档:
- PostgreSQL 18 Monitoring Database Activity
- PostgreSQL 18 Cumulative Statistics
- PostgreSQL 18
pg_stat_statements - PostgreSQL 18
auto_explain - PostgreSQL 18 Error Reporting and Logging
- PostgreSQL 18 Routine Vacuuming
- Pigsty PostgreSQL Monitoring
- Pigsty PostgreSQL Dashboards
- Pigsty pg_exporter
- VictoriaMetrics VMAlert
- VictoriaMetrics vmalert-tool
- Prometheus Alerting Rules
- Prometheus Unit Testing Rules
- Alertmanager Configuration
下一章 第 26 章 容量规划与压测基线 会在这些观察 语义之上建立需求模型、容量水位和可比较基线;第 28 章 VACUUM、冻结与膨胀治理 再深入维护信号。第 31 章把本章的诊断包作为故障排查入口,处理慢查询、锁、 连接、复制与磁盘等具体事件。
上一章:纲举目张:SLO、SOP 与组织治理 · 返回下卷导读 · 下一章:胸有成竹:容量规划与压测基线 · 查看全书目录 · 查看索引中心