这是本节的多页打印视图。 .
设计归档
1 - 把 PostgreSQL CSV 日志转成持久指标
PostgreSQL 日志会记录 SQL 快照可能错过的事件:死锁、认证失败、自动清理取消、检查点、临时文件删除和客户端断连。根据服务端日志策略,还可以记录语句耗时。
状态: 已实现,未发布。
决策日期: 2026-08-24。
最后核验: 2026-10-13。
范围: 源码提交c0ba58a的 PostgreSQL 14+ CSV 日志采集器,默认关闭;稳定版v1.4.1尚未包含。
取代: 独立可观测性产品提案。
交付进度: 本地测试通过;未合入main或发布标签;软件包、部署与生产运行未核验。
本采集器读取一个本地 CSV 日志目录,保存有限的聚合状态,并在 /metrics 暴露 Counter 和 Histogram。原始日志保留在 PostgreSQL 日志文件中。
范围与启用方式
采集器运行在现有 PG Exporter 进程中。指定非空日志目录即可启用:
对应环境变量为 PG_EXPORTER_PG_LOG_DIR、PG_EXPORTER_PG_LOG_STATE_FILE 和 PG_EXPORTER_PG_LOG_POLL_INTERVAL。默认目录为空,状态路径如上,轮询间隔为一秒。
关闭时不创建后台任务、状态锁、状态文件或日志指标,也不增加文件扫描或抓取协调。--dry-run 与 --explain 不启动后台任务。
范围限于本地 PostgreSQL CSV 日志和聚合指标,不包括其他格式、日志发送、查询界面、会话时间线、任意正则表达式或自动根因分析。日志设置仍由 PostgreSQL 配置管理,采集器不提供 pg_log_setting_* 指标。
读取完整 CSV 记录
PostgreSQL 14 到 18 文档采用相同的 26 列 CSV 布局,包含时间戳、进程和会话标识、严重级别、SQLSTATE、消息、应用、后端类型、并行主进程 PID 与查询 ID。
字段可以包含逗号、引号、回车和换行,因此读取器先识别完整 CSV 记录,再解码。逐物理行扫描无法正确处理该格式。
文件末尾尚未写完的记录保持待处理,完整后才提交其偏移量。单条记录上限为 16 MiB。畸形或超大输入触发有界重新同步,并增加解析错误和输入缺口计数。连续结构不匹配会使组件保持不可用,直到恢复有效输入。
文件身份与轮转
后台任务轮询并核对目录。仅靠文件通知无法恢复遗漏事件,也无法在重启后重建状态。
每个游标保存文件身份、代次、路径哈希、字节偏移、大小、内容指纹和读取状态。状态文件不保存明文日志路径。
重命名轮转按文件身份跟踪:读取器继续读完旧文件,为新文件建立游标。文件大小低于已提交偏移时,视为截断,从零开始新代次,并记录轮转和输入缺口。复制后截断可能在轮询发现前丢弃未读字节,采集器无法恢复这些字节。
未读完的文件消失或内容指纹变化,也会记录缺口。已读完且消失的游标可以移除。状态最多跟踪 256 个文件身份,并保留仍有未读内容的游标。
无状态文件的首次启动,从各现有文件的当前末尾开始读取,同时增加状态重置和输入缺口计数,标明新的计数起点。本设计不回填历史日志。
先提交状态,再发布指标
日志 Counter 与 Histogram 必须在 Exporter 重启后保留。游标偏移和聚合值共同提交;只推进其中一个,会导致观测丢失或重复。
一轮后台周期准备候选状态,然后执行:
状态文件上限为 4 MiB。在 Unix 上,必须是权限 0600 的普通文件;符号链接和不安全权限会被拒绝。非阻塞状态锁防止两个进程共用同一状态,保存的目录身份必须与配置来源一致。
重命名前崩溃会留下上一份已提交状态。重命名后崩溃,重启可以恢复新状态并重建对应指标。/metrics 只读取已发布快照,不扫描文件、解析 CSV 或写状态。
每轮最多处理 100,000 条记录或 64 MiB。仍有输入时,立即开始下一轮。
指标与序列上限
核心指标族为:
其他指标覆盖具体 SQLSTATE 代码、检查点与重启点、自动清理、锁等待、临时文件、连接和会话时长。
日志 Histogram 是与游标一同持久化的累计观测,可使用 rate() 等普通 Counter Histogram 查询。显式状态重置会开始新的计数周期。这与描述当前总体、使用 Gauge 序列的 SQL 快照直方图不同。
标签采用固定取值。查询时长的 kind 只有 statement、execute、parse、bind 和 other。具体 SQLSTATE 指标仅接受官方代码,最多保存 128 个已观察代码序列,自定义和未知代码归入 other。总输出上限为 1,200 条序列。
原始 SQL、消息、数据库名、用户名、应用名、关系名、查询 ID、地址、进程与会话 ID、事务 ID 和文件路径都不进入标签或持久状态。一条记录可以更新多个聚合值,但最多产生一个主要分类事件。例如,指标可以显示死锁增加,而不保留相关 SQL 文本。
读取器健康
读取器暴露以下指标:
它还使用 pg_exporter_component_*{component="postgres_log"}。输入、权限、解析、状态、上限或指标族冲突错误只将日志组件标为不可用,最后提交的快照继续提供。结合健康、最后成功时间和缺口计数判断数据的新鲜度与完整性。
--disable-intro 移除 Exporter、组件和读取器自监控,保留 pg_log_* 业务指标。
日志策略决定覆盖范围
指标只覆盖 PostgreSQL 实际输出的记录。查询时长分布取决于 log_duration、log_min_duration_statement、采样和协议行为。例如,慢语句阈值产生的是已记录慢语句的分布,而非全部查询的分布。
检查点、自动清理、连接、断连、锁等待和临时文件指标也需要对应服务端日志设置。基于消息文本的事件解析依赖支持的语言和格式;基于 SQLSTATE 的错误分类不依赖本地化措辞。
为服务用户授予指定日志的读取权限和状态目录的写入权限。源日志可能包含 SQL 与客户端数据,应限制访问范围。
备选方案与非目标
- 在
/metrics中读取日志,会给数据库抓取增加解析和持久化耗时。后台任务将这些工作分开。 - 文件通知可以加快发现,但不能替代保证正确性所需的轮询与核对。
- 首次启动重放全部历史文件,会让初始计数取决于日志保留策略。从文件末尾开始可明确建立基线。
- 持久化前发布指标可能导致崩溃后重复计数,因此先提交状态。
- 动态标签与用户匹配规则会使序列数量和保存结构取决于输入,因此采用固定指标目录。
- 独立端点或可执行文件会为同一有限数据源增加部署单元,因此复用现有进程和端点。
核验与剩余工作
实现位于 exporter/postgres_log*.go。测试覆盖 PostgreSQL 14、16、18 样例;引号与多行字段;未完成记录;重命名与截断;重启、锁和权限;崩溃位置;事件分类;序列上限;冲突;重叠抓取与关闭。
外部 CSV 集成测试待核验。设置 PG_EXPORTER_TEST_PG_LOG_DIR,使用预定服务用户验证真实日志的轮转与重启恢复。
协调规则见 Composite Exporter。CSV 定义和日志设置见 PostgreSQL 14 与 PostgreSQL 18 官方文档。
2 - 把 pgBackRest 指标移出抓取路径
pgbackrest info --output=json 提供备份状态。命令可能访问远程仓库并等待存储响应。若在 Prometheus 请求中执行,数据库监控也要承担这段延迟。
状态: 已实现,未发布。
决策日期: 2026-08-23。
最后核验: 2026-10-13。
范围: 源码提交c0ba58a的可选--pgbackrest组件;稳定版v1.4.1尚未包含。
交付进度: 本地测试通过;未合入main或发布标签;软件包、部署与生产运行未核验。
因此,PG Exporter 在后台执行 pgBackRest,验证结果后发布不可变快照。/metrics 读取最新快照,无需等待命令。
执行上限
后台任务直接执行配置的程序,不经过 shell。
| 控制项 | 默认值 | 规则 |
|---|---|---|
| 命令 | pgbackrest |
使用固定的版本与 info 参数 |
| 刷新间隔 | 2 分钟 | 最小 10 秒 |
| 刷新超时 | 30 秒 | 版本检测与 info 共用一个截止时间 |
| 标准输出 | 16 MiB | 超限取消命令 |
| 标准错误 | 64 KiB | 超限取消命令 |
后台先执行 version --output=num,旧版本回退到 version,随后执行 info --output=json。取消操作终止直接子进程;一秒的等待上限约束输出管道清理时间。
发布前验证
命令正常退出后,还要检查 JSON 结构、数值字段,以及 stanza 和仓库引用关系。输入最多包含 256 个 stanza 和 4,096 个备份;输出最多包含 20,000 个样本,Prometheus 文本不超过 4 MiB。
只有完整合法的结果才能替换快照。指标族在发布前完成验证,抓取路径只需检查元数据和所有权。
按 Composite 所有权顺序,pgBackRest 排在 PostgreSQL、进程自监控、Patroni 和 PgBouncer 之后。冲突指标族会被省略,组件标记为不可用;其他合法指标族仍可保留。
保留最后一次成功结果
首次成功刷新后,命令、超时、解析或资源上限错误会保留上一份业务指标。组件报告 up=0,增加错误计数,并保留最后成功时间。
刷新失败时,后台仍会根据保留的 JSON 重算备份年龄,使其按刷新间隔反映经过的时间。/metrics 不解析 JSON,也不执行 pgBackRest。
首次成功前没有备份业务指标。PostgreSQL 与其他有效来源继续工作。
健康与并发请求
组件健康使用 component="pgbackrest"。up 表示最近一次采集结果,最后成功时间说明备份数据有多旧。命令失败使用 exec;标准输出超限使用 limit;解析和合并错误使用各自原因。标准错误超限归类为执行错误。
重叠抓取可以读取同一份快照,不会启动第二条命令,也不会更新已保存的组件健康历史。指标冲突仍按 Composite 所有权规则处理。
备选方案与非目标
每次抓取都执行命令,会把 Prometheus 超时和并发请求绑定到仓库操作。后台任务使执行超时和刷新间隔独立于抓取。
独立 Exporter 提供进程隔离,但增加一个服务、端口、软件包和目标。集成组件提供另一种部署选择,不自动迁移现有部署。
通用 shell 命令插件不适合此处。pgBackRest 需要专用 JSON 校验、版本处理、指标定义与恢复规则。本组件接受 pgBackRest 可执行程序,不接受任意命令模板。
核验与运维
exporter/pgbackrest.go 负责命令执行与快照发布,exporter/pgbackrest_metrics.go 负责 JSON 校验与指标构造。测试覆盖版本回退、畸形与过量输出、超时、保留最后成功结果、指标族冲突和关闭。
服务用户需要执行 pgBackRest、读取其配置和仓库凭据的权限。PG Exporter 软件包不捆绑 pgBackRest,使用主机上的备份软件安装。
对组件健康和最后成功时间设置告警。采集失败后,旧备份指标仍可能可见。替换独立 Exporter 前,使用预定服务用户,对同一个仓库比较两者的输出。
3 - 我们最终没有做的 PostgreSQL 可观测性产品
我们最初考虑做一个本地 PostgreSQL 事故工作台:读取结构化日志,重建会话时间线,提供交互过滤与终端界面,后续再作为 Agent 运行。
状态: 已于 2026-08-24 被 PostgreSQL 日志指标方案取代。
决策日期: 2026-08-13 开始研究;2026-08-24 调整范围。
最后核验: 2026-10-13。
范围: 独立 PostgreSQL 事故工作台与 Agent 提案。
交付进度: 止于提案,未实现、发布或部署。
眼前需求更小:从 PostgreSQL 日志中提取可靠的运维指标。最终选择是在 PG Exporter 中增加后台采集器。本文记录保留的研究结论,以及放弃独立产品的原因。
最初提案
事故发生时,DBA 可能只有本机日志,没有集中日志服务。理解 PostgreSQL CSV、SQLSTATE、会话与轮转的工具,可以在不上传 SQL 文本的情况下生成时间线。
提案包括:
- PostgreSQL 14+ CSV 解析,包括多行字段;
- 按时间、严重级别、SQLSTATE、数据库、用户、应用和会话过滤;
- 跨重命名日志文件保留上下文;
- 交互式终端界面;
- 本地处理与低基数 Prometheus 指标;
- 后续增加持久游标和多个输出目标的守护进程。
保留的结论
PostgreSQL 14 到 18 文档给出了相同的 26 列 CSV 布局。示例导入表以 (session_id, session_line_num) 为主键。CSV 字段可包含逗号、引号和换行,因此解析器必须读取完整记录。
SQLSTATE 比本地化消息文本稳定,是错误分类的主要依据。检查点、自动清理、锁等待、临时文件和连接消息,需要针对支持版本和语言测试匹配规则。
原始 SQL、用户名、数据库名、客户端地址和会话标识不适合作为默认指标标签。它们会暴露源数据,并使序列数量随工作负载变化。固定事件类别和有限分布更适合 Prometheus。
轮转、部分写入、重启恢复和游标持久化决定计数是否可靠,必须从一开始就纳入功能契约。
调整范围的原因
工作台需要独立的命令、输出结构、界面、软件包、文档和发布周期。Agent 还需要队列、重试、保留策略和服务管理。这些职责超过了指标导出器的范围。
PG Exporter 已有抓取目标、/metrics、打包和 Pigsty 集成;开发中的协调层也提供组件健康指标。有限范围的日志采集器可以复用这些能力,满足眼前需求。
因此,我们停止独立产品、仓库和品牌工作,将交互调查与日志发送移出范围。
替代方案
2026-08-24 的决策是:
为 PG Exporter 增加默认关闭的 PostgreSQL CSV 日志后台采集器,在现有
/metrics端点发布有限的运维指标。
替代方案保留完整 CSV 解析、文件身份、轮转与截断处理、持久游标与聚合值、原子持久化、不可变快照、固定标签和明确的输入缺口指标。
日志发送、交互查询、会话时间线、任意正则表达式和自动根因分析仍不在范围内。实现契约见 PostgreSQL 日志指标。
何时重新评估
独立工作台需要一个现有日志工具无法满足的本地调查场景,也需要用户验证事件模型,以及维护者承担发布和支持周期。在这些需求明确之前,PG Exporter 继续提供聚合指标。
来源
CSV 要求来自 PostgreSQL 14 与 PostgreSQL 18 官方日志文档。替代方案的源码边界和测试证据记录在链接的设计文章中。
4 - 一个端点,多种来源:Composite Exporter 契约
Composite 模式把 PostgreSQL、PgBouncer、Patroni、pgBackRest 和 PostgreSQL 日志指标合并到同一个 /metrics 端点,减少数据库节点上的进程和抓取目标。PostgreSQL 是主数据源;各可选来源独立报告故障和健康状态。
状态: 已实现,未发布。
决策日期: 2026-08-11;2026-08-23 与 2026-08-24 增加缓存组件。
最后核验: 2026-10-13。
范围: 源码提交c0ba58a的 Composite 协调层;稳定版v1.4.1尚未包含。
交付进度: 本地测试通过;未合入main或发布标签;软件包、部署与生产运行未核验。
PostgreSQL 保持主导
只有 PostgreSQL 的指标汇总错误会使 Composite 汇总失败。可选组件故障只影响自身指标和健康状态。只要 PostgreSQL 汇总成功,端点仍返回 HTTP 200。
所有可选组件默认关闭。全部关闭时,启动过程不创建可选后台任务、客户端或文件读取器,抓取路径也不增加 Composite 协调锁。
实时采集与缓存快照
PostgreSQL 与 PgBouncer 使用现有 SQL 采集器及查询缓存。Patroni 的角色和主节点状态变化较快,因此在每次完整抓取中请求其指标端点。
pgBackRest 与 PostgreSQL 日志由后台任务采集,并发布不可变快照。HTTP 请求只读取快照,命令执行、日志解析和状态持久化不会拖慢数据库采集。刷新与恢复规则见缓存 pgBackRest 指标和持久 PostgreSQL 日志指标。
超时与并发请求
PgBouncer 与 Patroni 在 --scrape-timeout 限制下并发执行,默认 10 秒。PostgreSQL 同时采集,沿用自身查询超时;可选组件的超时不会取消 PostgreSQL 采集。
若已有一轮完整 Composite 抓取正在运行,重叠请求只采集 PostgreSQL、进程指标和缓存快照。它跳过 PgBouncer 与 Patroni 的实时采集,并在本次响应中将这两个组件的 up 设为零,不更新已保存的错误计数和最后成功时间。这样可选采集不会形成请求队列。
指标族所有权
业务指标的优先级如下:
进程与 HTTP 自监控在 PostgreSQL 之后、可选来源之前合并。组件健康指标最后合并。
先占用名称的来源拥有整个指标族。即使类型、说明和标签一致,低优先级来源也不能追加样本。Histogram 与 Summary 的派生名称同样保留:高优先级 foo Histogram 会阻止低优先级 foo_count 指标族加入。
发生冲突时,省略冲突指标族,并将可选组件标记为 gather 错误。该组件的其他合法指标族仍可保留。
Patroni 指标接入
PG Exporter 抓取、解析、验证并重新编码 Patroni 的经典 Prometheus 文本,保留指标族名称、说明、类型、标签和值,不为业务指标添加 component 标签。
响应上限为 1 MiB、10,000 行样本和 256 个指标族。HTTPS 使用系统信任根及可选的 --http-ca-file。证书错误会将 Patroni 标记为不可用;没有跳过证书验证的参数。
组件健康
除非设置 --disable-intro,Composite 模式会暴露以下自监控指标:
enabled 表示组件是否启用,关闭的组件为零。up 表示采集结果。耗时和最后成功时间对实时来源表示抓取,对缓存来源表示后台周期。错误原因使用固定枚举,例如 connect、timeout、tls、parse 和 gather。
既有 /up、/health、/primary 和 /replica 端点继续描述 PostgreSQL。这些端点用于数据库健康检查与路由,可选组件不改变其含义。--disable-intro 移除自监控指标,保留业务指标。
备选方案与非目标
- 独立 Exporter 提供进程隔离,但需要独立的目标、软件包和服务配置。Composite 是一种可选部署方式。
- 串行采集使总耗时依赖来源顺序。并发实时采集共用一个可选组件超时。
- 原样转发 Patroni 文本无法检查指标所有权和响应上限。解析后可以同时检查两者。
- 通用插件注册机制会在集成尚未稳定时暴露生命周期和优先级规则。本设计采用具名组件和固定优先级。
- 要求所有来源成功,会让数据库监控依赖可选服务。协调层将故障限制在所属组件内。
本设计不改变指标命名空间,也不负责迁移 Pigsty 目标、仪表盘、告警或现有独立 Exporter。
核验与运维影响
实现位于 exporter/composite.go、exporter/patroni.go 及启动、重载路径。测试覆盖关闭行为、超时、TLS 与格式错误、指标族冲突、并发请求、重载和关闭。
同一个进程需要所有已启用来源的权限,只授予实际所需权限。替换独立 Exporter 前,在目标环境验证正式软件包、目标标签、仪表盘和告警。
5 - 快照直方图是 Gauge,不是 Counter
一个标量指标无法描述变化中的总体分布。一个 30 分钟事务与一百个 18 秒事务的总年龄相同,但数量、最大年龄和运维影响不同。
状态: 已随 v1.4.0 发布。
决策日期: 2026-07-11;2026-07-17 修订。
最后核验: 2026-10-13。
范围: 稳定版v1.4.1的HISTOGRAM列与pg_xact_age采集器,并对照开发提交c0ba58a核验。
交付进度: 已实现、合并、打标签并发布软件包。针对性本地测试已通过;部署与生产运行未核验。
PG Exporter 快照直方图对一次 SQL 执行返回的观测值分组。每次执行都重建分布。由于值可能下降,桶、计数和总和都以 Gauge 序列输出。
时间语义
事务开始时进入总体,随时间增长移入更大的年龄桶,结束时离开总体。这与持续累计事件的 Histogram 不同。
输出沿用常见的桶结构:
这三个指标族都是 Gauge。桶内计数按当前快照的上界累计,不跨抓取累计。直接使用 histogram_quantile():
当前平均年龄由总和除以计数得到:
不要对这些快照序列使用 rate()、irate() 或 increase()。这些函数会把数值下降解释为计数器重置。
配置与 SQL
用 usage: HISTOGRAM 声明观测列,并指定桶上界:
每个非 NULL 值是一次观测。完整标签元组相同的行归入同一分布;多个 Histogram 列独立聚合。
桶包含上界,边界必须有限且严格递增。配置加载时拒绝空列表、重复值、NaN 和无穷值。PG Exporter 自动追加 +Inf。le 标签及生成的 _bucket、_count、_sum 名称为保留名称,冲突配置会被拒绝。
scale 在分桶和求和前生效。时间戳与布尔值沿用标量转换规则,不进行缩放。显式 default 将 NULL 转为观测值;未指定时忽略 NULL。
查询、缓存与失败行为
每次 SQL 执行都从空累加器开始。PG Exporter 对观测分组、计算累计桶,并在读完全部结果后发布指标。
查询出错、缺少必需列或出现非有限观测值时,整份查询结果都被拒绝,包括同一查询的标量指标。刷新失败会将缓存替换为空结果,不保留上一份分布。
缓存命中直接返回上一份结果,不追加观测。下一次 SQL 执行从零开始。重载丢弃旧采集器和缓存,包括旧桶布局。
备选方案与非目标
prometheus.NewConstHistogram将数据标为 Counter Histogram,其时间语义不适合变化中的 SQL 总体。- OpenMetrics GaugeHistogram 能直接表达该语义,但需要为此功能改变输出协议。显式 Gauge 可沿用经典文本端点。
- Native Histogram 解决存储和分辨率问题,不改变观测是事件还是当前总体这一事实。
- 在 SQL 中预聚合桶,会让每个采集器重复分组逻辑。
- 跨抓取保留观测需要事件身份、重启处理和去重。持久事件采集不在本设计范围内;日志 Histogram 使用独立契约。
参考采集器与验证
pg_xact_age 按数据库统计未结束事务的年龄和事务内空闲时长,只选择客户端后端,TTL 为 10 秒。其桶边界支持计算当前分位数、超过阈值的数量和平均年龄。
以下 pgbench 脚本产生多档查询时长和事务内空闲时长。可在测试数据库中运行,观察事务进入和离开各桶:
实现与测试覆盖多个 Histogram 列独立聚合、NULL、缩放、桶边界、查询失败、缓存复用、确定性输出、并发采集与重载。
运维影响
Exporter 无需保存事件历史,就能提供可聚合的当前分布。虽然序列使用常见 Histogram 后缀,仪表盘查询仍须遵循快照语义。
完整语法见采集器配置,发布内容见 v1.4.0。普通累计 Histogram 的查询方法见 Prometheus Histograms and summaries。