pg_exporter 1.5.0 配置参数详解
pg_exporter 1.5.0 YAML 配置体系逐项详解:五级探测顺序与目录合并、96 个默认采集器字段全集(ttl/timeout/版本边界/fatal/skip/tags 调度/usage 五取值/谓词查询)、官方全量配置在 PG16 的真实规划实测与三档生产配置模板。
pg_exporter 1.5.0 配置参数详解
目标:把 pg_exporter 1.5.0 的 YAML 配置体系逐项讲透:配置文件的探测顺序与目录合并规则、96 个默认采集器的字段全集(标识/缓存/超时/版本边界/fatal/skip/tags 调度/metrics 列声明/谓词查询)、官方默认配置在 PostgreSQL 16 上的真实规划结果,以及三档可直接落地的生产配置模板。全部结论基于官方随附配置文件逐行解析与真实库实测(运行环境与实测端口见第一章),报错回显均为真实输出。
一、环境信息
本文实测环境与依据(查询/实测日期 2026-11-01):
- 操作系统:Ubuntu 24.04 LTS(x86_64)
- pg_exporter:1.5.0(官方镜像
pgsty/pg_exporter:1.5.0+ GitHub Release tarball 二进制pg_exporter v1.5.0 (built with go1.27.3 on linux/amd64),--version实测回显) - 被监控数据库:PostgreSQL 16.15(官方镜像
postgres:16,模拟端口 8134 → exporter 9630 的 Docker Compose 栈,部署方法见 《pg_exporter 1.5.0 Docker Compose 部署指南》) - 解析样本:官方随附默认配置
pg_exporter.yml(v1.5.0 Release 随附,237 KB / 约 3600 行) - 参照文档:官方仓库 README 与随附配置文件头部注释(
config/0000-doc.yml同源,查询日期 2026-11-01)
pg_exporter 的配置哲学是"代码里只有执行引擎,指标本体全部是配置"——本文主角的启动参数(--url/--config/--web.listen-address 等命令行 flags 与 PG_EXPORTER_* 环境变量)属于进程启动层,其逐项实测与 systemd 注入方式见 《pg_exporter 1.5.0 常用 CLI 命令与工具详解》;本文聚焦 YAML 配置文件层:每一条指标 SQL 怎么写、每个字段怎么调度。
二、前置条件
跟读本文的实测操作前,需要具备:
- 一个运行中的 pg_exporter:可按 《pg_exporter 1.5.0 Docker Compose 部署指南》 第四章一键拉起(含
dbtest演示库与demo.yml采集器),下文实测端口8134即该栈的宿主端口;也可用 Release tarball 的裸二进制直接运行(--help回显与各报错实测均来自该二进制)。 - 监控账号:
dbuser_monitor(已授予pg_monitor角色),与部署篇一致,密码q1w2e3r4。 - 官方默认配置文件:从 https://github.com/pgsty/pg_exporter/releases 的 v1.5.0 资产或仓库根目录获取
pg_exporter.yml(本文所有"官方默认值"统计都基于该文件逐行解析)。 - curl:验证指标端点与统计端点用。
三、参数查看与修改方式
pg_exporter 没有配置中心与管理界面,全部配置收敛为"一个 YAML 文件(或目录)+ 启动参数"。本章给出配置从哪来、怎么改、怎么验证生效的完整闭环。
3.1 配置文件的五级探测顺序
pg_exporter 按固定优先级定位配置文件(来源:官方随附 pg_exporter.yml 头部 "Config File" 一节原文,查询日期 2026-11-01):
- 命令行参数:
--config=<config path> - 环境变量:
PG_EXPORTER_CONFIG=<config path> - 当前目录:
pg_exporter.yml - 根配置文件:
/etc/pg_exporter.yml - 根配置目录:
/etc/pg_exporter/
也就是说,裸跑 pg_exporter 不带任何参数时,它会依次探测 3→4→5;用 systemd(RPM/DEB 包安装)时,/etc/default/pg_exporter 里预设的 PG_EXPORTER_CONFIG=/etc/pg_exporter.yml 生效(第 2 级)。生产建议显式传 --config,让配置来源在进程日志中可追溯——启动日志会记录实际命中的级别(实测回显,来自 demo.yml 栈):
time=2026-11-01T03:32:06.822Z level=INFO msg="retrieve config path /etc/pg_exporter/demo.yml from command line"
(from command line 即第 1 级命中;若经环境变量命中,日志显示 from environment。)
3.2 单文件与目录两种形态
--config 接受两种形态(来源:官方 pg_exporter.yml 头部 "Config Format" 一节原文):
- 单文件:一个 YAML 包含一个或多个采集器定义,每个顶层键就是一条采集器;
- 目录:目录下所有 YAML 按文件名字母序合并为一份逻辑配置。
目录形态是官方仓库自身的维护方式:config/ 目录下 58 个采集器定义文件(0110-pg.yml、0310-pg_size.yml……)由 make conf 合并出单文件 pg_exporter.yml。生产中把"官方默认集 + 本地自定义集"分文件管理时,目录形态免维护合并顺序——字母序即加载序,自定义文件放最后(如 999-custom.yml)即可覆盖同名定义。
3.3 修改配置的三种生效途径
改完 YAML 后必须显式生效,三种途径(按推荐序):
-
热重载端点(推荐):
curl -X POST http://<exporter>:9630/reload,零中断重规划。实测(demo.yml 追加新采集器后):server reloaded [HTTP 200]同时日志出现
server reloaded, 3 queries applied,新指标立即出现在/metrics(完整实测过程见部署篇 8.2 节)。 -
重启进程:Docker 形态
docker compose restart exporter;systemd 形态systemctl restart pg_exporter。适合连接串等启动参数级变更。 -
启动时校验:
--dry-run参数解析并打印配置后退出,用于上线前语法检查(报错形态实测见 5.7 节)。
3.4 运行时查看配置的两个端点
pg_exporter 自带两个"看配置"的 HTTP 端点(均在 9630 端口下):
-
GET /stat:查看每条采集器的执行统计(次数/缓存命中/错误/跳过/指标数/TTL/耗时)。实测回显(demo.yml 栈):name total hit error skip metric ttl/s duration/ms demo_db 4 3 0 0 2 21 1.164441 demo_uptime 4 3 0 0 1 1 0.173402列解读:
total抓取请求次数、hit缓存命中次数(demo_db 的 TTL 30 秒内 4 次请求命中 3 次,缓存省掉了 75% 的 SQL 执行)、error/skip计数、metric该采集器产出的指标数、ttl/s缓存秒数、duration/ms最近一次执行耗时。 -
GET /explain:查看采集规划解释。实测curl http://127.0.0.1:8134/explain返回 HTTP 200、空正文(当前规划无待解释项时的形态);规划结论更直接的来源是启动日志的planned with N queries, X installed, Y discarded行(实测样例见 4.3 节)。
四、参数总览
pg_exporter 的 YAML 配置没有"全局服务段"——每个顶层键就是一条采集器定义,服务监听地址等进程级参数全部走启动参数(见 D1 篇)。本章先给全景规模,再给两张字段总表。
4.1 官方默认配置的全景规模
对 v1.5.0 随附 pg_exporter.yml 逐行解析的实测统计:
| 统计项 | 实测值 | 说明 |
|---|---|---|
| 顶层采集器定义 | 96 个 | 每个顶层键一条定义,与 README "96 collector branches" 口径一致 |
显式 name 命名空间 | 93 条定义声明,去重 56 个 | README 汇报口径为 59 个 namespaces(含未显式命名的分支归组,两种统计口径并存) |
metrics 列声明 | 1176 条 | usage 分布:GAUGE 447 / COUNTER 488 / LABEL 194 / DISCARD 45 / HISTOGRAM 2 |
ttl 配置分布 | 10s×82、60s×9、300s×3、1s×2 | 10 秒是绝对主流(README 建议的 15s 抓取间隔下的合理取值) |
timeout 配置分布 | 未设(默认 100ms)×78、2s×11、1s×7 | 绝大多数依赖 100ms 默认超时 |
min_version / max_version | 96 个全部声明 min / 36 个声明 max | 版本边界是默认配置的基本盘 |
fatal: true | 3 个:pg_primary_only、pg_replica_only、pgbouncer_list | 与官方注释"至少设一条 fatal"的建议一致 |
skip: true | 6 个:pg_origin、pg_shmem、pg_table_bloat、pg_index_bloat、pg_tsdb_hypertable、pg_heartbeat | 默认关停的高成本/需额外权限采集器(pg_heartbeat 同时带谓词查询) |
predicate_queries | 1 个:pg_heartbeat | 谓词查询在默认配置中的唯一实例(样例见 5.6 节) |
tags 声明 | 82 条定义带 tags | 前缀分布:cluster 66 / primary 10 / replica 9 / pgbouncer 12 / extension 7 / schema 3 / dbname 1 |
表解读:两个数字最能说明 pg_exporter 的配置形态——96 条定义全部带 min_version(版本兼容是规划的基本维度,不是可选项),82 条带 tags(绝大多数采集器都声明了自己的调度条件)。默认配置的分组编号规范(官方 "Collector Presets" 一节):1xx 基础指标、2xx 复制、3xx 持久化(大小/WAL/检查点)、4xx 活动(后端/锁/事务)、5xx 进度(vacuum/索引)、6xx 数据库级、7xx 对象级、8xx 可选(默认关闭的重查询)、9xx PgBouncer;其中 100–599 为集群级(每实例抓一次)、600–899 为库级(每库各抓)。
4.2 采集器定义字段总表
一条采集器定义可用的全部字段(字段名后为是否必填):
| 字段 | 必填 | 类型 | 作用 | 默认行为 |
|---|---|---|---|---|
<顶层键> | 必填 | 键名 | 采集器分支名,全配置唯一 | — |
name | 可选 | 字符串 | 指标命名空间(指标前缀) | 缺省取顶层键名;同 namespace 多分支时规划器至多选一条 |
desc | 可选 | 字符串 | 采集器描述(文档作用) | — |
query | 必填 | SQL 块 | 指标查询 SQL,多行块 ` | ` |
ttl | 可选 | 秒 | 结果缓存 TTL | 0/留空 = 不缓存 |
timeout | 可选 | 秒 | 查询超时,超时即取消 | 0/留空 = 0.1(100ms);负数 = 关闭超时 |
min_version | 可选 | 6 位整数 | 支持的最低版本(含边界) | 0 = 不限 |
max_version | 可选 | 6 位整数 | 支持的最高版本(不含边界,[min, max)) | 0 = 不限 |
fatal | 可选 | 布尔 | 该采集器失败即整个 scrape 失败,pg_up 归 0 | false |
skip | 可选 | 布尔 | 规划阶段直接不安装(快捷关停) | false |
tags | 可选 | 字符串数组 | 调度标签(全集见 5.4 节) | 空 = 无条件安装 |
predicate_queries | 可选 | 数组 | 主查询前置谓词(见 5.6 节) | 空 = 不做前置检查 |
metrics | 必填 | 数组 | 返回列声明(见 5.5 节) | — |
💡 技术拓展:监控指标的常见类型不止 GAUGE 一种。Prometheus 指标四类型对比——
类型 语义 典型例子 Gauge 瞬时值,可升可降 连接数、数据库大小、内存占用 Counter 只增不减的累计值(配合 rate()用)查询总数、提交数、死锁次数 Histogram 分桶观测分布 查询耗时分布、事务年龄分布 Summary 客户端侧分位数(不易聚合,Prometheus 生态较少用) Go 运行时的 GC 暂停 pg_exporter 的
usage声明与此对应(GAUGE/COUNTER/HISTOGRAM/LABEL/DISCARD),LABEL 与 DISCARD 是导出器特有的"列角色"标注而非指标类型。默认配置的 1176 条列声明中 COUNTER(488)与 GAUGE(447)几乎对半,符合数据库监控"累计值看速率、瞬时值看水位"的混合需求。
4.3 默认配置的真实规划结果
把官方全量 pg_exporter.yml 挂到真实 PostgreSQL 16.15 上(demo 栈同款环境,监控账号 dbuser_monitor),启动日志给出的规划结果(实测回显,输出节选):
time=2026-11-01T03:42:11.165Z level=INFO msg="server [postgres] planned with 96 queries, 38 installed, 58 discarded, installed: pg_table_size, pg_primary_only, pg_timeline, pg_backup, pg_pubrel, pg_slot_16, … , discarded: pg_sub_19, pg_db_12, pg_db_10, pgbouncer_database_124, … "
time=2026-11-01T03:42:11.221Z level=INFO msg="server [dbtest] planned with 96 queries, 9 installed, 87 discarded, installed: pg_table_size, pg_pubrel, pg_relkind, pg_subrel, pg_func, pg_seq, pg_defpart, pg_table_16, pg_index , discarded: …"
/metrics 全量输出实测 1781 行(demo.yml 最小配置时为 211 行)。逐项解读:
- 96 条定义并不会全部执行——规划器按版本边界、tags、库级别逐条裁决。postgres 主库装上 38 条(
pg_slot_16即 PG16 分支、pg_io_16即 PG16+ 的pg_stat_io),pg_sub_19(PG19 分支)、pg_db_10(PG10 分支)等版本不匹配的分支被丢弃,12 个pgbouncer_*采集器因目标不是 PgBouncer 全部不装。 - 集群级采集器(
cluster标签)只在 postgres 库的 server 上装;库级采集器(表/索引/函数类)在 dbtest 上另装 9 条——两个库各自独立规划。 - 这印证了 README "实际暴露的时序数量取决于 PostgreSQL 版本、启用的采集器、数据库与对象数量" 的说法:同一份 96 条配置,在不同环境装出来的指标集完全不同,且全部由配置字段自动裁决,无需人工开关。
五、核心参数分类详解
本章对每个字段给"语义 + 官方默认 + 实测样例",样例全部摘自官方默认配置或实测环境。
5.1 采集器标识:顶层键、name、desc、query
顶层键是采集器的分支名,全配置唯一;name 是指标前缀(namespace);desc 是纯文档性描述。三者关系看官方默认配置的第一条(pg_primary_only,实测摘录):
pg_primary_only: # 顶层键 = 分支名(全配置唯一)
name: pg # namespace:指标前缀,本条产出 pg_uptime / pg_lsn …
desc: PostgreSQL basic information (on primary)
query: |-
SELECT
extract(EPOCH FROM CURRENT_TIMESTAMP) AS timestamp,
extract(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime,
…
pg_is_in_recovery() AS is_in_recovery,
FALSE AS is_wal_replay_paused;
tags: [ cluster, primary ]
…
关键语义:
- 指标全名 =
<name>_<列名>(列未被rename时)。pg_primary_only的uptime列最终暴露为pg_uptime——这就是 demo.yml 里demo_orders命名空间的rows列变成demo_orders_rows的同一规则。 - 同一 namespace 允许多条分支,规划器保证至多选中一条。官方配置里最典型的就是
pg命名空间的主库/从库双分支:pg_primary_only(tags: [cluster, primary])与pg_replica_only(tags: [cluster, replica])两条定义产出同一组指标名(pg_uptime、pg_lsn……),但 SQL 不同——主库走pg_current_wal_lsn()、从库走pg_last_wal_replay_lsn()。规划器按实例角色自动二选一,Grafana 大盘因此无需关心实例角色。官方注释明确:"It's the user's responsibility to make sure that AT MOST ONE collector is picked for each namespace"——同名分支的互斥条件(如 primary/replica 标签)要作者自己保证。 query用 YAML 块标量(|或|-)承载多行 SQL,以分号结尾;列别名(AS uptime)就是后续metrics段的列名。
5.2 缓存与超时:ttl、timeout
这两个字段控制每条查询的执行成本,是大规模部署下防止监控拖垮数据库的两道闸门。
ttl(缓存 TTL,秒)。语义:查询结果缓存 N 秒,期间 Prometheus 重复抓取直接返回缓存(官方头部注释原文:"TTL has to be smaller than your scrape interval. 15s scrape interval and 10s TTL is a good start for production environment")。实测效果(/stat 回显,demo_db 的 TTL 为 30 秒):
name total hit error skip metric ttl/s duration/ms
demo_db 4 3 0 0 2 21 1.164441
4 次抓取命中 3 次缓存——真实只执行了 1 次 SQL。默认配置的取值分布(10s×82、60s×9、300s×3)体现了分层思想:高频基础指标 10 秒;体积类(pg_size)、bloat 检查类给 60–300 秒(贵查询低频跑);TTL 还被官方用来实现"不同指标不同抓取频率"——Prometheus 匀速抓取,贵查询靠长 TTL 降频。
timeout(查询超时,秒)。语义:超时立即取消查询(防雪崩);默认 0.1 秒(100ms),留空或 0 即取默认,负数关闭超时。官方头部注释同时给出警告:如果所有查询的超时加起来超过抓取/缓存间隔(通常 15s),查询仍可能积压——"or, you can just disable potential slow queries"(关掉慢查询比放大超时更健康)。默认配置中 18 条显式设了 timeout(2s×11、1s×7),全部是已知较慢的对象级统计查询;其余 78 条吃 100ms 默认值。
5.3 版本边界与开关:min_version、max_version、fatal、skip
版本边界。min_version/max_version 用 PostgreSQL 服务器版本号格式:6 位整数 <2位主版本><2位次版本><2位修订>,如 090600 = 9.6、120100 = 12.1、160000 = 16.0。区间左闭右开 [min, max),0/留空表示负无穷/正无穷(官方头部注释 "Version Compatibility" 一节原文)。版本信息来自 pg_exporter 启动时抓取的 pg_version(实测 pg_version 160015 即 16.15)。
默认配置用它实现"一条指标、多版本 SQL":如 pg_checkpointer 家族有 _10(PG10–16 的 pg_stat_bgwriter)、_17(PG17 的 pg_stat_checkpointer)、_18(PG18 新增 num_done/slru_written)三条分支,版本号自动路由。96 条定义全部声明 min_version、36 条另声明 max_version——这是动态规划的底盘。
fatal(致命采集器)。语义:标记 fatal: true 的采集器失败时,整个 scrape 立即失败、pg_up 归 0(告警触发点);非 fatal 采集器失败只累加错误计数、scrape 继续(官方头部注释 "Fatality" 一节原文,并建议"至少设一条 fatal 采集器")。默认配置恰好 3 条:pg_primary_only(主库分支)、pg_replica_only(从库分支)、pgbouncer_list(PgBouncer 场景)——基础信息查询是监控链路的生死线,挂了就该全红。
skip(直接关停)。语义:skip: true 的采集器在规划阶段就不安装(官方注释:"This could be a handy option to disable collectors")。默认配置用 skip 关停 6 条高成本或需额外权限的采集器:pg_origin(需额外权限)、pg_shmem、pg_table_bloat/pg_index_bloat(膨胀估算重查询)、pg_tsdb_hypertable(TimescaleDB 专用)、pg_heartbeat。用户侧最常用的姿势:拷贝官方配置后把不要的采集器加 skip: true(比整段删除更可追溯),或自己的新采集器开发期先 skip: true 灰度。
5.4 调度标签:tags 全集
tags 是动态规划的调度输入,决定"这条 SQL 装到哪些 server 对象上"。全集如下(来源:官方 pg_exporter.yml 头部 "Tags and Planning" 一节原文,逐类配默认配置实例):
| 标签 | 语义 | 默认配置实例 |
|---|---|---|
cluster | 集群级:同一 PostgreSQL 实例只执行一次 | 66 条(pg_primary_only、pg_size…) |
primary / master | 仅主库执行(pg_is_in_recovery() 为 false 时才装) | 10 条(pg_primary_only…) |
standby / replica | 仅副本执行 | 9 条(pg_replica_only…) |
dbname:<名> | 仅指定数据库 | demo_orders_stat 的 dbname:dbtest;官方 pg_heartbeat 的 dbname:postgres |
username:<用户> | 仅指定连接用户时执行 | — |
extension:<扩展> | 仅装了该扩展的库执行 | 7 条(pg_tsdb_hypertable 的 extension:timescaledb…) |
schema:<模式> | 仅该模式存在时执行 | 3 条 |
pgbouncer | PgBouncer 专用采集器族 | 12 条(pgbouncer_list…) |
not:<标签> | exporter 被打上 <标签> 时不执行(负标签/污点) | — |
<自定义标签> | exporter 启动参数带了该标签(--tag)才执行 | — |
规划时机(官方注释原文大意):pg_exporter 连上目标后先采集数据库事实(版本、角色、库清单、扩展、模式),再与每条采集器的 tags 与版本边界匹配,当且仅当完全兼容才安装。B2 部署篇 4.5 节的日志是该机制的最直观实证:
server [postgres] planned with 2 queries, 1 installed, 1 discarded, installed: demo_db_size , discarded: demo_orders_stat
server [dbtest] planned with 2 queries, 1 installed, 1 discarded, installed: demo_orders_stat , discarded: demo_db_size
demo_orders_stat(dbname:dbtest)与 demo_db_size(cluster)在同一份配置下按库自动分流。多环境单配置是 tags 的最大收益:一套配置管住主库/从库/多版本混跑机群,换环境不改配置。
5.5 列声明:metrics 与 usage 五种取值
metrics 数组逐列声明 query 返回结果的处理方式,每列可用字段:
| 字段 | 必填 | 作用 |
|---|---|---|
<列名> | 必填 | 与 SQL 返回列名严格一致(键名即列名) |
usage | 必填 | 列角色,五种取值见下表 |
rename | 可选 | 指标名别名(替代列名参与 <name>_<列名> 拼接) |
description | 可选 | 指标 HELP 文本 |
default | 可选 | 列值为 NULL 时使用的默认值 |
scale | 可选 | 值缩放因子(乘法) |
bucket | 可选 | HISTOGRAM 专用的有限递增桶边界 |
usage 五种取值(来源:官方配置头部 "Collector Example" 注释原文):
| usage | 语义 | 默认配置实例 |
|---|---|---|
GAUGE | 瞬时仪表量 | 447 条(uptime、size_bytes…) |
COUNTER | 累计计数器(只增) | 488 条(xact_commit、blks_read…) |
LABEL | 列值转为指标标签(非数值) | 194 条(datname、usename、state…) |
HISTOGRAM | 每行一个观测,聚合成快照分布 | 2 条(见下文专述) |
DISCARD | 完全忽略该列 | 45 条(辅助列不出指标) |
HISTOGRAM 专述(v1.5.0 的特色能力,官方注释原文要点):从当前 SQL 结果重建快照分布,产出累积的 <name>_bucket{le=…}、<name>_count、<name>_sum Gauge 型序列(快照间可升可降);配合 histogram_quantile() 直接查分位数。官方默认配置的两条实例(pg_xact_age,实测摘录):
# seconds covers every open transaction, including implicit autocommit ones in
# flight, so _count is the current open-transaction count; low buckets absorb
# that healthy churn.
- seconds: { usage: HISTOGRAM ,bucket: [1, 3, 10, 30, 100, 300, 1000, 3000, 10000, 30000, 100000] ,description: "Open transaction age snapshot in seconds" }
# idle_seconds covers the idle-in-transaction subset; capped at 3000s (~50min)
# since anything older is uniformly critical and lands in +Inf.
- idle_seconds: { usage: HISTOGRAM ,bucket: [1, 3, 10, 30, 100, 300, 1000, 3000] ,description: "Idle-in-transaction age snapshot in seconds" }
官方同时给出三条使用纪律:+Inf 桶自动存在、首档有限桶隐含更低值;有符号域要显式配负数边界与 0、不要配 -Inf;禁止对快照 Histogram 序列套 rate()/irate()/increase()(它们是 Gauge 不是 Counter,权威契约见 https://exp.pgsty.com/design/snapshot-histograms/ )。
rename/default/scale 组合实例(官方 pg_io(PG16+ 的 pg_stat_io)实测摘录——毫秒转秒 + NULL 兜底):
- read_time: { usage: COUNTER ,default: 0 ,scale: 1e-3 ,description: "Time spent in read operations in seconds" }
- write_time: { usage: COUNTER ,default: 0 ,scale: 1e-3 ,description: "Time spent in write operations in seconds" }
三字段各司其职:default: 0 把 PG16 早期 pg_stat_io 的 NULL 值兜住,scale: 1e-3 把数据库返回的毫秒折算成秒——单位换算与空值治理都收敛在配置层,SQL 保持原样。
5.6 谓词查询:predicate_queries
谓词查询是主查询的前置开关:在主查询执行前(缓存命中检查之后)运行,全部返回"单行单列布尔 true"才执行主查询;任一返回 false/零行则跳过主查询(不算错误);返回多行、非布尔或报错则整条标记失败(来源:官方配置头部 "predicate queries" 注释原文)。默认配置唯一实例 pg_heartbeat(实测摘录):
pg_heartbeat:
name: pg_heartbeat
desc: monitoring heartbeat in monitor.heartbeat table
predicate_queries:
- name: if heartbeat table exists
predicate_query: |
SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'monitor' AND table_name = 'heartbeat');
query: |-
SELECT id AS cluster_name, extract(EPOCH FROM ts) AS ts, lsn, txid FROM monitor.heartbeat;
ttl: 10
min_version: 090100
tags: [ "dbname:postgres", "schema:monitor" ]
skip: true
…
解读:心跳表 monitor.heartbeat 是 Pigsty 体系的外置依赖,不是每套库都有——谓词查询先探表存在性,避免主查询直接报错刷屏;tags: ["dbname:postgres", "schema:monitor"] 再叠加库与模式两级条件。三层防线(谓词 + 库标签 + 模式标签)+ skip: true 默认关停,是"条件苛刻的可选采集器"的标准写法。适用场景:探测特定函数/表/扩展/厂商特性存在后再跑主查询(如 pg_backup_start_time() 仅 PG14+ 存在)。
5.7 配置校验与报错实录
上线前用 --dry-run 校验配置(解析并打印后退出,不连库不监听)。两种典型错误形态的实测回显(本地 v1.5.0 二进制,./pg_exporter --config=<文件> --dry-run):
错误一:非法 usage 值。错误配置(usage: FOO,五种合法值之外的任意值):
bad_usage_collector:
name: bad
desc: bad usage demo
query: |
SELECT 1 AS v;
metrics:
- v:
usage: FOO
description: wrong usage
实测回显:
time=2026-11-01T11:41:30.418+08:00 level=WARN msg="fail retrieving target url, fallback on default url: postgresql:///?sslmode=disable"
time=2026-11-01T11:41:30.418+08:00 level=INFO msg="retrieve config path e1/bad.yml from command line"
time=2026-11-01T11:41:30.418+08:00 level=ERROR msg="fail loading config e1/bad.yml, query \"bad_usage_collector\" column \"v\" has unsupported usage: FOO"
错误二:metrics 缺失/为空。错误配置(metrics: [] 空数组,另有 SQL 残缺的 query: SELECT 1 AS):
demo_broken:
name: broken
desc: yaml syntax error
query: |
SELECT 1 AS
metrics: []
实测回显:
time=2026-11-01T11:41:30.425+08:00 level=ERROR msg="fail loading config e1/bad2.yml, query \"demo_broken\" has no metrics definition"
两条报错的解读:加载期即失败、拒绝启动(错误信息带采集器名与列名,定位直接);注意第二例——YAML 语法本身合法、SQL 残缺并不在加载期校验(SQL 只有跑起来才知道对不对),加载器检查到的是"没有可用的 metrics 定义"。另外第一例的 WARN 行顺带实证了连接串回退行为:不传 --url/PG_EXPORTER_URL 时回退默认 postgresql:///?sslmode=disable。
⚠️ 注意:配置校验只在启动与 reload 时发生。用
POST /reload热重载一份坏配置时,重载会失败但旧配置继续生效(进程不退),修正后重新 reload 即可——这是热重载相对重启的安全优势。
六、生产配置模板
按三档场景给出可直接改造的模板。模板只示意结构与关键取值,query/metrics 的完整 SQL 从官方 pg_exporter.yml 摘取或按 5.5 节规则自写。
6.1 模板 A:官方全量 + 按需关停(推荐起步,适配 8GB+ 内存数据库服务器)。直接使用官方 pg_exporter.yml(96 采集器,PG16 上实测装出 38 条、/metrics 1781 行),把不要的重查询加 skip:
# 在官方 pg_exporter.yml 尾部追加(或直接修改对应采集器段落):
pg_table_bloat: # 官方默认已 skip;确认保持 skip
skip: true
pg_index_bloat:
skip: true
# 自定义业务指标追加在最后(字母序加载,自定义放文件末尾便于维护)
demo_orders_stat:
name: demo_orders
desc: business table statistics
query: |
SELECT count(*) AS rows, coalesce(sum(amount), 0) AS amount_total FROM demo_orders;
ttl: 5
timeout: 1
tags: [dbname:dbtest]
metrics:
- rows: { usage: GAUGE, description: total rows }
- amount_total: { usage: GAUGE, description: total amount }
适用:想一步到位获得 Pigsty 同款大盘指标面的团队。资源水位:exporter 进程静态单二进制(约 14.3 MB),内存占用在几十 MB 量级;数据库侧压力取决于对象数量与 TTL 设置(默认 10s 主流档)。
6.2 模板 B:最小自定义集(适配低配主机或只想监控核心水位)。不使用官方默认集,完全自写(demo.yml 即此形态,实测 211 行指标):
pg_basic:
name: pg
desc: minimal health set
query: |
SELECT extract(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime,
pg_current_wal_lsn() - '0/0' AS lsn,
(SELECT count(*) FROM pg_stat_activity) AS active_connections;
ttl: 5
timeout: 1
tags: [cluster, primary]
fatal: true
metrics:
- uptime: { usage: GAUGE, description: seconds since start }
- lsn: { usage: COUNTER, description: current wal write location }
- active_connections: { usage: GAUGE, description: total connections }
pg_db_size:
name: pg_size
desc: per database size
query: |
SELECT datname, pg_database_size(datname) AS size_bytes
FROM pg_database WHERE datallowconn AND NOT datistemplate;
ttl: 60
timeout: 1
tags: [cluster]
metrics:
- datname: { usage: LABEL, description: database name }
- size_bytes: { usage: GAUGE, description: database size in bytes }
适用:边缘节点/开发库,或从零自建监控面。要点:第一条设 fatal: true 守住 pg_up 的告警语义;贵查询(size 类)TTL 拉长到 60 秒。
6.3 模板 C:目录形态的多环境单配置(适配多版本混跑机群)。目录结构:
/etc/pg_exporter/
├── 100-base.yml # 官方默认集(从 pg_exporter.yml 拆出或整文件放入)
└── 999-custom.yml # 自定义业务采集器 + skip 裁剪
--config=/etc/pg_exporter/ 指向目录,两文件按字母序合并;主库/从库/PG10–18 混跑机器共用同一份配置(版本边界与 tags 自动分流),每台机器的差异化(如自定义标签过滤)通过启动参数 --tag=prod 配合配置里的 <自定义标签>/not:<标签> 实现。
三档选型建议:先跑模板 A 观察 /stat 的 error 列与数据库侧负载,出现压力再降级到模板 B 或对 A 做减法;模板 C 适合机群规模上去后的配置治理形态。
七、常见问题
7.1 改了配置不生效
现象:改 YAML 后指标不变。定位:pg_exporter 不自动监听文件变化。解决:curl -X POST http://<exporter>:9630/reload(实测回显 server reloaded [HTTP 200])或重启进程;Docker 单文件挂载 + vim"重命名替换"式保存可能导致容器内文件视图断链,此时用 docker compose restart exporter(完整实测见部署篇 8.2 节)。
7.2 reload 后日志报 fail loading config,指标还是旧的
现象:POST /reload 后日志出现 5.7 节同款 fail loading config … ERROR。定位:新配置校验未通过(usage 非法/metrics 缺失/YAML 语法错)。解决:按报错定位行修正后重新 reload;坏配置不会破坏运行中的旧配置。上线前先跑 --dry-run 可提前拦截(5.7 节实录)。
7.3 某条采集器日志报错但 pg_up 还是 1
现象:日志出现单条查询 ERROR(如权限不足、函数不存在),pg_up 仍为 1。定位:该采集器未标 fatal——非致命失败只累加错误计数,scrape 整体仍成功(5.3 节语义)。解决:能修则修(授权/版本分支);确属环境不支持的采集器加 skip: true;属于生死线的基础指标才标 fatal。
7.4 指标名和列名对不上
现象:配置写 rows,指标却是 demo_orders_rows;或预期 checkpoint_write_time 实际是 pg_write_time。定位:指标全名 = <name>_<rename 或列名>——前者是 namespace 前缀规则,后者是 rename 字段生效。解决:按 5.1/5.5 节的命名规则对照;不想带前缀就把 name 设得更短(namespace 同时是多分支互斥的调度单位,改前先确认无同名分支冲突)。
7.5 同一 namespace 的多条分支全被丢弃
现象:日志 discarded 列表里同一前缀的多条分支(如 pg_db_10/12/14/18)全都没装。定位:分支互斥是"至多一条"而非"至少一条"——版本边界全不匹配(如 PG15 上 pg_db 家族的 min_version 均不覆盖 15)时全丢弃是正常行为。解决:确认目标版本号(pg_version 指标)与各分支的 [min, max) 区间;需要覆盖 15 就自写一条 min_version: 150000, max_version: 160000 的分支。
7.6 官方全量配置里找不到某个指标
现象:/metrics 里没有官方文档提到的某指标。定位:三层过滤——版本分支不匹配、tags 不满足(如 bloat 类默认 skip: true)、该指标属库级采集器而当前查看的是集群级 server 的输出。解决:用 /stat 看哪些采集器在跑、启动日志看 installed/discarded 清单(4.3 节实测方法);确认被 skip 的按需改 skip: false 并 reload。
八、参考链接
- 官方仓库与 README:https://github.com/pgsty/pg_exporter (Usage/Collectors 章节与
config/0000-doc.yml文档化采集器,查询日期 2026-11-01) - v1.5.0 随附默认配置:https://github.com/pgsty/pg_exporter/blob/main/pg_exporter.yml (本文全部"官方默认值"统计的解析样本;头部 1–241 行为配置格式权威注释)
- Snapshot Histogram 设计契约:https://exp.pgsty.com/design/snapshot-histograms/ (HISTOGRAM 使用的官方权威文档,README 引用)
- 站内系列篇:认知与选型见 《pg_exporter 1.5.0 介绍与选型指南》;Compose 部署与热重载实测见 《pg_exporter 1.5.0 Docker Compose 部署指南》;命令行参数与 systemd 部署见 《pg_exporter 1.5.0 常用 CLI 命令与工具详解》