Nightingale 集成 PostgreSQL 监控采集:categraf 账号授权、配置详解与内置仪表盘告警实践
Nightingale 通过其采集器 categraf 以普通 client 方式连接 PostgreSQL 实例并拉取监控指标。本指南以仓库中的 PostgreSQL 集成文档 为主体,完整讲解从创建专用监控账号、配置 postgresql.toml 采集实例,到引入内置仪表盘与告警规则的端到端落地过程,读完即可在生产环境快速接入 PostgreSQL 监控,并掌握自定义业务指标查询的扩展方法。
前置准备:创建专用监控账号
categraf 作为独立 client 连接 PostgreSQL 采集指标,出于安全与最小权限原则,建议创建专用监控账号,而不是直接使用超级用户。在 PostgreSQL 中执行如下 SQL:
CREATE USER categraf WITH PASSWORD '<password>';
GRANT pg_monitor TO categraf;
ALTER USER categraf SET default_transaction_read_only = on;
三段语句各自承担明确的职责:
CREATE USER categraf WITH PASSWORD '<password>':创建名为categraf的数据库账号,<password>替换为实际密码;GRANT pg_monitor TO categraf:pg_monitor是 PostgreSQL 内置的预定义角色,授予后可以读取pg_stat_*等监控视图(如pg_stat_activity、pg_stat_database、pg_stat_bgwriter),这是指标采集所需的最小权限集;ALTER USER categraf SET default_transaction_read_only = on:将该账号的默认事务设置为只读,确保即使采集器后续执行了意外 SQL,也不会对业务数据产生写操作,属于纵深防御手段。
注意:pg_monitor 只解决监控视图的读取问题。只有当你在 [[instances.metrics]] 中配置了自定义业务表查询时,才需要额外为对应 schema/table 授予 USAGE 与 SELECT 权限,否则不建议放开更多权限。
配置文件示例与参数详解
Nightingale 仓库中为 PostgreSQL 集成预置了采集配置模板 integrations/PostgreSQL/collect/postgresql/postgresql.toml,将其内容(或下方示例)拷贝到 categraf 的采集配置目录后即可生效。完整示例:
# Read metrics from one or many postgresql servers
# # collect interval
# interval = 15
[[instances]]
## specify address via a url matching:
## postgres://[pqgotest[:password]]@localhost[/dbname]?sslmode=[disable|verify-ca|verify-full]
## or a simple string:
## host=localhost user=pqgotest password=... sslmode=... dbname=app_production
##
## All connection parameters are optional.
##
## Without the dbname parameter, the driver will default to a database
## with the same name as the user. This dbname is just for instantiating a
## connection with the server and doesn't restrict the databases we are trying
## to grab metrics for.
##
# address = "host=localhost user=postgres sslmode=disable"
## A custom name for the database that will be used as the "server" tag in the
## measurement output. If not specified, a default one generated from
## the connection address is used.
# outputaddress = "db01"
## connection configuration.
## maxlifetime - specify the maximum lifetime of a connection.
## default is forever (0s)
# max_lifetime = "0s"
## A list of databases to explicitly ignore. If not specified, metrics for all
## databases are gathered. Do NOT use with the 'databases' option.
# ignored_databases = ["postgres", "template0", "template1"]
## A list of databases to pull metrics about. If not specified, metrics for all
## databases are gathered. Do NOT use with the 'ignored_databases' option.
# databases = ["app_production", "testing"]
## Whether to use prepared statements when connecting to the database.
## This should be set to false when connecting through a PgBouncer instance
## with pool_mode set to transaction.
#prepared_statements = true
模板顶部注释了采集周期选项 interval = 15(单位秒),取消注释即可调整拉取频率。下面逐一说明各参数:
| 参数 | 作用 | 默认行为 / 建议 |
|---|---|---|
address |
PostgreSQL 连接串,支持 URL 与 key=value 两种写法(见下节) | 必填;未指定 dbname 时驱动默认连接与用户名同名的数据库 |
outputaddress |
作为输出指标中 server 标签的自定义名称 |
不填时自动从连接地址生成 |
max_lifetime |
连接的最大存活时长,Go time.Duration 格式 |
默认 "0s" 表示连接永不失效 |
ignored_databases |
显式忽略的数据库列表 | 不配置时采集全部数据库;不可与 databases 同时使用 |
databases |
显式指定要采集指标的数据库列表 | 不配置时采集全部数据库;不可与 ignored_databases 同时使用 |
prepared_statements |
是否使用预编译语句连接数据库 | 默认 true;经 PgBouncer 且 pool_mode=transaction 时应设为 false |
关于 databases / ignored_databases 的互斥关系,模板注释中反复强调"Do NOT use with",两者只能二选一,否则配置含义冲突会导致不可预期的采集范围。默认采集全部数据库时,通常会配合 ignored_databases 排除系统库 postgres、template0、template1 以减少无效指标与标签基数。
address 的两种连接写法
address 支持两种等价的连接串格式:
# 1) URL 形式
address = "postgres://pqgotest:password@localhost/app_production?sslmode=disable"
# 2) key=value 形式
address = "host=192.168.11.181 port=5432 user=categraf password=<password> sslmode=disable"
URL 形式的完整模板为 postgres://[user[:password]]@host[/dbname]?sslmode=[disable|verify-ca|verify-full];key=value 形式支持 host、port、user、password、sslmode、dbname 等参数,全部连接参数均为可选项。sslmode 的取值对应 PostgreSQL 的标准安全等级:disable(不加密)、verify-ca(校验 CA)、verify-full(校验 CA 且校验主机名),内网环境常用 disable 以降低开销,公网或跨机房传输建议至少 verify-ca。
有一点容易误解:连接串里的 dbname 只用于建立初始连接,并不会限制采集的数据库范围。采集哪些库由 databases / ignored_databases 决定。
自定义业务指标查询
除了内置的 pg_stat_* 指标,集成模板还支持通过 [[instances.metrics]] 自定义 SQL 查询,将任意业务指标纳入采集。以统计各会话状态的连接数为例:
[[instances.metrics]]
measurement = "sessions"
label_fields = [ "state" ]
metric_fields = [ "value" ]
timeout = "3s"
request = '''
SELECT COALESCE(state, 'unknown') AS state,
COUNT(*)::double precision AS value
FROM pg_stat_activity
GROUP BY COALESCE(state, 'unknown')
'''
各字段含义:
measurement:指标名,即写入时序库的 measurement/指标前缀;label_fields:SQL 结果中作为标签(label)输出的列名,此处state会成为指标标签;metric_fields:SQL 结果中作为指标值的列名,此处value为数值;timeout:单次自定义查询的超时时间,防止慢 SQL 阻塞采集;request:要执行的 SQL。注意示例中对state使用了COALESCE(..., 'unknown')兜底,并把COUNT(*)显式::double precision转为浮点,避免空值与整型除法影响指标质量。
当自定义查询涉及业务表时,才需要额外授予对应 schema/table 的 USAGE 与 SELECT 权限,这与前文账号授权一节相呼应。
采集指标的输出形态
categraf 采集到的 PostgreSQL 指标以 postgresql_ 前缀写入时序库,且按数据库打上 server、db 标签。结合内置仪表盘 integrations/PostgreSQL/dashboards/postgresql_by_categraf.json 中的查询表达式,可以还原出主要指标族,主要包括两大类:
pg_stat_database 维度(按数据库细分):
postgresql_numbackends:当前连接数;postgresql_blks_hit/postgresql_blks_read:缓存命中/从磁盘读取的数据块数,二者相除即缓存命中率;postgresql_deadlocks:死锁累计次数;postgresql_conflicts:与恢复冲突被取消的查询次数(仅备库出现);postgresql_xact_commit/postgresql_xact_rollback:提交/回滚事务数;postgresql_tup_returned/postgresql_tup_fetched/postgresql_tup_inserted/postgresql_tup_updated/postgresql_tup_deleted:查询扫描行数、返回行数与增删改行数;postgresql_temp_files/postgresql_temp_bytes:临时文件数量与字节数;postgresql_blk_read_time/postgresql_blk_write_time:读写数据文件耗时(需要track_io_timing=on才有意义)。
pg_stat_bgwriter 维度(实例级):
postgresql_checkpoints_timed/postgresql_checkpoints_req:超时触发的检查点次数 / 因 WAL 达到max_wal_size或手动触发的检查点次数;postgresql_checkpoint_write_time/postgresql_checkpoint_sync_time:检查点写入 page cache 与 fsync 落盘耗时;postgresql_buffers_checkpoint/postgresql_buffers_clean/postgresql_buffers_backend/postgresql_buffers_backend_fsync:checkpoint、bgwriter、backend 进程写入的数据块数及 backend 的 fsync 次数。
仪表盘 JSON 中为每个面板都写了指标解读(如"returned 远大于 fetched,代表查询效率低,存在全表扫描,应增加索引"),对应的多语言词条维护在 integrations/PostgreSQL/i18n/en_US.json,可作为指标语义的权威参考。
快速接入:内置仪表盘与告警规则
集成目录下预置了可直接导入使用的仪表盘与告警规则,无需从零编写 PromQL:
-
仪表盘 integrations/PostgreSQL/dashboards/postgresql_by_categraf.json:名称为
postgresql by categraf,包含"连接数、缓存命中率、死锁数、冲突数、事务统计、数据查询统计、数据更新统计、生成临时文件统计、数据库读写时间统计、checkpoint 分布、checkpoint 写文件时间分布、数据块写入分布"等面板,提供datasource、server、db三个模板变量,导入后选择 Prometheus 数据源即可按实例和数据库筛选。 -
告警规则 integrations/PostgreSQL/alerts/postgresql_by_categraf.json:内置 5 条基于 PromQL 的告警,默认
disabled=1(导入后需手动启用):
| 告警名称 | PromQL | 触发条件说明 |
|---|---|---|
| Postgresql down | postgresql_up!=1 |
实例不可达/进程异常 |
| posgresql读取时间过高 | rate(postgresql_blk_read_time[5m]) > 100 |
读盘耗时过高,通常意味着内存不足 |
| postgresql写入时间过高 | rate(postgresql_blk_write_time[5m]) > 100 |
写盘耗时过高,cache 偏小或 IO 尖峰 |
| postgresql有死锁 | increase(postgresql_deadlocks[10m]) > 0 |
10 分钟内出现死锁 |
| Postgresql缓存命中率低于50% | rate(postgresql_blks_hit[5m])*100/(rate(postgresql_blks_hit[5m])+rate(postgresql_blks_read[5m])) < 50 |
缓存命中率跌破 50% |
这些规则的评价周期为 30s(prom_eval_interval),持续 60s 触发(prom_for_duration),并携带 annotations.action 处置建议。例如"缓存命中率低于 50%"的处置动作包括:排除实例刚重启导致的缓存冷启动、用 pg_stat_statements 按 shared_blks_read 排序找出读盘最多的 SQL 补索引、将 shared_buffers 调至物理内存的 25% 左右、错峰执行大表全量扫描任务;"读/写时间过高"则要求先确认 SHOW track_io_timing 为 on(否则指标恒为 0),并配合 iostat -x 1 排查磁盘是否打满。这些处置建议同样在 i18n/en_US.json 中提供了英文对照,可直接作为告警通知模板内容。
集成机制的实现原理
理解上述文件如何生效,有助于排查"配置了却没数据"的问题。Nightingale 服务启动时由 center/integration/init.go 扫描 integrations 目录:每个子目录作为一个组件(component.Ident),读取其 icon 目录作为 Logo、读取 markdown/README.<lang>.md 作为组件文档、读取 dashboards、alerts 目录下的 JSON 注册为内置仪表盘与告警规则,i18n 目录下的 JSON 则作为多语言词条表(中文原文 + 英文翻译),最终写入内置 payload 库,供用户在页面上导入使用。这就是本文所讲 README、仪表盘、告警规则能直接出现在 Nightingale 平台集成中心的底层原因。
另一方面,采集到的 postgresql_* 指标进入时序库后,在 Nightingale 中还可以通过内建的 PostgreSQL 数据源(类型标识 pgsql,实现位于 datasource/postgresql/postgresql.go)直接对 PostgreSQL 执行查询:该插件支持 ShowDatabases/ShowTables 元数据浏览,QueryData/QueryLog 执行任意 SQL 并返回时序或日志结果,查询支持 $__ 时间宏替换(如 $__timeFilter),SQL 中的库名会被自动规范化为 "dbname".schema.table 形式以兼容 PostgreSQL 的大小写语义。注意这一数据源插件与本文的 categraf 采集链路是两个独立模块——前者面向"用 PostgreSQL 存监控查询数据",后者才是"监控 PostgreSQL 本身",两者可同时启用、互不冲突。
总结
接入 PostgreSQL 监控的完整链路为:建账号(pg_monitor + 只读)→ 配置采集(address/databases/ignored_databases)→ 可选自定义 SQL 指标 → 导入内置仪表盘与告警规则。仓库中的 README、采集模板、仪表盘 与 告警规则 构成了开箱即用的完整闭环,用户只需按本文完成账号授权与配置替换,即可获得覆盖连接数、事务、缓存、checkpoint、死锁等核心维度的 PostgreSQL 可观测能力。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.24 K638- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python670
SlideSCIPPT插件,支持素材库、AI助手、一键添加图片标题,复制粘贴位置、一键图片对齐、一键插入Markdown(加粗、超链接等行内样式、代码块、LaTeX等块级样式)、便捷导出图片!C#230
hello-agents📚 《从零开始构建智能体》——从零开始的智能体原理与实践教程Python52874
new-apiAI模型聚合管理中转分发系统,一个应用管理您的所有AI模型,支持将多种大模型转为统一格式调用,支持OpenAI、Claude、Gemini等格式,可供个人或者企业内部管理与分发渠道使用。🍥 A Unified AI Model Management & Distribution System. Aggregate all your LLMs into one app and access them via an OpenAI-compatible API, with native support for Claude (Messages) and Gemini formats.Go22545
JeecgBoot🔥企业级低代码平台集成了AI应用平台,帮助企业快速实现低代码开发和构建AI应用!前后端分离架构 SpringBoot,SpringCloud、Mybatis,Ant Design4、 Vue3.0、TS+vite!强大的代码生成器让前后端代码一键生成,无需写任何代码! 引领AI低代码开发模式: AI生成->OnlineCoding-> 代码生成-> 手工MERGE,显著的提高效率,又不失灵活~Java36351