25.5 Pigsty 可观测体系
Pigsty 提供的是一套 PostgreSQL 可观测参考实现,而不是另一套数据库语义。
PostgreSQL system views
-> pg_exporter metrics
-> VictoriaMetrics time series
-> recording/alert rules
-> Grafana dashboard
-> Alertmanager route
PostgreSQL / PgBouncer / Patroni / pgBackRest / host logs
-> Vector
-> VictoriaLogs
-> Grafana exploration
application traces, when instrumented
-> VictoriaTraces
-> Grafana exploration每一层都可能:
-正常工作; -延迟; -丢数据; -标签漂移; -权限不足; -版本升级; -将一个原生值重新聚合; -把缺失误写成零。
所以“Pigsty 面板显示”仍要回到 PostgreSQL 和应用合同复核。
当前官方入口:
25.5.1 采集、存储、规则、面板与通知链
metrics 采集
Pigsty PostgreSQL 监控主要汇集:
PostgreSQL pg_exporter, usually 9630
PgBouncer exporter, usually 9631
Patroni REST/metrics, usually 8008 or HTTPS target
Node node_exporter, usually 9100
HAProxy exporter/stats
other infra etcd, Vector, Grafana, Alertmanager, storage self metrics实际端口、TLS 和访问控制以 inventory/rendered config 为准,不能把教学默认值 当网络策略。
沙箱 pg-test-1 的只读探测:
pg_exporter PostgreSQL 9630
pg_exporter PgBouncer 9631
Patroni API 8008
node_exporter 9100探测 endpoint 可证明 process/HTTP 返回,不能证明:
-所有 SQL collector 成功; -所有 database 被发现; -权限足够; -series 新鲜; -rule 查询正确; -用户服务健康。
target registration
Pigsty 文档中的 PostgreSQL target 文件沿用:
/etc/prometheus/targets/pgsql/命名不意味着当前存储一定是旧版 Prometheus;Pigsty v4 的当前栈使用 VictoriaMetrics。target 记录:
labels:
cls: pg-test
ins: pg-test-1
ip: 10.10.10.11
targets:
- 10.10.10.11:9630
- 10.10.10.11:9631
- 10.10.10.11:8008这个 external identity 会与 raw exporter metric-specific labels 合并。
raw exporter 与存储后的 label 不同
直接访问 :9630/metrics:
pg_activity_count{datname="test",state="idle"} 1写入 VictoriaMetrics 后还会带:
cls="pg-test"
ins="pg-test-1"
ip="10.10.10.11"
instance="10.10.10.11:9630"
job="pgsql"因此调试 label 漂移要分别看:
- exporter raw output;
- target/relabel config;
- storage series;
- recording result。
只看一层可能误判 producer。
pg_exporter 是 SQL 到 metric 的编译层
它的配置定义:
query
minimum PostgreSQL version
timeout
cache
tag columns
metric columns
type
description
scale同一个 view 可以变成多条 metric。升级 PostgreSQL/pg_exporter/Pigsty 后:
-列可能增加; -metric 名可能变化; -tag 可能变化; -旧 dashboard/rule 可能失配; -权限 schema 可能变化。
生产需要 versioned config 和 compatibility test。
exporter 内建最小信号
pg_exporter 即使不加载大量自定义 collector,也有基本自描述/连通信号,例如:
pg_up
pg_version
pg_in_recovery
pg_exporter_build_info它们适合判断:
- exporter process/target;
- database connectivity;
- server version;
- recovery role。
pg_up=1 不证明所有高成本 collector、扩展 view 或 application database 可读。
management endpoint 要保护
pg_exporter 的管理/配置能力不应无条件暴露给业务网络。即使 /metrics 可被
监控系统读取,也要区分:
scrape read
health read
configuration reload
profiling/debug使用:
-网络 ACL; -reverse proxy auth/TLS; -bind address; -least-privilege service; -管理面关闭或隔离; -access log/audit。
不要把“exporter 没有业务写权限”等同于“管理 endpoint 无风险”。
metrics storage
Pigsty v4 使用 VictoriaMetrics 保存时序。它负责:
- ingest; -time-series index; -MetricsQL/PromQL-compatible query; -retention; -recording result; -rule state相关读写; -API。
本章快照:
VictoriaMetrics version 1.148.0
total series 44,842
total label-value pairs 387,724
distinct metric names 3,078这些不是“监控容量还剩多少”的答案。还要看:
- ingest rate; -data size; -retention; -series churn; -query latency; -cache; -disk; -backup; -self errors; -cardinality trend。
logs storage
Vector 收集:
/pg/log/postgres
/pg/log/pgbouncer
/pg/log/patroni
/pg/log/pgbackrest
host/service logs发送到 VictoriaLogs。沙箱 health/version 证明:
VictoriaLogs v1.52.0 endpoint healthy本章没有读取任何日志 body,因此没有证明:
-所有 source 被采集; -parser 正确; -redaction 正确; -retention 正确; -query role 正确; -incident window 有完整日志。
endpoint health 只是第一层。
traces storage
沙箱有:
VictoriaTraces v0.9.4 endpoint healthy但没有声称 pg36_shop 发出 application span。三件事要分开:
trace backend exists
collector receives data
specific service has complete/useful instrumentation没有第三项,不能在架构图上把 trace 当成已覆盖。
rule evaluation
VMAlert:
-读取规则; -向 datasource 查询; -执行 recording/alert; -remote-write recording/state; -把 alert 发给 Alertmanager; -暴露自监控 API/metric。
快照:
VMAlert version 1.148.0
groups 17
alert rules 50
recording rules 698
group/rule errors 0
current firing alerts 0这些是 Pigsty 已有规则。第 25 章的:
18 recording + 13 alert只经过隔离工具测试,未放进在线 VMAlert。
dashboard
Grafana 将三类 data source 组织为:
PGSQL PostgreSQL metrics
PGCAT PostgreSQL catalog/direct datasource
PGLOG PostgreSQL-related logs当前 Pigsty 文档列出约 26 个 PostgreSQL dashboard,按 overview、cluster、 instance、database 等层级组织。
dashboard 的优势:
-导航与变量; -版本化 panel; -多层关联; -time range; -release annotation; -top-N; -drill-down。
它的边界:
-panel query 可能与告警不同; -变量默认值可能聚合错 scope; -time range/step 改变结果; -downsampling 隐藏 spike; -颜色阈值不等于 SLO; -Grafana cache/query error; -直接 PG datasource 可能与 metric snapshot 不同。
Alertmanager
Alertmanager 负责:
-group; -dedup; -route; -inhibition; -silence; -receiver integration; -repeat。
它不负责决定 expression 是否有业务意义。VMAlert 能成功发送给 Alertmanager, 也不等于外部 receiver 已收到。
快照:
Alertmanager 0.33.1
current alerts 0
notification failure counters nonzero series 0没有 receipt canary,真实 delivery 仍是盲区。
端到端链路的健康层
| 层 | 证据 |
|---|---|
| producer | PostgreSQL view/metric raw output |
| scrape | target up、scrape duration/error |
| ingest | newest sample time、storage health |
| query | exact expression result、error |
| rule | evaluation state/error/duration |
| notifier | VMAlert notifier success/error |
| route | Alertmanager matched receiver |
| integration | external API accepted |
| receipt | human/system acknowledgment |
“面板有数据”通常证明到 query;“Alertmanager 无失败”最多证明部分 notifier/ integration 路径;receipt 需要独立 canary。
Pigsty 三种监控模式
当前文档:
| 模式 | 场景 | 可见能力 |
|---|---|---|
| RDS / Basic | 只有可连接 PGURL | PG metrics,缺 host/pool/LB/log |
| Managed | 现有数据库且可 SSH/sudo | PG + node,其他可选 |
| Full / Standard | Pigsty 创建并管理 | PG/pool/LB/node/log 完整参考栈 |
这直接影响诊断:
RDS mode has no node metrics
-> cannot conclude host normal from absent panel
RDS mode has no local PG logs
-> PGLOG absence is expected capability gap
Managed optional pool
-> check inventory before diagnosing queuedashboard 应根据 capability 隐藏/标记 unavailable,而不是显示绿色零。
平台版本是合同的一部分
本章快照:
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旧教程若仍写 Prometheus、Loki 等历史组件,不能直接套用 v4。规则语法具有兼容 目标,但 storage、API、自监控 metric 和运行特性必须按实际版本核对。
25.5.2 以指标语义定位集群、实例、数据库和查询
三个稳定基础身份
Pigsty 使用:
cls cluster
ins instance/member
ip node address同一个:
cls=pg-test
ins=pg-test-1
ip=10.10.10.11可关联 PostgreSQL、PgBouncer、Patroni、node、HAProxy 与 logs。
它们解决的是平台身份,不自动解决业务身份:
service
environment
operation_class
objective_id需要应用层单独提供。
为什么同时保留 cls、ins、ip
| label | 用途 | 变化风险 |
|---|---|---|
cls | 服务集群聚合 | cluster rename/migration |
ins | 稳定成员角色 | rebuild/replacement |
ip | node/网络关联 | IP 重用/迁移 |
IP 不是唯一永久身份;instance 也可能重建。诊断包同时保存 topology event 和 captured_at。
instance 与 exporter endpoint
storage series 还有:
instance="10.10.10.11:9630"
job="pgsql"这个 instance 是 scrape target endpoint,不一定等于 Pigsty ins。写 query
时明确:
sum by (cls, ins, ip) (...)不要误用 Prometheus convention 的 instance 代替 Pigsty member identity。
cluster 级
常见问题:
-集群是否有 primary; -多少 member exporter 可达; -transaction/WAL 总 workload; -aggregate capacity; -replication topology; -entrypoint health。
查询示意:
min by (cls) (pg_up)
sum by (cls) (rate(pg_db_xact_total[5m]))
max by (cls) (pg_lag)第一条 min(pg_up) 只是“是否每个目标 up”,不是 service availability。
instance 级
常见:
role
activity/wait
checkpointer
I/O
WAL/archive
replication sender/receiver
autovacuum
host resource本章现场:
pg_in_recovery{cls="pg-test"}可区分:
pg-test-1 0 primary
pg-test-2 1 replica
pg-test-3 1 replica但角色应与 Patroni、direct SQL 和 topology event 交叉,特别是在切换窗口。
database 级
raw exporter:
pg_activity_count{datname="test",state="idle"}
pg_db_deadlocks{datname="test"}
pg_db_temp_bytes{datname="test"}storage 加平台身份后,可以:
sum by (cls, datname, state) (
pg_activity_count
)database label 是 logical database 名;多个 cluster 可能都有 postgres 或
test,不能丢 cls。
query 级
现场 pg_query_calls:
pg_query_calls{
datname="postgres",
query="-1567903771303523871"
} 214这里 query 的值是 numeric queryid 字符串,不是 SQL text。语义:
metric label name query
metric label value queryid
cardinality bound pg_stat_statements.max per tracking dimensions查询时:
topk(
20,
sum by (cls, datname, query) (
rate(pg_query_exec_time[5m])
)
)具体 metric 名与单位由当前 pg_exporter.yml 定义,使用前查看 HELP 和
dashboard query;不要凭记忆假设 _exec_time 是 counter 还是 seconds。
query label 仍有 cardinality 成本
即使不是 raw text:
-pg_stat_statements.max=10000;
-多个 database/user/toplevel;
-多个 instance;
-旧 series retention;
-query churn;
仍可产生大量 series。current snapshot 的 top label cardinality 中
recording 有 698 个值,也说明 rule identity 自身会形成规模。
需要:
-只保留需要的 query metric; -记录 dealloc; -控制 dynamic SQL shape; -top-N dashboard; -retention; -不要把 queryid 复制到 page grouping。
exact metric names 来自当前 exporter
沙箱 pg_exporter v1.4.0 实际暴露:
pg_activity_count
pg_activity_max_conn_duration
pg_activity_max_duration
pg_activity_max_tx_duration
pg_archiver_failed_count / failed_time
pg_archiver_finish_count / finish_time
pg_checkpointer_timed / req / done
pg_checkpointer_write_time / sync_time / buffers_written
pg_db_numbackends / deadlocks / temp_bytes / xact_*
pg_io_read_bytes / write_bytes / extend_bytes
pg_io_read_time / write_time / fsyncs ...
pg_lag
pg_repl_*
pg_query_calls / exec_time / io_time / rows / blocks / wal_bytes
pg_table_age / n_dead_tup / size / bloat estimates这是版本化现场证据,不是永久 API。升级时用:
curl --fail --silent http://TARGET:9630/metrics仅在受控网络检查 # HELP、# TYPE 与 label,不要把 endpoint 公网暴露。
pg_lag 与 pg_repl_replay_diff
现场:
pg_lag all observed 0
pg_repl_replay_diff two downstream series 0前者可能是 time-like convenience metric,后者是 replay distance;具体实现要 查 exporter SQL。两者都不能代替 commit-correlated SLI。
archiver metric 命名的实现差异
native view:
archived_count
last_archived_time
failed_count
last_failed_timeexporter 观察名:
finish_count / finish_time
failed_count / failed_time规则作者要确认:
-finish_time 是 Unix seconds;
-counter type;
-primary/replica exposure;
-reset;
-last success after failure;
-missing on replica。
不能把 native column 名直接猜成 metric 名。
label join 的显式性
组合两个指标:
A
and on (service, operation_class, environment)
B必须显式声明 join key。默认所有共同 label 会参与匹配;一侧多一个 ins 或
job,结果可能空。
调试步骤:
- 分别查询 A/B;
- 列 label sets;
3.确定语义上应该一对一、多对一还是聚合;
4.先 aggregate;
5.用
on/ignoring; 6.检查重复结果。
不要通过删除 identity 修复 join
错误:
sum(A) / sum(B)它可能跨 cluster/environment 聚合,虽然“有数了”,语义已丢失。
正确做法先确定 service scope,再用相同 bounded dimensions。
scrape freshness
本章正式采集使用:
timestamp(pg_up)
timestamp(pg_exporter_up)
timestamp(vmalert_iteration_total)
timestamp(alertmanager_notifications_failed_total)并计算 newest sample age,要求不超过 180 秒。up=1 但最后样本很旧,不应视为
健康;storage 里旧值可能仍可查询。
current app SLI absence
查询:
count({__name__=~"pg36_shop_.*"}) by (__name__)结果 series 为 0。结论:
application SLI not implemented in live sandbox不是:
zero errors
zero latency
100% availability这一区分贯穿全章。
25.5.3 面板结论回到 SQL、日志与主机事实复核
dashboard 是索引,不是裁判
一个 panel 应能回答:
query expression
data source
scope variables
unit
legend identity
window/step
missing behavior
link to native evidence看不到 query 的 panel 不适合支撑高风险动作。
先检查 dashboard scope
事故前先读变量:
cluster
instance
database
query
time range
timezone
refresh interval常见错误:
-选了 pg-meta 而非 pg-test;
-instance 仍是旧 primary;
-database 选 postgres 而用户在 test;
-time range 不包含 onset;
-browser timezone 与事件 UTC 不同;
-panel 聚合 all instance;
-Grafana repeat panel 隐藏一个 member。
本章 SSH 还遇到一个真实访问路径陷阱:工作站对多个逻辑 IP 的 SSH port
forward 落到同一元节点。只有进入元节点再连接真实沙箱网络,并验证
hostname + Patroni scope + cluster_name,才证明查询了 pg-test-1。
从 availability panel 回到 event
panel:
availability bad ratio 1h / 5m复核:
- source metric 是否存在;
- eligible/good selector;
- event count;
- low traffic;
- release/route;
- missing;
- reconciliation; 8.独立 probe。
如果 app metric series 根本不存在,panel 不应该显示绿色 0。
从 connection panel 回到 activity
panel 显示连接增加:
SELECT
backend_type,
datname,
state,
wait_event_type,
count(*)
FROM pg_stat_activity
GROUP BY backend_type, datname, state, wait_event_type
ORDER BY backend_type, datname, state, wait_event_type;再看:
-PgBouncer client/server/wait; -HAProxy queue/session; -application pool config event; -connection churn log; -transaction age; -max connection headroom。
不要直接提高 max_connections。
从 lock panel 回到 blocker graph
SELECT
a.pid AS waiting_pid,
a.datname,
a.application_name,
a.wait_event,
clock_timestamp() - a.query_start AS wait_age,
pg_blocking_pids(a.pid) AS blockers
FROM pg_stat_activity AS a
WHERE cardinality(pg_blocking_pids(a.pid)) > 0
ORDER BY a.query_start;然后在受限会话按 queryid/application 找 owner。panel 的 lock count 不足以
授权 terminate。
从 I/O panel 回到两个系统
PostgreSQL:
SELECT backend_type, object, context,
sum(read_bytes), sum(read_time),
sum(write_bytes), sum(write_time)
FROM pg_stat_io
GROUP BY backend_type, object, context;主机:
device latency/queue/throughput
filesystem capacity
memory/page cache pressure
other process activity只有两层同窗,才能区分 PG workload 与 host path。
从 WAL/replication panel 回到原生位置
SELECT
application_name,
state,
sync_state,
pg_wal_lsn_diff(sent_lsn, replay_lsn) AS gap_bytes,
write_lag,
flush_lag,
replay_lag
FROM pg_stat_replication;再检查:
-Patroni role/timeline; -receiver; -slot; -WAL generation rate; -read routing; -commit token probe。
不要仅凭 panel 的“lag 0”关闭 freshness incident。
从 archive panel 回到时间顺序
SELECT *
FROM pg_stat_archiver;问:
new failure or historical?
last success after failure?
WAL currently generated?
archive queue progressing?
pgBackRest check?
restore evidence age?沙箱就是 failed_count=21 但后来成功。panel 若只把 total failed 画红,会永久
误报。
从 slow query panel 回到 reset
先看:
SELECT *
FROM monitor.pg_stat_statements_info;再看 queryid 聚合:
SELECT
dbid, userid, queryid, toplevel,
calls, total_exec_time, mean_exec_time,
shared_blks_read, temp_blks_written, wal_bytes,
stats_since, minmax_stats_since
FROM monitor.pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 50;检查:
-reset; -dealloc; -member/failover; -calls vs mean; -track planning/timing; -dashboard delta 算法; -query text 权限。
从 vacuum panel 回到对象与 blocker
SELECT
schemaname,
relname,
n_live_tup,
n_dead_tup,
n_mod_since_analyze,
last_autovacuum,
last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 50;再查:
-progress; -old transaction/xmin; -slot/feedback; -relation size; -freeze age; -autovacuum config; -host I/O。
不要因为 bloat panel 红就执行 rewrite。
从 log panel 回到 pipeline
先验证:
source file exists and advances
Vector source healthy
parse errors
VictoriaLogs ingest/query
time zone
retention
redaction然后限定:
cluster / instance / database
severity or SQLSTATE
time window
row limit本章不导出 body;如果必须查看,在受限界面完成。
面板与规则必须共享 contract
如果 alert:
bad_ratio 1h + 5mdashboard 却画:
5m p99值班无法复核 alert。至少提供:
-exact long/short expression; -event count; -threshold; -pending/firing start; -missing/freshness; -release marker; -rule evaluation error。
用 source link,不复制 payload
alert 携带:
dashboard id
query template id
time range
service/environment而不是把 metric dump、SQL text、log body 全塞进通知。诊断包按权限拉取。
三次复核法
高风险动作前至少三类独立证据:
service symptom
app SLI or independent probe
PostgreSQL fact
native SQL / log / topology
platform/host fact
pool / host / rule engine / change event不是机械凑三条,而是让每条能 falsify 竞争解释。
Pigsty dashboard 的正确使用路径
overview
locate service/cluster and onset
cluster
topology, workload, replication, capacity
instance
role, activity, I/O, WAL, maintenance
database
transactions, tables, query workload
query/catalog/log
focused evidence
native SQL and host
verify before mutation下钻过程中始终保留 time range 和 identity。
平台升级验收
Pigsty/pg_exporter/PG major 升级后:
- inventory/target identity;
- raw exporter HELP/TYPE/labels;
- required metric presence;
- series cardinality;
- recording rule dry run/unit test;
- dashboard no-data/error;
- alert route test;
- native SQL parity;
- log parse/redaction;
- production canary/rollback。
不要以“Grafana 首页能打开”验收监控升级。
本节验收
你应当能解释:
- Pigsty v4 metrics、logs、traces、rules、dashboards、routes 各由谁负责;
- raw exporter label 与 storage external label 为什么不同;
cls、ins、ip与 scrapeinstance的区别;- RDS/Managed/Full 三种模式会缺哪些信号;
pg_query_*的querylabel 为什么是 queryid 而非 text;- exporter endpoint up 为什么不等于所有 collector 正常;
- VictoriaMetrics series count 为什么需要趋势而非单次上限;
- VMAlert 无 error 为什么不等于本章规则已部署;
- Alertmanager 无失败为什么不等于 receiver 已收到;
- trace backend healthy 为什么不等于应用有 span;
- 从 connection、I/O、replication、archive、query、vacuum panel 分别回到什么原生证据;
- 平台升级为什么必须做 metric/rule/dashboard/native parity。
上一节:把观察契约变成告警 · 返回本章目录 · 下一节:从告警到诊断包 · 查看全书目录 · 查看索引中心