ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Vector 的 postgresql_metrics 源:从 RFC 设计到生产实现的 PostgreSQL 指标采集指南

Vector 的 postgresql_metrics 源:从 RFC 设计到生产实现的 PostgreSQL 指标采集指南 Vector 的 postgresql_metrics 源从 RFC 设计到生产实现的 PostgreSQL 指标采集指南【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector本文以 Vector 仓库中的 RFC 36032020-08-27 提交为骨架结合仓库中postgresql_metrics源的最终实现代码与其官方组件文档完整讲解Vector 如何原生采集 PostgreSQL 服务器指标、postgresql_metrics源暴露哪些配置项、每一类指标的名称与语义是什么以及该设计在实现落地过程中的关键演进。读完本文你将能够独立配置一个postgresql_metrics源理解其指标命名规则与标签体系并知道如何用集成测试验证采集结果。一、RFC 背景为什么 Vector 需要原生 PostgreSQL 指标源RFC 3603 的动机非常直接用户希望采集、转换并转发 PostgreSQL 数据库的性能指标以更好地观察数据库的运行状态。在此之前用户若想将 PostgreSQL 指标送入 Vector 管道只能依赖 Telegraf 的postgresqlinput 或 Prometheus 的postgresql_exporter这类外部采集器再让 Vector 通过prometheus源去抓取——链路长、组件多、维护成本高。RFC 的 Scope 明确了两点边界覆盖新增一个用于采集 PostgreSQL 服务器指标的 source不覆盖其他数据库的指标采集。之所以值得做除了 PostgreSQL 本身是被广泛采用的现代数据库、用户普遍需要监控其状态与性能外更关键的是 Vector 的产品愿景——One Tool. All Data.即一个工具完成日志、指标、追踪当时即将支持的摄取与投递。RFC 中引用了 Vector 官方文档的两条原则One Tool. All Data. —— 一个简单工具将你的日志、指标和追踪从 A 送到 B。你应该使用 Vector 替代 Logstash、Fluent*、Telegraf、Beats 或类似的工具。换句话说把 PostgreSQL 指标采集内建到 Vector 中是为了减少用户在摄取指标时对第三方采集器的依赖让 Vector 真正成为可替代 Telegraf 的一体化数据管道。二、整体设计一个源、三个查询、一套命名规则2.1 实现方案Rust PostgreSQL 客户端直连RFC 给出的内部方案是构建一个名为postgresql_metrics当时名称待确认的单一 source使用 Rust 的 PostgreSQL 客户端tokio_postgres按配置中给定的地址连接目标数据库服务器。这一方案在最终实现中完全落地。在 src/sources/postgresql_metrics.rs 中源码直接依赖tokio_postgres含Client、Config、NoTls、Row等类型并通过postgres_openssl::MakeTlsConnector支持 TLS 连接。连接建立后源码会执行SHOW server_version_num检查服务器版本只有**主版本号大于等于 9.6即 server_version_num 90600**的服务器才会被接受否则抛出InvalidVersion错误——这与 RFC 中支持所有未 EOL 的 PostgreSQL 版本的承诺一致。2.2 三个核心查询RFC 明确规定了 source 需要执行的三条查询SELECT * FROM pg_stat_database SELECT * FROM pg_stat_database_conflicts SELECT * FROM pg_stat_bgwriter最终实现与 RFC 完全一致。在源码中这三条查询被封装在DatnameFilter与PostgresqlMetrics中pg_stat_databaseDatnameFilter::pg_stat_database逐数据库返回连接数、事务提交/回滚、块读写命中、元组增删改查、临时文件、死锁等累计统计pg_stat_database_conflictsDatnameFilter::pg_stat_database_conflicts在备库standby上返回因恢复冲突而被取消的查询次数按冲突类型表空间、锁、快照、buffer pin、死锁拆分pg_stat_bgwriterDatnameFilter::pg_stat_bgwriter后台写进程background writer的检查点与缓冲写统计属于集群级非数据库级数据。三者通过try_join_all并发执行见collect_metrics采集完成后统计字节数与事件数并通过内部事件EndpointBytesReceived、EventsReceived上报。采集循环由tokio::time::interval驱动每次迭代结束发送CollectionCompleted事件度量单轮采集耗时。2.3 指标命名规则RFC 定义的命名规则非常清晰这也是本文值得记住的核心约定table_name_column_name Prometheus 结尾计数器加_total等即表名 下划线 列名再依据指标类型追加 Prometheus 风格的_total后缀。RFC 给出的示例pg_database_conflicts_confl_tablespace_total其中pg_database_conflicts是表名confl_tablespace是列名_total是因为计数器在 Prometheus 命名约定中必须以total结尾。这套规则与 Prometheus 官方 exporter 的命名方式保持一致方便用户在 Prometheus 生态中复用查询经验。需要注意的是RFC 中表名的示例写法是pg_database_conflicts而最终实现落地时统一采用了pg_stat_database_conflicts_confl_*前缀指标语义与命名规则本身没有变化只是前缀与 PostgreSQL 视图名保持了一致。三、指标清单完整指标表与语义RFC 在Internal Proposal一节列出了一份完整的指标清单并标注了每个指标的标签tag集数据库级指标带db、host、server、user集群级指标带host、server。最终实现保留了这一分层思想但标签体系简化为所有指标带endpoint、host数据库级指标额外带dbserver、user未在最终实现中出现endpoint则是 RFC 在所有指标将额外带 endpoint去除用户名/密码后一节中要求增加的。以下为最终实现实际输出的指标清单结合 组件文档 中的官方描述整理3.1 可用性指标指标名类型标签语义upgaugeendpoint, hostPostgreSQL 服务器是否存活成功采集为1失败为0up指标对应 RFC 中的pg_up设计0 表示采集成功、1 表示采集失败实现时去掉了pg_前缀并反转语义成功1。在源码collect()中采集成功时输出gauge!(1.0)任一步骤出错则输出gauge!(0.0)并发出PostgresqlMetricsCollectError内部事件。3.2 pg_stat_database 系列数据库级带 db 标签指标名类型语义pg_stat_database_datidgauge数据库 OID共享对象为 0pg_stat_database_numbackendsgauge当前连接到该数据库的后端进程数唯一反映当前状态的列pg_stat_database_xact_commit_totalcounter已提交事务数pg_stat_database_xact_rollback_totalcounter已回滚事务数pg_stat_database_blks_read_totalcounter磁盘块读取数pg_stat_database_blks_hit_totalcounter命中 PostgreSQL 缓冲缓存非 OS 文件缓存的块数pg_stat_database_tup_returned_totalcounter查询返回的行数pg_stat_database_tup_fetched_totalcounter查询取回的行数pg_stat_database_tup_inserted_totalcounter插入的行数pg_stat_database_tup_updated_totalcounter更新的行数pg_stat_database_tup_deleted_totalcounter删除的行数pg_stat_database_conflicts_totalcounter因恢复冲突被取消的查询数仅备库出现pg_stat_database_temp_files_totalcounter创建的临时文件数pg_stat_database_temp_bytes_totalcounter写入临时文件的数据总量pg_stat_database_deadlocks_totalcounter检测到的死锁数pg_stat_database_blk_read_time_seconds_totalcounter后端读取数据文件块耗时秒需启用track_io_timingpg_stat_database_blk_write_time_seconds_totalcounter后端写入数据文件块耗时秒需启用track_io_timingpg_stat_database_stats_resetgauge上次重置统计的时间Unix 时间戳3.3 pg_stat_database_conflicts 系列备库冲突带 db 标签指标名类型语义pg_stat_database_conflicts_confl_tablespace_totalcounter因表空间被删除而取消的查询数pg_stat_database_conflicts_confl_lock_totalcounter因锁超时而取消的查询数pg_stat_database_conflicts_confl_snapshot_totalcounter因旧快照而取消的查询数pg_stat_database_conflicts_confl_bufferpin_totalcounter因 buffer 被 pin 而取消的查询数pg_stat_database_conflicts_confl_deadlock_totalcounter因死锁而取消的查询数3.4 pg_stat_bgwriter 系列集群级无 db 标签指标名类型语义pg_stat_bgwriter_checkpoints_timed_totalcounter已执行的定时检查点次数pg_stat_bgwriter_checkpoints_req_totalcounter已执行的请求式检查点次数pg_stat_bgwriter_checkpoint_write_time_seconds_totalcounter检查点处理中写入文件的总耗时秒pg_stat_bgwriter_checkpoint_sync_time_seconds_totalcounter检查点处理中同步文件的总耗时秒pg_stat_bgwriter_buffers_checkpoint_totalcounter检查点期间写入的缓冲数pg_stat_bgwriter_buffers_clean_totalcounter后台写进程写入的缓冲数pg_stat_bgwriter_maxwritten_clean_totalcounter后台写进程因写入过多缓冲而停止清理扫描的次数pg_stat_bgwriter_buffers_backend_totalcounter后端直接写入的缓冲数pg_stat_bgwriter_buffers_backend_fsync_totalcounter后端自行执行 fsync 的次数pg_stat_bgwriter_buffers_alloc_totalcounter已分配的缓冲数pg_stat_bgwriter_stats_resetgauge上次重置统计的时间Unix 时间戳3.5 按版本条件输出的扩展指标PostgreSQL 12源码中有一处版本分支当client_version 120000即 PostgreSQL 12 及以上时额外采集两个校验和指标指标名类型语义pg_stat_database_checksum_failures_totalcounter检测到的数据页校验和失败次数未启用数据校验和时为 0pg_stat_database_checksum_last_failuregauge最后一次数据页校验和失败的时间Unix 时间戳未启用时为 03.6 单位与数值归一化细节实现层面有几个值得注意的数值处理时间类指标统一转为秒blk_read_time、blk_write_time、checkpoint_write_time、checkpoint_sync_time在 PostgreSQL 中单位为毫秒源码读取f64后统一除以1000f64再输出且指标名带有_seconds_段命名与单位自洽时间戳类指标转为 Unix 时间戳stats_reset、checksum_last_failure这类timestamptz列通过chrono::DateTimeUtc读取后取.timestamp()所有指标使用MetricKind::Absolute输出并带namespace默认postgresql与当前 UTC 时间戳。四、配置详解从 RFC 草案到最终实现4.1 RFC 中的配置草案RFC 的 Doc-level Proposal 给出的配置示例如下[sources.my_source_id] type postgresql_metrics # required endpoint postgres://postgreslocalhost # required - address of the PG server. included_databases [production, testing] # optional, list of databases to query. Defaults to all if not specified. excluded_databases [ development ] # optional, excludes specific databases. If a DB is excluded explicitly but included in included_databases then it is excluded. scrape_interval_secs 15 # optional, default, seconds namespace postgresql # optional, default is postgresql, namespace to attach to metrics.RFC 同时提出还将暴露 HTTP SSL 设置并在 endpoint URL 中支持ssl参数并计划补充一份无需 root 权限运行的指南。4.2 最终实现的配置项对照 生成配置文档 与 源码配置结构体最终配置形态如下[sources.my_source_id] type postgresql_metrics # required endpoints [postgresql://postgres:vectorlocalhost:5432/postgres] # required include_databases [^postgres$, ^vector$] # optional exclude_databases [^template.*] # optional scrape_interval_secs 15 # optional, default 15 (seconds) namespace postgresql # optional, default postgresql [sources.my_source_id.tls] ca_file certs/ca.pem # optional各配置项说明RFC 草案 → 最终实现的差异已标注配置项必填默认值说明endpoints是—RFC 草案为单个endpoint实现演进为endpoints字符串数组可同时抓取多个 PostgreSQL 实例每个元素须为 PostgreSQL 连接 URI 格式如postgresql://postgres:vectorlocalhost:5432/postgresinclude_databases否全部数据库RFC 草案名为included_databases实现定稿为include_databases使用 POSIX 正则表达式匹配datname列指定表示包含datname为 NULL 的记录如共享对象exclude_databases否不排除RFC 草案名为excluded_databases实现定稿为exclude_databases同样使用 POSIX 正则。RFC 明确优先级语义数据库若同时被 include 与 exclude则被排除scrape_interval_secs否15两次抓取之间的间隔单位秒namespace否postgresql附加到所有输出指标上的命名空间tls.ca_file否—附加 CA 证书文件的绝对路径证书须为 DER 或 PEMX.509格式4.3 include/exclude 的正则过滤是如何实现的最终实现没有在 SQL 层面硬编码数据库名而是用DatnameFilter源码实现在构建查询时动态拼装 WHERE 子句include 列表中的每个正则生成一个datname ~ $N谓词POSIX 正则匹配多个正则之间用OR连接整体用括号包裹exclude 列表生成NOT (datname ~ $1 OR datname ~ $2 ...)谓词并通过AND与 include 组合从而天然实现exclude 优先级更高被特殊处理为datname IS NULL/datname IS NOT NULL条件include 含空串则保留 NULL 记录exclude 含空串则剔除 NULL 记录所有正则通过参数化查询match_params传入避免 SQL 注入。若include_databases与exclude_databases均未配置则查询保持最简形式SELECT * FROM pg_stat_database等价于采集全部数据库。这一点与 RFC 中未指定时默认采集所有数据库的语义一致。4.4 TLS 与连接安全RFC 提出的 SSL 支持最终以两种方式落地endpoint URL 内建 SSL 参数连接 URI 中直接支持sslmode如?sslmoderequire源码会解析并透传该参数独立tls配置块提供tls.ca_file指定附加 CA 证书DER/PEM 格式通过 OpenSSL 构建MakeTlsConnector建立加密连接见源码build_client中的SslConnector::builder(SslMethod::tls_client())与set_ca_file。此外连接成功后源码在 DEBUG 级别记录服务器版本SELECT version()并对endpoint标签做了脱敏处理config_to_endpoint函数会将连接配置重新序列化为不含用户名/密码的规范化 URI如postgresql:///postgres?hostlocalhostport5432这正是 RFC 要求的所有指标均带上去除用户名/密码后的 endpoint 标签。从源码看该函数还会保留sslmode、connect_timeout、keepalives_idle、target_session_attrs、channel_binding等连接参数剔除默认值。4.5 输出标签体系最终实现的标签体系如下所有指标endpoint脱敏后的连接 URI、host取自连接配置的主机TCP 主机名或 Unix socket 路径数据库级指标pg_stat_database 与 pg_stat_database_conflicts 系列额外带db标签取自datname列NULL 时为集群级指标pg_stat_bgwriter 系列仅endpoint与host。五、权限要求与运维注意5.1 所需权限组件文档 的 Required Privileges 一节明确指出postgresql_metrics通过向配置的 PostgreSQL 服务器发起查询来采集指标必须确保配置的用户对以下三个视图拥有 SELECT 权限pg_stat_databasepg_stat_database_conflictspg_stat_bgwriterRFC 也提到要补充无需 root 权限运行的指南——即使用具备上述视图查询权限的专用低权限账号而不是超级用户。实际操作中应避免在 endpoint URI 中硬编码高权限账号口令可通过 Vector 的密钥管理能力注入凭据。5.2 采集行为与版本限制多实例并发endpoints中每个实例对应一个独立的PostgresqlMetrics采集器抓取时通过join_all并发执行互不阻塞版本校验连接时执行SHOW server_version_num低于 9.6 的服务器连接会被拒绝并返回InvalidVersion错误12.0 以上自动多采集两个校验和指标失败语义任何一轮采集中有实例失败该实例输出up 0成功实例正常输出管道不会中断内部遥测每轮抓取会产生collect_completed_total、collect_duration_seconds等内部指标可用于监控采集器自身健康状况。六、集成测试验证实现确实按 RFC 工作postgresql_metrics的集成测试位于 src/sources/postgresql_metrics.rs 的integration_tests模块需启用postgresql_metrics-integration-testsfeature测试覆盖了 RFC 中的核心承诺test_host / test_local分别验证 TCP 连接与 Unix socket 连接postgresql:///postgres?hostsocketuservectorpasswordvectortest_host_ssl验证?sslmoderequiretls.ca_file的加密连接test_host_include_databases配置[^vec, gres$]断言所有指标的db标签只能是vector或postgrestest_host_exclude_databases配置排除[^vec, gres$]断言没有任何指标带vector/postgres的db标签test_host_exclude_databases_empty验证排除即排除datname IS NULL的记录test_host_include_databases_and_exclude_databasesincludetemplate\d且 excludetemplate0时断言只保留template1—— 直接验证了 RFC 中被显式排除的数据库即使被 include 也会被排除的优先级规则。测试同时断言事件数大于 1、up指标值为 1、所有指标 namespace 为postgresql、每条指标都带endpoint与host标签且pg_stat_database_datid、pg_stat_database_conflicts_confl_tablespace_total、pg_stat_bgwriter_checkpoints_timed_total三类来源的指标都存在——三条查询全部生效。七、设计决策回顾Prior Art、替代方案与取舍7.1 已有实现参考Prior ArtRFC 列出并参考了社区已有的 PostgreSQL 采集实现wrouesnel 的postgres_exporter、Telegraf 的postgresqlinput 插件以及 collectd 的 PostgreSQL 插件。这些项目验证了通过查询统计视图采集指标这一路线的可行性Vector 的指标命名也向其靠拢。7.2 替代方案外部采集器 prometheus 源RFC 认真考虑过一个替代方案不新增 source而是让用户运行 Telegraf 的 postgresql input 或 Prometheus 的 postgresql_exporter再由 Vector 的prometheus源抓取结果。该方案能复用既有项目但 RFC 明确否决了它理由是这与 Vector 的One Tool. All Data.原则相悖——Vector 的目标是替代 Telegraf而不是依赖它。不过 RFC 也承认已经在运行 Telegraf 或 PostgreSQL Exporter 的用户完全可以继续走这条老路prometheus源依然可用。7.3 缺点与未来工作RFC 坦承该方案的缺点主要是新增 source 带来的额外维护与集成测试负担因此仓库中配套了完整的集成测试矩阵。RFC 还留下两个待办Outstanding Questions实现过程中应关注是否采集pg_settingsFuture Work后续可扩展采集更多数据库指标包括复制Replication指标、锁Locks指标、pg_stat_user_tables。八、总结从 RFC 3603 到落地postgresql_metrics源完整兑现了设计承诺以 Rust 客户端直连 PostgreSQL、执行三条核心统计视图查询、按表名_列名 Prometheus 后缀命名指标、以endpoint/host/db标签描述指标归属。与 RFC 草案相比实现的演进主要体现在endpoint升级为多实例的endpoints数组、include/exclude 从字面匹配升级为 POSIX 正则、指标命名统一为pg_stat_*前缀、新增 PostgreSQL 12 校验和指标、以及 endpoint 标签的凭据脱敏处理。如果你正在用 Vector 构建可观测性管道只需在配置中加上一个postgresql_metrics源就能以极低代价把 PostgreSQL 的事务、缓冲、检查点、冲突等关键性能信号汇入统一的日志/指标管道再配合 Vector 的 transform 与 sink 能力完成富化与分发。相关参考材料配置结构体见 src/sources/postgresql_metrics.rs、采集逻辑见同文件collect_pg_stat_database等函数、指标语义与权限要求见 组件文档。【免费下载链接】vectorA high-performance observability data pipeline.项目地址: https://gitcode.com/GitHub_Trending/vect/vector创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进