跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

设计归档

PG Exporter 的架构决策、被否决方案与实现契约

设计记录解释 PG Exporter 的架构、备选方案与取舍。每篇注明状态、源码边界和最后核验日期。

快照直方图已随 v1.4.0 发布。Composite 模式、缓存 pgBackRest 指标和 PostgreSQL 日志指标已在开发分支实现,尚未进入稳定版 v1.4.1。独立可观测性产品提案已被取代。

稳定版操作方法见使用手册,已发布变更见发布归档。

1 - 把 PostgreSQL CSV 日志转成持久指标

读取完整 CSV 记录,持久化游标与聚合值,发布有界 PostgreSQL 日志指标

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=/var/log/postgresql \
  --pg-log-state-file=/var/lib/pg_exporter/pglog-state.json \
  --pg-log-poll-interval=1s

对应环境变量为 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 重启后保留。游标偏移和聚合值共同提交;只推进其中一个,会导致观测丢失或重复。

一轮后台周期准备候选状态,然后执行:

读取完整记录,更新候选状态
    -> 验证计数器、直方图、标签和上限
    -> 构造并验证指标族
    -> 写入 0600 临时状态文件
    -> fsync 文件
    -> 原子重命名到状态路径
    -> 在支持的平台 fsync 父目录
    -> 发布对应的不可变指标快照

状态文件上限为 4 MiB。在 Unix 上,必须是权限 0600 的普通文件;符号链接和不安全权限会被拒绝。非阻塞状态锁防止两个进程共用同一状态,保存的目录身份必须与配置来源一致。

重命名前崩溃会留下上一份已提交状态。重命名后崩溃,重启可以恢复新状态并重建对应指标。/metrics 只读取已发布快照,不扫描文件、解析 CSV 或写状态。

每轮最多处理 100,000 条记录或 64 MiB。仍有输入时,立即开始下一轮。

指标与序列上限

核心指标族为:

pg_log_records_total{severity}
pg_log_errors_total{severity,sqlstate_class}
pg_log_query_duration_seconds{kind}
pg_log_events_total{category,event}

其他指标覆盖具体 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_log_bytes_read_total
pg_exporter_log_parse_errors_total{reason}
pg_exporter_log_files_watched
pg_exporter_log_last_record_timestamp_seconds
pg_exporter_log_state_persist_timestamp_seconds
pg_exporter_log_rotations_total{type}
pg_exporter_log_input_gaps_total{reason}
pg_exporter_log_state_resets_total

它还使用 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,并提供最后一份有效指标快照

pgbackrest info --output=json 提供备份状态。命令可能访问远程仓库并等待存储响应。若在 Prometheus 请求中执行,数据库监控也要承担这段延迟。

状态: 已实现,未发布。
决策日期: 2026-08-23。
最后核验: 2026-10-13。
范围: 源码提交 c0ba58a 的可选 --pgbackrest 组件;稳定版 v1.4.1 尚未包含。
交付进度: 本地测试通过;未合入 main 或发布标签;软件包、部署与生产运行未核验。

因此,PG Exporter 在后台执行 pgBackRest,验证结果后发布不可变快照。/metrics 读取最新快照,无需等待命令。

后台任务
    -> 检测 pgBackRest 版本
    -> 执行 info --output=json
    -> 验证并构造指标
    -> 发布快照

/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 可观测性产品

为什么独立事故工作台最终变为 PG Exporter 内的 CSV 日志采集器

我们最初考虑做一个本地 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 契约

通过固定所有权和独立故障处理,合并 PostgreSQL 与可选来源的指标

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 协调锁。

实时采集与缓存快照

Prometheus /metrics
        |
        v
Composite 协调层
  |-- PostgreSQL SQL       实时、主数据源
  |-- PgBouncer SQL        实时、可选
  |-- Patroni HTTP         实时、可选
  |-- pgBackRest 快照      缓存、可选
  `-- PostgreSQL 日志      缓存、可选

PostgreSQL 与 PgBouncer 使用现有 SQL 采集器及查询缓存。Patroni 的角色和主节点状态变化较快,因此在每次完整抓取中请求其指标端点。

pgBackRest 与 PostgreSQL 日志由后台任务采集,并发布不可变快照。HTTP 请求只读取快照,命令执行、日志解析和状态持久化不会拖慢数据库采集。刷新与恢复规则见缓存 pgBackRest 指标和持久 PostgreSQL 日志指标。

超时与并发请求

PgBouncer 与 Patroni 在 --scrape-timeout 限制下并发执行,默认 10 秒。PostgreSQL 同时采集,沿用自身查询超时;可选组件的超时不会取消 PostgreSQL 采集。

若已有一轮完整 Composite 抓取正在运行,重叠请求只采集 PostgreSQL、进程指标和缓存快照。它跳过 PgBouncer 与 Patroni 的实时采集,并在本次响应中将这两个组件的 up 设为零,不更新已保存的错误计数和最后成功时间。这样可选采集不会形成请求队列。

指标族所有权

业务指标的优先级如下:

PostgreSQL > Patroni > PgBouncer > pgBackRest > PostgreSQL Log

进程与 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 模式会暴露以下自监控指标:

pg_exporter_component_enabled{component="..."}
pg_exporter_component_up{component="..."}
pg_exporter_component_scrape_duration_seconds{component="..."}
pg_exporter_component_scrape_errors_total{component="...",reason="..."}
pg_exporter_component_last_success_timestamp_seconds{component="..."}

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

为什么 SQL 快照分布将桶、计数与总和输出为 Gauge 序列

一个标量指标无法描述变化中的总体分布。一个 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 不同。

输出沿用常见的桶结构:

pg_xact_age_seconds_bucket{datname="app",le="10"} 5
pg_xact_age_seconds_bucket{datname="app",le="30"} 9
pg_xact_age_seconds_bucket{datname="app",le="+Inf"} 11
pg_xact_age_seconds_count{datname="app"} 11
pg_xact_age_seconds_sum{datname="app"} 214

这三个指标族都是 Gauge。桶内计数按当前快照的上界累计,不跨抓取累计。直接使用 histogram_quantile():

histogram_quantile(
  0.95,
  sum by (datname, le) (pg_xact_age_seconds_bucket)
)

当前平均年龄由总和除以计数得到:

sum by (datname) (pg_xact_age_seconds_sum)
/
sum by (datname) (pg_xact_age_seconds_count)

不要对这些快照序列使用 rate()、irate() 或 increase()。这些函数会把数值下降解释为计数器重置。

配置与 SQL

用 usage: HISTOGRAM 声明观测列,并指定桶上界:

- seconds:
    usage: HISTOGRAM
    bucket: [1, 3, 10, 30, 100, 300, 1000, 3000]
    description: Open transaction age snapshot in seconds

每个非 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 脚本产生多档查询时长和事务内空闲时长。可在测试数据库中运行,观察事务进入和离开各桶:

\set query_band random(1, 4)
\if :query_band = 1
  \set query_ms 300
\elif :query_band = 2
  \set query_ms 3000
\elif :query_band = 3
  \set query_ms 10000
\else
  \set query_ms 30000
\endif

\set hold_band random(1, 4)
\if :hold_band = 1
  \set hold_ms 300
\elif :hold_band = 2
  \set hold_ms 3000
\elif :hold_band = 3
  \set hold_ms 10000
\else
  \set hold_ms 30000
\endif

BEGIN;
SELECT pg_current_xact_id(), pg_sleep(:query_ms / 1000.0);
\sleep :hold_ms ms
COMMIT;

实现与测试覆盖多个 Histogram 列独立聚合、NULL、缩放、桶边界、查询失败、缓存复用、确定性输出、并发采集与重载。

运维影响

Exporter 无需保存事件历史,就能提供可聚合的当前分布。虽然序列使用常见 Histogram 后缀,仪表盘查询仍须遵循快照语义。

完整语法见采集器配置,发布内容见 v1.4.0。普通累计 Histogram 的查询方法见 Prometheus Histograms and summaries。