From 505933e880c308efd48c7ccb779ba37bb72c9c8c Mon Sep 17 00:00:00 2001 From: Maksym Buz Date: Mon, 30 Mar 2026 19:55:12 +0000 Subject: [PATCH] feat(template): remove ODBC template, move agent2 SQL, and track template directory --- .gitignore | 1 - template/README.md | 35 ++++++++ template/partitions.get_all.sql | 6 ++ .../zbx_pg_partitions_monitor_agent2.yaml | 79 +++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 template/README.md create mode 100644 template/partitions.get_all.sql create mode 100644 template/zbx_pg_partitions_monitor_agent2.yaml diff --git a/.gitignore b/.gitignore index a50e7cf..0bc71a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ db_credentials global-bundle.pem -template/ diff --git a/template/README.md b/template/README.md new file mode 100644 index 0000000..41f1411 --- /dev/null +++ b/template/README.md @@ -0,0 +1,35 @@ +# Zabbix PostgreSQL Partitioning Monitoring + +This directory contains an extremely efficient, production-ready Zabbix Native Agent 2 monitoring suite designed to track the health of your actively partitioned PostgreSQL database tables. + +This template natively leverages the Zabbix Agent 2 backend. It uses a single, highly-optimized master payload query (`partitions.get_all.sql`) to pull all metrics in bulk over a single database connection, dynamically distributing the numbers to Zabbix using Dependent Items. + +### Step-by-Step Setup +1. Copy the **one** SQL file (`template/partitions.get_all.sql`) into a secure directory on your Agent machine. E.g., `/etc/zabbix/zabbix_agent2.d/postgresql/`. +2. Secure the local Linux permissions so the Zabbix user can strictly read it: + ```bash + chown -R zabbix:zabbix /etc/zabbix/zabbix_agent2.d/postgresql + chmod 644 /etc/zabbix/zabbix_agent2.d/postgresql/*.sql + ``` +3. Open your main `/etc/zabbix/zabbix_agent2.conf` file. Scroll to the absolute bottom and add these exact lines to safely establish your custom query module AND a secure named session (e.g., `AWS_RDS`): + ```ini + # 1. Enable Loadable Custom Queries (Mandatory in Zabbix 7.4+) + Plugins.PostgreSQL.CustomQueriesPath=/etc/zabbix/zabbix_agent2.d/postgresql/ + Plugins.PostgreSQL.CustomQueriesEnabled=true + + # 2. Establish a Secure Backend Session + Plugins.PostgreSQL.Sessions.AWS_RDS.Uri=tcp://your-cluster-endpoint.amazonaws.com:5432 + Plugins.PostgreSQL.Sessions.AWS_RDS.User=zabbix + Plugins.PostgreSQL.Sessions.AWS_RDS.Password= + Plugins.PostgreSQL.Sessions.AWS_RDS.TLSConnect=verify_full + Plugins.PostgreSQL.Sessions.AWS_RDS.TLSCAFile=/etc/zabbix/global-bundle.pem + ``` +4. Restart your agent to lock the session and SSL configurations into memory: + ```bash + systemctl restart zabbix-agent2 + ``` +5. Import the `zbx_pg_partitions_monitor_agent2.yaml` template directly into your Zabbix Frontend. +6. Attach the template to your Host, navigate to its "Macros" tab, and define strictly exactly this **one** macro: + * `{$PG.CONNSTRING.AGENT2}`: `AWS_RDS` + +*(By pointing this macro to the Session name we built in Step 3, you are telling Zabbix to seamlessly abandon all plaintext frontend passwords and rely 100% on the encrypted local session parameters!)* diff --git a/template/partitions.get_all.sql b/template/partitions.get_all.sql new file mode 100644 index 0000000..7c82e6f --- /dev/null +++ b/template/partitions.get_all.sql @@ -0,0 +1,6 @@ +SELECT + table_name, + future_partitions, + total_size_bytes, + EXTRACT(EPOCH FROM (now() - last_updated)) AS age_seconds +FROM partitions.monitoring; \ No newline at end of file diff --git a/template/zbx_pg_partitions_monitor_agent2.yaml b/template/zbx_pg_partitions_monitor_agent2.yaml new file mode 100644 index 0000000..52212b6 --- /dev/null +++ b/template/zbx_pg_partitions_monitor_agent2.yaml @@ -0,0 +1,79 @@ +zabbix_export: + version: '7.0' + templates: + - uuid: a1d5f8c3b2e44a7c9d6b1f2e8a3c5b4d + template: 'RDS PostgreSQL Partitioning Monitoring Agent 2' + name: 'RDS PostgreSQL Partitioning Monitoring (Agent 2)' + description: 'Monitors the custom partitions.monitoring view via the native Zabbix Agent 2 PostgreSQL plugin. Optimized using a master data payload.' + groups: + - name: Templates/Databases + macros: + - macro: '{$PG.CONNSTRING.AGENT2}' + value: 'AWS_RDS' + description: 'Session name or URI of the PostgreSQL instance' + - macro: '{$PG.DBNAME}' + value: 'zabbix' + items: + - uuid: b8c7d6e5f4a34b2c8d2e3f4a5b6c7d8e + name: 'PostgreSQL: Get Partitioning Data' + type: ZABBIX_PASSIVE + key: 'pgsql.custom.query["{$PG.CONNSTRING.AGENT2}",,,"{$PG.DBNAME}","partitions.get_all"]' + value_type: TEXT + description: 'Master item that queries all partition statistics in a single bulk JSON sequence.' + discovery_rules: + - uuid: b7c2a5d8f1e44b9c8a3f6d2e1c5b4a7d + name: 'Partitioned Tables Discovery' + type: DEPENDENT + key: 'db.partitions.discovery.dependent' + delay: '0' + master_item: + key: 'pgsql.custom.query["{$PG.CONNSTRING.AGENT2}",,,"{$PG.DBNAME}","partitions.get_all"]' + lld_macro_paths: + - lld_macro: '{#TABLE_NAME}' + path: '$.table_name' + item_prototypes: + - uuid: c4b9e2a5f1d84c7a9f3b6d1e5a2c8b4d + name: 'Table {#TABLE_NAME}: Future Partitions Buffer' + type: DEPENDENT + key: 'db.partitions.future["{#TABLE_NAME}"]' + value_type: FLOAT + master_item: + key: 'pgsql.custom.query["{$PG.CONNSTRING.AGENT2}",,,"{$PG.DBNAME}","partitions.get_all"]' + preprocessing: + - type: JSONPATH + parameters: + - '$.[?(@.table_name == "{#TABLE_NAME}")].future_partitions.first()' + trigger_prototypes: + - uuid: d6e3a5c8b2f14d9e8a7b6c5d4e3f2a1b + expression: 'last(/RDS PostgreSQL Partitioning Monitoring Agent 2/db.partitions.future["{#TABLE_NAME}"])<2' + name: 'Table {#TABLE_NAME}: Future partitions buffer is critically low (< 2)' + priority: HIGH + - uuid: e8f2a1b3c4d54e6f9a8b7c6d5e4f3a2b + name: 'Table {#TABLE_NAME}: Total Size Bytes' + type: DEPENDENT + key: 'db.partitions.size["{#TABLE_NAME}"]' + value_type: FLOAT + units: B + master_item: + key: 'pgsql.custom.query["{$PG.CONNSTRING.AGENT2}",,,"{$PG.DBNAME}","partitions.get_all"]' + preprocessing: + - type: JSONPATH + parameters: + - '$.[?(@.table_name == "{#TABLE_NAME}")].total_size_bytes.first()' + - uuid: f1a2b3c4d5e64f7a9b8c7d6e5f4a3b2c + name: 'Table {#TABLE_NAME}: Time Since Last Maintenance' + type: DEPENDENT + key: 'db.partitions.age["{#TABLE_NAME}"]' + value_type: FLOAT + units: s + master_item: + key: 'pgsql.custom.query["{$PG.CONNSTRING.AGENT2}",,,"{$PG.DBNAME}","partitions.get_all"]' + preprocessing: + - type: JSONPATH + parameters: + - '$.[?(@.table_name == "{#TABLE_NAME}")].age_seconds.first()' + trigger_prototypes: + - uuid: a9b8c7d6e5f44a3b8c1d2e3f4a5b6c7d + expression: 'last(/RDS PostgreSQL Partitioning Monitoring Agent 2/db.partitions.age["{#TABLE_NAME}"])>172800' + name: 'Table {#TABLE_NAME}: Maintenance script has not run successfully in over 48 hours' + priority: WARNING