├── LICENSE ├── README-en.md ├── README.md ├── pg_monz ├── template │ ├── Template_App_PostgreSQL.xml │ ├── Template_App_PostgreSQL_SR.xml │ ├── Template_App_PostgreSQL_SR_Cluster.xml │ ├── Template_App_pgpool-II-36.xml │ ├── Template_App_pgpool-II.xml │ └── Template_App_pgpool-II_watchdog.xml ├── usr-local-bin │ ├── find_dbname.sh │ ├── find_dbname_table.sh │ ├── find_pgpool_backend.sh │ ├── find_pgpool_backend_ip.sh │ ├── find_sr.sh │ ├── find_sr_client_ip.sh │ ├── pgpool_backend_status.sh │ ├── pgpool_cache.sh │ ├── pgpool_connections.sh │ ├── pgpool_delegate_ip.sh │ ├── pgpool_simple.sh │ ├── pgsql_db_funcs.sh │ ├── pgsql_primary.sh │ ├── pgsql_server_funcs.sh │ ├── pgsql_simple.sh │ ├── pgsql_sr_server_funcs.sh │ ├── pgsql_standby.sh │ ├── pgsql_tbl_funcs.sh │ └── pgsql_userdb_funcs.sh ├── usr-local-etc │ ├── pgpool_funcs.conf │ └── pgsql_funcs.conf └── zabbix_agentd.d │ └── userparameter_pgsql.conf └── quick-install.txt /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README-en.md: -------------------------------------------------------------------------------- 1 | **Maintenance for pg_monz ended on October 31, 2021.** 2 | 3 | pg_monz 2.0 4 | ============================ 5 | pg_monz (PostgreSQL monitoring template for Zabbix) is a Zabbix template for 6 | monitoring PostgreSQL. It enables various types of monitoring of PostgreSQL 7 | such as alive, resource, performance, etc. 8 | Pg_monz also supports automatic discovery of databases and tables using the 9 | discovery feature of Zabbix and can automatically start monitoring. 10 | 11 | 12 | Changes from 1.0 13 | ---------------- 14 | The following is a summary of the major changes. 15 | 16 | 17 | ### Support for monitoring of PostgreSQL Streaming Replication 18 | pg_monz 2.0 now supports monitoring of Streaming Replication which is embedded in PostgreSQL since 9.0. 19 | Various monitoring items such as Primary / Standby servers alive monitoring, delay of replication data propagation and conflicts occurred by operation to Primary and Standby are available. 20 | It is also that a trigger which can detect the occurence of write block query when useing synchronous replication is provided. 21 | 22 | 23 | ### Support for monitoring of pgpool-II 24 | pg_monz 2.0 now supports monitoring of pgpool-II which is a dedicated middleware for PostgreSQL. 25 | Various types of monitoring and triggers for the main features of pgpool-II such as Connection Pooling, Replication, In memory query Cache, Load Balance, Automatically Failover of PostgreSQL are provided. 26 | 27 | Please see [pgpool-II user manual](http://www.pgpool.net/docs/latest/pgpool-en.html), [pgpool Wiki](http://www.pgpool.net/mediawiki/index.php/Main_Page) for more detailed informations. 28 | 29 | 30 | ### Support for monitoring of cluster system with PostgreSQL + pgpool-II 31 | And more, it make it possible to monitor a cluster system which is configured with PostgreSQL Streaming replication and pgpool-II or pgpol-II watchdog which add high availability to themselves. 32 | Useful triggers which can detects the occurence of split brain, failover are provided through monitoring of postgres, pgpool-II processes. 33 | 34 | 35 | ### Group items 36 | Monitoring items are grouped by each application to clarify them. 37 | The following are main applications. 38 | 39 | 40 | #### Applications | PostgreSQL 41 | |application name |summary of monitoring | 42 | |:------------------|-------------------------------------------------------------------------------------------------| 43 | |pg.transactions |Connection count, state to PostgreSQL, the number of commited, rolled back transactions | 44 | |pg.log |log monitoring for PostgreSQL | 45 | |pg.size |garbage ratio, DB size | 46 | |pg.slow_query |slow query count which exceeds the threshold value | 47 | |pg.sr.status |conflict count, write block existence or non-existence, process count using Streaming Replication| 48 | |pg.status |PostgreSQL processes working state | 49 | |pg.stat_replication|delay of replication data propagation using Streaming Replication | 50 | |pg.cluster.status |PostgreSQL processes count as a cluster | 51 | 52 | 53 | #### Applications | pgpool-II 54 | |application name |summary of monitoring | 55 | |:------------------|-------------------------------------------------------------------------------------------------| 56 | |pgpool.cache |cash informations using In Memory query Cache | 57 | |pgpool.connections |frontend, backend connection count through pgpool-II | 58 | |pgpool.log |log monitoring for pgpool-II | 59 | |pgpool.nodes |backend state, load balance ratio and replication delay viewed from pgpool-II | 60 | |pgpool.status |pgpool-II processes working state, vip existence or non-existence | 61 | |pgpool.watchdog |pgpool-II processes working state, vip existence or non-existence as a cluster | 62 | 63 | 64 | ### Improve performance of gathering monitoring items 65 | Previously, pg_monz accesses the monitoring DB every when gathering one monitoring item about DB, which may affect the performance of monitoring DB. 66 | With this update, to reduce the frequency of DB accesse, pg_monz gathers collectable monitoring items all at once. 67 | 68 | 69 | System requirements 70 | ------------------- 71 | pg_monz requires the following software products: 72 | 73 | * Zabbix server, zabbix agent, zabbix sender 2.0 or later 74 | * PostgreSQL 9.2 or later 75 | * pgpool-II 3.4.0 or later 76 | 77 | 78 | Installation and usage 79 | ---------------------- 80 | Please see the included quick-install.txt. 81 | pg_monz 2.0 does not have backward compatibility with the 1.0. When upgrading from 1.0, please install the new version again. 82 | 83 | 84 | License 85 | ------- 86 | pg_monz is distributed under the Apache License Version 2.0. 87 | See the LICENSE file for details. 88 | 89 | Copyright (C) 2013-2021 SRA OSS, Inc. Japan All Rights Reserved. 90 | Copyright (C) 2013-2021 TIS Inc. All Rights Reserved. 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **2021年10月31日をもって、pg_monzのメンテナンスを終了しました。** 2 | 3 | pg_monz 2.0 4 | ============================ 5 | pg_monz (PostgreSQL monitoring template for Zabbix) は、Zabbix で PostgreSQL の各種監視を行うためのテンプレートで、 6 | PostgreSQL の死活監視、リソース監視、性能監視などが行えます。 7 | また、Zabbix のディスカバリ機能を利用し、データベースやテーブルを自動検出し、自動で監視を開始することができます。 8 | 9 | 10 | 1.0 からの主な変更点 11 | -------------------- 12 | 1.0 からの主な変更点は以下の通りです。 13 | 14 | 15 | ### PostgreSQL ストリーミングレプリケーションの監視に対応 16 | PostgreSQL の組み込み機能であるストリーミングレプリケーションを利用した DB 構成の監視がサポートされました。 17 | Primary / Standby サーバの死活監視や、レプリケーション先へのデータ伝搬の遅延状況、Primary と Standby の DB 操作によって発生する可能性のあるコンフリクト状況などの監視が行えます。 18 | また、同期レプリケーション実行時に Standby サーバの障害によって発生する書き込みブロックを検知するトリガーが設定されています。 19 | 20 | 21 | ### pgpool-II の監視に対応 22 | PostgreSQL 専用ミドルウェアである pgpool-II の監視がサポートされました。 23 | pgpool-II の主な機能である、コネクションプーリング・レプリケーション・インメモリクエリキャッシュ・負荷分散・PostgreSQL の自動フェイルオーバに対応した各種監視項目およびトリガーが設定されています。 24 | 25 | pgpool-II に関する詳細な情報は、[pgpool-II ユーザマニュアル](http://www.pgpool.net/mediawiki/jp/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8)、[Pgpool Wiki](http://www.pgpool.net/mediawiki/jp/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8) を参照してください。 26 | 27 | 28 | ### PostgresQL + pgpool-II クラスタ構成の監視に対応 29 | PostgreSQL のストリーミングレプリケーション、または pgpool-II や pgpool-II 自身の冗長化を行う watchdog 機能を利用している複数のサーバを 1 つのクラスタ構成とした監視も可能です。 30 | Postgres、pgpoo-II プロセスの監視を通して、スプリットブレインの検知や、フェイルオーバを検知するトリガーが設定されています。 31 | 32 | 33 | ### 監視項目のグルーピング 34 | 監視項目がアプリケーション毎にグルーピングし、わかりやすく整理されました。 35 | 主なアプリケーションは以下の通りです。 36 | 37 | 38 | #### PostgreSQL の監視に関連するアプリケーション 39 | |アプリケーション名 |監視内容の概要 | 40 | |:------------------|----------------------------------------------------------------------------------------| 41 | |pg.transactions |PostgreSQL への接続数、接続状態、トランザクションのコミット、ロールバック数 | 42 | |pg.log |PostgreSQL のログ監視 | 43 | |pg.size |各 DB のサイズと不要領域の回収率 | 44 | |pg.slow_query |設定した閾値を超えたスロークエリ数 | 45 | |pg.sr.status |ストリーミングレプリケーション構成時のコンフリクト数、書き込むブロックの有無、プロセス数| 46 | |pg.status |PostgreSQL のプロセス稼働状況 | 47 | |pg.stat_replication|ストリーミングレプリケーション構成時のデータ伝搬の遅延状況 | 48 | |pg.cluster.status |クラスタ単位の PostgreSQL プロセス数 | 49 | 50 | 51 | #### pgpool-II の監視に関連するアプリケーション 52 | |アプリケーション名 |監視内容の概要 | 53 | |:------------------|----------------------------------------------------------------------------------------| 54 | |pgpool.cache |インメモリクエリキャッシュ使用時のキャッシュ状況 | 55 | |pgpool.connections |pgpool-II を介したフロントエンド、バックエンドのコネクション数 | 56 | |pgpool.log |pgpool-II のログ監視 | 57 | |pgpool.nodes |pgpool-II から見た各バックエンドの稼働状況、負荷分散の比率、レプリケーションの遅延量 | 58 | |pgpool.status |pgpool-II のプロセス稼働状況、仮想 IP 保持状況 | 59 | |pgpool.watchdog |クラスタ単位の pgpool-II のプロセス稼働状況、仮想 IP 保持状況 | 60 | 61 | 62 | ### アイテム収集時のパフォーマンス改善 63 | 1.0 までは、DB に関する監視アイテムのデータを 1 つ取得する都度 DB に接続を行っており、監視対象の DB 負荷に影響を与える可能性がありました。 64 | 2.0 では、まとめて取得可能なデータは 1 度の DB 接続で取得するようになり、DB 接続頻度が減少しました。 65 | 66 | 67 | 動作環境 68 | -------- 69 | pg_monz を使用するには以下のソフトウェアが必要です。 70 | 71 | * Zabbix server, zabbix agent, zabbix sender 2.0 以上 72 | * PostgreSQL 9.2 以上 73 | * pgpool-II 3.4.0 以上 74 | 75 | 76 | インストール方法、使用方法 77 | -------------------------- 78 | 同梱の quick-install.txt を参照してください。 79 | 1.0 との後方互換性は保たれていません。1.0 からアップグレードする場合は 2.0 を再インストールしてください。 80 | 81 | 82 | ライセンス 83 | ---------- 84 | pg_monz は Apache License Version 2.0 の元で配布されています。 85 | ライセンスの内容は LICENSE ファイルを参照して下さい。 86 | 87 | Copyright (C) 2013-2021 SRA OSS, Inc. Japan All Rights Reserved. 88 | Copyright (C) 2013-2021 TIS Inc. All Rights Reserved. 89 | -------------------------------------------------------------------------------- /pg_monz/template/Template_App_PostgreSQL_SR.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3.0 4 | 2018-10-30T02:50:54Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 1099 | 1100 | 1101 | 1102 | {Template App PostgreSQL SR:psql.block_query.last(0)}=0 1103 | blocking write query because sync standby is not exists on {HOST.NAME} 1104 | 1105 | 0 1106 | 4 1107 | 1108 | 0 1109 | 1110 | 1111 | 1112 | 1113 | -------------------------------------------------------------------------------- /pg_monz/template/Template_App_PostgreSQL_SR_Cluster.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2015-03-10T07:20:01Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 165 | 166 | 167 | 168 | {Template App PostgreSQL SR Cluster:grpsum[{$PG_HOST_GROUP},"psql.running[{$PGSCRIPTDIR},{$PGSCRIPT_CONFDIR}]",last,].last(0)}=0 169 | All PostgreSQL servers are dead on {$PG_HOST_GROUP} group 170 | 171 | 0 172 | 4 173 | 174 | 0 175 | 176 | 177 | 178 | {Template App PostgreSQL SR Cluster:grpsum[{$PG_HOST_GROUP},"psql.primary_server[{$PGSCRIPTDIR},{$PGSCRIPT_CONFDIR}]",last,0].last(0)}=0 179 | PostgreSQL primary server is down on {$PG_HOST_GROUP} group 180 | 181 | 0 182 | 4 183 | 184 | 0 185 | 186 | 187 | 188 | {Template App PostgreSQL SR Cluster:grpsum[{$PG_HOST_GROUP},"psql.primary_server[{$PGSCRIPTDIR},{$PGSCRIPT_CONFDIR}]",last,0].count(#2,2,"ge")}>1 189 | PostgreSQL split-brain is occurring on {$PG_HOST_GROUP} group 190 | 191 | 0 192 | 4 193 | 194 | 0 195 | 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /pg_monz/template/Template_App_pgpool-II.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2015-03-10T07:20:17Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 1135 | 1136 | 1137 | 1138 | {Template App pgpool-II:pgpool.have_delegate_ip[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}].last(#2)}=0 & {Template App pgpool-II:pgpool.have_delegate_ip[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}].last(#1)}=1 1139 | pgpool-II server promote to master with activating delegate_ip on {HOST.NAME} 1140 | 1141 | 0 1142 | 1 1143 | 1144 | 0 1145 | 1146 | 1147 | 1148 | {Template App pgpool-II:pgpool.running[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}].last(0)}#1 1149 | pgpool-II service is not running on {HOST.NAME} 1150 | 1151 | 0 1152 | 4 1153 | 1154 | 0 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | pgpool-II frontend connections 1161 | 900 1162 | 200 1163 | 0.0000 1164 | 100.0000 1165 | 1 1166 | 1 1167 | 0 1168 | 1 1169 | 0 1170 | 0.0000 1171 | 0.0000 1172 | 0 1173 | 0 1174 | 0 1175 | 0 1176 | 1177 | 1178 | 0 1179 | 0 1180 | 00C800 1181 | 0 1182 | 2 1183 | 0 1184 | 1185 | Template App pgpool-II 1186 | pgpool.frontend.max 1187 | 1188 | 1189 | 1190 | 2 1191 | 0 1192 | 0000C8 1193 | 0 1194 | 2 1195 | 0 1196 | 1197 | Template App pgpool-II 1198 | pgpool.frontend.used 1199 | 1200 | 1201 | 1202 | 1 1203 | 0 1204 | C80000 1205 | 0 1206 | 2 1207 | 0 1208 | 1209 | Template App pgpool-II 1210 | pgpool.frontend.empty 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | pgpool-II memory cache activity 1217 | 900 1218 | 200 1219 | 0.0000 1220 | 100.0000 1221 | 1 1222 | 1 1223 | 0 1224 | 1 1225 | 0 1226 | 0.0000 1227 | 0.0000 1228 | 0 1229 | 0 1230 | 0 1231 | 0 1232 | 1233 | 1234 | 1 1235 | 0 1236 | 0000C8 1237 | 0 1238 | 2 1239 | 0 1240 | 1241 | Template App pgpool-II 1242 | pgpool.cache.used_cache_entries_size 1243 | 1244 | 1245 | 1246 | 2 1247 | 0 1248 | C80000 1249 | 0 1250 | 2 1251 | 0 1252 | 1253 | Template App pgpool-II 1254 | pgpool.cache.fragment_cache_entries_size 1255 | 1256 | 1257 | 1258 | 0 1259 | 0 1260 | 00C800 1261 | 0 1262 | 2 1263 | 0 1264 | 1265 | Template App pgpool-II 1266 | pgpool.cache.free_cache_entries_size 1267 | 1268 | 1269 | 1270 | 3 1271 | 0 1272 | C800C8 1273 | 1 1274 | 2 1275 | 0 1276 | 1277 | Template App pgpool-II 1278 | pgpool.cache.cache_hit_ratio 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | -------------------------------------------------------------------------------- /pg_monz/template/Template_App_pgpool-II_watchdog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2.0 4 | 2015-03-10T07:20:40Z 5 | 6 | 7 | Templates 8 | 9 | 10 | 11 | 122 | 123 | 124 | 125 | {Template App pgpool-II watchdog:grpsum[{$PGPOOL_HOST_GROUP},"pgpool.running[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}]",last,].last(0)}=0 126 | All pgpool-II servers are dead on {$PGPOOL_HOST_GROUP} group 127 | 128 | 0 129 | 4 130 | 131 | 0 132 | 133 | 134 | 135 | {Template App pgpool-II watchdog:grpsum[{$PGPOOL_HOST_GROUP},"pgpool.have_delegate_ip[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}]",last,0].last(0)}=0 136 | pgpool-II delegate_ip is not exists on {$PGPOOL_HOST_GROUP} group 137 | 138 | 0 139 | 4 140 | 141 | 0 142 | 143 | 144 | 145 | {Template App pgpool-II watchdog:grpsum[{$PGPOOL_HOST_GROUP},"pgpool.have_delegate_ip[{$PGPOOLSCRIPTDIR},{$PGPOOLSCRIPT_CONFDIR}]",last,0].count(#2,2,"ge")}>1 146 | pgpool-II split-brain is occurring on {$PGPOOL_HOST_GROUP} group 147 | 148 | 0 149 | 4 150 | 151 | 0 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_dbname.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get list of Database Name which you want to monitor. 4 | # The default settings are excepted template databases(template0/template1). 5 | # 6 | # :Example 7 | # 8 | # If you want to monitor "foo" and "bar" databases, you set the GETDB as 9 | # GETDB="select datname from pg_database where datname in ('foo','bar');" 10 | 11 | PGSHELL_CONFDIR="$1" 12 | 13 | GETDB="select datname from pg_database where datistemplate = 'f';" 14 | 15 | # Load the pgsql connection option parameters. 16 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 17 | 18 | result=$(psql -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -t -X -c "${GETDB}" 2>&1) 19 | if [ $? -ne 0 ]; then 20 | echo "$result" 21 | exit 22 | fi 23 | 24 | IFS=$'\n' 25 | for dbname in $result; do 26 | dblist="$dblist,"'{"{#DBNAME}":"'${dbname# }'"}' 27 | done 28 | echo '{"data":['${dblist#,}' ]}' 29 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_dbname_table.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # For using this rules, you set the status to enable from 6 | # [Configuration]->[Hosts]->[Discovery]->[DB and Table Name List] 7 | # at Zabbix WEB. 8 | 9 | # Get list of Database Name which you want to monitor. 10 | # The default settings are excepted template databases(template0/template1). 11 | # 12 | # :Customize Example 13 | # 14 | # For "foo" and "bar" databases, set the GETDB as 15 | # GETDB="select datname from pg_database where datname in ('foo','bar');" 16 | 17 | GETDB="select datname from pg_database where datistemplate = 'f';" 18 | 19 | # Get List of Table Name 20 | # Using the default setting, Zabbix make a discovery "ALL" user tables. 21 | # If you want to specify the tables, you can change the $GETTABLE query. 22 | # 23 | # :Customize Example 24 | # 25 | # For pgbench tables, set the GETTABLE as 26 | #GETTABLE="select \ 27 | # row_to_json(t) \ 28 | # from ( 29 | # select current_database() as "{#DBNAME}\",schemaname as \"{#SCHEMANAME}\",tablename as \"{#TABLENAME}\" \ 30 | # from \ 31 | # pg_tables \ 32 | # where \ 33 | # schemaname not in ('pg_catalog','information_schema') \ 34 | # and \ 35 | # tablename in ('pgbench_accounts','pgbench_branches','pgbench_history','pgbench_tellers') \ 36 | # ) as t" 37 | 38 | GETTABLE="select row_to_json(t) from (select current_database() as \"{#DBNAME}\",schemaname as \"{#SCHEMANAME}\",tablename as \"{#TABLENAME}\" from pg_tables where schemaname not in ('pg_catalog','information_schema')) as t" 39 | 40 | # Load the psql connection option parameters. 41 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 42 | 43 | # This low level discovery rules are disabled by deafult. 44 | dbname_list=$(psql -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -t -X -c "${GETDB}" 2>&1) 45 | if [ $? -ne 0 ]; then 46 | echo "$dbname_list" 47 | exit 48 | fi 49 | 50 | IFS=$'\n' 51 | for dbname in $dbname_list; do 52 | tablename_list=$(psql -h $PGHOST -p $PGPORT -U $PGROLE -d ${dbname# } -t -X -c "${GETTABLE}" 2>&1) 53 | if [ $? -ne 0 ]; then 54 | echo "$tablename_list" 55 | exit 56 | fi 57 | for tablename in $tablename_list; do 58 | dblist="$dblist,"${tablename# } 59 | done 60 | done 61 | echo '{"data":['${dblist#,}' ]}' 62 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_pgpool_backend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get list of pgpool-II database backend name which you want to monitor. 4 | 5 | PGPOOLSHELL_CONFDIR="$1" 6 | 7 | POOL_STATUS="show pool_status" 8 | 9 | # Load the pgpool connection option parameters. 10 | source $PGPOOLSHELL_CONFDIR/pgpool_funcs.conf 11 | 12 | config=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${POOL_STATUS}" 2>&1) 13 | if [ $? -ne 0 ]; then 14 | echo "$config" 15 | exit 16 | fi 17 | 18 | replication_mode=`echo "$config" | awk -F, '$1 ~ /replication_mode/ {print $2}'` 19 | 20 | if [ $replication_mode == 1 ]; then 21 | MODE=replication 22 | else 23 | master_slave_mode=`echo "$config" | awk -F, '$1 ~ /master_slave_mode/ {print $2}'` 24 | if [ $master_slave_mode == 1 ]; then 25 | MODE=`echo "$config" | awk -F, '$1 ~ /master_slave_sub_mode/ {print $2}'` 26 | else 27 | MODE=connection_pool 28 | fi 29 | fi 30 | 31 | echo "{\"data\":[{\"{#MODE}\":\"$MODE\"} ]}" 32 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_pgpool_backend_ip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get list of pgpool-II database backend name which you want to monitor. 4 | 5 | PGPOOLSHELL_CONFDIR="$1" 6 | 7 | POOL_STATUS="show pool_status" 8 | 9 | # Load the pgpool connection option parameters. 10 | source $PGPOOLSHELL_CONFDIR/pgpool_funcs.conf 11 | 12 | config=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${POOL_STATUS}" 2>&1) 13 | if [ $? -ne 0 ]; then 14 | echo "$config" 15 | exit 16 | fi 17 | 18 | replication_mode=`echo "$config" | awk -F, '$1 ~ /replication_mode/ {print $2}'` 19 | 20 | if [ $replication_mode == 1 ]; then 21 | MODE=replication 22 | else 23 | master_slave_mode=`echo "$config" | awk -F, '$1 ~ /master_slave_mode/ {print $2}'` 24 | if [ $master_slave_mode == 1 ]; then 25 | MODE=`echo "$config" | awk -F, '$1 ~ /master_slave_sub_mode/ {print $2}'` 26 | else 27 | MODE=connection_pool 28 | fi 29 | fi 30 | 31 | BACKENDDB="show pool_nodes" 32 | result=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${BACKENDDB}" 2>&1) 33 | if [ $? -ne 0 ]; then 34 | echo "$result" 35 | exit 36 | fi 37 | 38 | IFS=$'\n' 39 | for backendrecord in $result; do 40 | BACKENDID=`echo $backendrecord | awk -F, '{print $1}'` 41 | BACKENDNAME=`echo $backendrecord | awk -F, '{print $2}'` 42 | BACKENDPORT=`echo $backendrecord | awk -F, '{print $3}'` 43 | BACKEND=ID_${BACKENDID}_${BACKENDNAME}_${BACKENDPORT} 44 | backendlist="$backendlist,"'{"{#BACKEND}":"'$BACKEND'"}' 45 | done 46 | echo '{"data":['${backendlist#,}' ]}' 47 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_sr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | GETROW="select count(*) from pg_stat_replication" 6 | 7 | # Load the psql connection option parameters. 8 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 9 | 10 | result=$(psql -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -t -X -c "$GETROW" 2>&1) 11 | if [ $? -ne 0 ]; then 12 | echo "$result" 13 | exit 14 | fi 15 | 16 | if [ $result -ge 1 ]; then 17 | echo '{"data":[{"{#MODE}":"streaming"} ]}' 18 | else 19 | echo '{"data":[ ]}' 20 | fi 21 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/find_sr_client_ip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | GETTABLE="select row_to_json(t) from (select client_addr as \"{#SRCLIENT}\" from pg_stat_replication) as t" 6 | 7 | # Load the psql connection option parameters. 8 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 9 | 10 | result=$(psql -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -t -X -c "${GETTABLE}" 2>&1) 11 | if [ $? -ne 0 ]; then 12 | echo "$result" 13 | exit 14 | fi 15 | 16 | IFS=$'\n' 17 | for row in $result; do 18 | sr_client_list="$sr_client_list,"${row# } 19 | done 20 | echo '{"data":['${sr_client_list#,}' ]}' 21 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgpool_backend_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get status of pgpool-II database backend which you want to monitor. 4 | 5 | APP_NAME="$1" 6 | PGPOOLSHELL_CONFDIR="$2" 7 | HOST_NAME="$3" 8 | ZABBIX_AGENTD_CONF="$4" 9 | 10 | BACKENDDB="show pool_nodes" 11 | TIME=` date +%s` 12 | 13 | # Load the pgpool connection option parameters. 14 | source $PGPOOLSHELL_CONFDIR/pgpool_funcs.conf 15 | 16 | IFS=$'\n' 17 | 18 | case "$APP_NAME" in 19 | pgpool.nodes) 20 | pool_nodes=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${BACKENDDB}" 2>&1) 21 | 22 | if [ $? -ne 0 ]; then 23 | echo "$pool_nodes" 24 | exit 25 | fi 26 | 27 | sending_data=$(for backendrecord in $pool_nodes; do 28 | BACKENDID=`echo $backendrecord | awk -F, '{print $1}'` 29 | BACKENDNAME=`echo $backendrecord | awk -F, '{print $2}'` 30 | BACKENDPORT=`echo $backendrecord | awk -F, '{print $3}'` 31 | BACKEND=ID_${BACKENDID}_${BACKENDNAME}_${BACKENDPORT} 32 | BACKENDSTATE=`echo $backendrecord | awk -F, '{print $4}'` 33 | BACKENDWEIGHT=`echo $backendrecord | awk -F, '{print $5}'` 34 | BACKENDROLE=`echo $backendrecord | awk -F, '{print $6}'` 35 | BACKENDREPLICATIONDELAY=`echo $backendrecord | awk -F, '{print $9}'` 36 | BACKENDLASTSTATUSCHANGE=`echo $backendrecord | awk -F, '{print $10}'` 37 | echo -e "\"$HOST_NAME\" pgpool.backend.status[${BACKEND}] $TIME $BACKENDSTATE" 38 | echo -e "\"$HOST_NAME\" pgpool.backend.weight[${BACKEND}] $TIME $BACKENDWEIGHT" 39 | echo -e "\"$HOST_NAME\" pgpool.backend.role[${BACKEND}] $TIME $BACKENDROLE" 40 | if [ ! -z "$BACKENDREPLICATIONDELAY" ]; then 41 | echo -e "\"$HOST_NAME\" pgpool.backend.replication_delay[${BACKEND}] $TIME $BACKENDREPLICATIONDELAY" 42 | fi 43 | if [ ! -z "$BACKENDLASTSTATUSCHANGE" ]; then 44 | echo -e "\"$HOST_NAME\" pgpool.backend.last_status_change[${BACKEND}] $TIME $BACKENDLASTSTATUSCHANGE" 45 | fi 46 | done 47 | ) 48 | ;; 49 | *) 50 | echo "'$APP_NAME' did not match anything." 51 | exit 52 | ;; 53 | esac 54 | 55 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 56 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 57 | if [ -n "$response" ]; then 58 | echo "$response" 59 | else 60 | echo "$result" 61 | fi 62 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgpool_cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get list of pgpool-II database backend name which you want to monitor. 4 | 5 | APP_NAME="$1" 6 | PGPOOLSHELL_CONFDIR="$2" 7 | HOST_NAME="$3" 8 | ZABBIX_AGENTD_CONF="$4" 9 | 10 | POOL="show pool_cache" 11 | TIME=` date +%s` 12 | 13 | # Load the pgpool connection option parameters. 14 | source $PGPOOLSHELL_CONFDIR/pgpool_funcs.conf 15 | 16 | case "$APP_NAME" in 17 | pgpool.cache) 18 | pool_cache=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${POOL}" 2>&1) 19 | 20 | if [ $? -ne 0 ]; then 21 | echo "$pool_cache" 22 | exit 23 | fi 24 | 25 | num_cache_hits=`echo "$pool_cache" | awk -F, '{print $1}'` 26 | num_selects=`echo "$pool_cache" | awk -F, '{print $2}'` 27 | cache_hit_ratio=`echo "$pool_cache" | awk -F, '{print $3 * 100}'` 28 | num_hash_entries=`echo "$pool_cache" | awk -F, '{print $4}'` 29 | used_hash_entries=`echo "$pool_cache" | awk -F, '{print $5}'` 30 | num_cache_entries=`echo "$pool_cache" | awk -F, '{print $6}'` 31 | used_cache_entries_size=`echo "$pool_cache" | awk -F, '{print $7}'` 32 | free_cache_entries_size=`echo "$pool_cache" | awk -F, '{print $8}'` 33 | fragment_cache_entries_size=`echo "$pool_cache" | awk -F, '{print $9}'` 34 | sending_data=$( 35 | echo -e \"$HOST_NAME\" pgpool.cache.num_cache_hits $TIME $num_cache_hits 36 | echo -e \"$HOST_NAME\" pgpool.cache.num_selects $TIME $num_selects 37 | echo -e \"$HOST_NAME\" pgpool.cache.cache_hit_ratio $TIME $cache_hit_ratio 38 | echo -e \"$HOST_NAME\" pgpool.cache.num_hash_entries $TIME $num_hash_entries 39 | echo -e \"$HOST_NAME\" pgpool.cache.used_hash_entries $TIME $used_hash_entries 40 | echo -e \"$HOST_NAME\" pgpool.cache.num_cache_entries $TIME $num_cache_entries 41 | echo -e \"$HOST_NAME\" pgpool.cache.used_cache_entries_size $TIME $used_cache_entries_size 42 | echo -e \"$HOST_NAME\" pgpool.cache.free_cache_entries_size $TIME $free_cache_entries_size 43 | echo -e \"$HOST_NAME\" pgpool.cache.fragment_cache_entries_size $TIME $fragment_cache_entries_size 44 | ) 45 | ;; 46 | *) 47 | echo "'$APP_NAME' did not match anything." 48 | exit 49 | ;; 50 | esac 51 | 52 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 53 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 54 | if [ -n "$response" ]; then 55 | echo "$response" 56 | else 57 | echo "$result" 58 | fi 59 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgpool_connections.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get list of pgpool-II database backend name which you want to monitor. 4 | 5 | APP_NAME="$1" 6 | PGPOOLSHELL_CONFDIR="$2" 7 | HOST_NAME="$3" 8 | ZABBIX_AGENTD_CONF="$4" 9 | 10 | POOL="show pool_pools" 11 | TIME=` date +%s` 12 | 13 | # Load the pgpool connection option parameters. 14 | source $PGPOOLSHELL_CONFDIR/pgpool_funcs.conf 15 | 16 | case "$APP_NAME" in 17 | pgpool.connections) 18 | pool_connections=$(psql -A --field-separator=',' -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE -d $PGPOOLDATABASE -t -X -c "${POOL}" 2>&1) 19 | 20 | if [ $? -ne 0 ]; then 21 | echo "$pool_connections" 22 | exit 23 | fi 24 | 25 | valid_num=`echo "$pool_connections" | wc -l` 26 | frontend_used=`echo "$pool_connections" | awk -F, '$12 !~ /^0$/ {print $12,$1}' | uniq | wc -l` 27 | backend_used=`echo "$pool_connections" | awk -F, '$11 !~ /^0$/ {print $11}' | wc -l` 28 | frontend_total=`echo "$pool_connections" | awk -F, '{print $1}' | uniq |wc -l` 29 | sending_data=$( 30 | echo -e \"$HOST_NAME\" pgpool.frontend.used $TIME $frontend_used 31 | echo -e \"$HOST_NAME\" pgpool.frontend.max $TIME $frontend_total 32 | echo -e \"$HOST_NAME\" pgpool.frontend.empty $TIME $(($frontend_total - $frontend_used)) 33 | echo -e \"$HOST_NAME\" pgpool.backend.used $TIME $backend_used 34 | ) 35 | ;; 36 | *) 37 | echo "'$APP_NAME' did not match anything." 38 | exit 39 | ;; 40 | esac 41 | 42 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 43 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 44 | if [ -n "$response" ]; then 45 | echo "$response" 46 | else 47 | echo "$result" 48 | fi 49 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgpool_delegate_ip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # Load the psql connection option parameters. 6 | source $PGSHELL_CONFDIR/pgpool_funcs.conf 7 | 8 | if [ ! -n "$PGPOOLCONF" ]; then 9 | echo 0 10 | exit 11 | fi 12 | 13 | if [ ! -e "$PGPOOLCONF" ]; then 14 | echo 0 15 | exit 16 | fi 17 | 18 | delegate_ip=`cat $PGPOOLCONF | grep delegate_IP | awk -F\' '{print $2}'` 2>/dev/null 19 | 20 | if [ ! -n "$delegate_ip" ]; then 21 | echo 0 22 | exit 23 | fi 24 | 25 | num_ip=`ip addr show | grep $delegate_ip | wc -l` 26 | echo $num_ip 27 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgpool_simple.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # Load the psql connection option parameters. 6 | source $PGSHELL_CONFDIR/pgpool_funcs.conf 7 | 8 | psql -t -X -A -h $PGPOOLHOST -p $PGPOOLPORT -U $PGPOOLROLE $PGPOOLDATABASE -c "select 1" 2>/dev/null 9 | if [ $? -ne 0 ]; then 10 | echo 0 11 | fi 12 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_db_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_NAME="$1" 4 | PGSHELL_CONFDIR="$2" 5 | HOST_NAME="$3" 6 | ZABBIX_AGENTD_CONF="$4" 7 | DBNAME="$5" 8 | 9 | TIMESTAMP_QUERY='extract(epoch from now())::int' 10 | 11 | # Load the psql connection option parameters. 12 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 13 | 14 | case "$APP_NAME" in 15 | pg.stat_database) 16 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 17 | "select '\"$HOST_NAME\"', 'psql.db_connections[$DBNAME]', $TIMESTAMP_QUERY, (select numbackends from pg_stat_database where datname = '$DBNAME') \ 18 | union all \ 19 | select '\"$HOST_NAME\"', 'psql.cachehit_ratio[$DBNAME]', $TIMESTAMP_QUERY, (SELECT round(blks_hit*100/(blks_hit+blks_read), 2) AS cache_hit_ratio FROM pg_stat_database WHERE datname = '$DBNAME' and blks_read > 0 union all select 0.00 AS cache_hit_ratio order by cache_hit_ratio desc limit 1) \ 20 | union all \ 21 | select '\"$HOST_NAME\"', 'psql.db_tx_commited[$DBNAME]', $TIMESTAMP_QUERY, (select xact_commit from pg_stat_database where datname = '$DBNAME') \ 22 | union all \ 23 | select '\"$HOST_NAME\"', 'psql.db_deadlocks[$DBNAME]', $TIMESTAMP_QUERY, (select deadlocks from pg_stat_database where datname = '$DBNAME') \ 24 | union all \ 25 | select '\"$HOST_NAME\"', 'psql.db_tx_rolledback[$DBNAME]', $TIMESTAMP_QUERY, (select xact_rollback from pg_stat_database where datname = '$DBNAME') \ 26 | union all \ 27 | select '\"$HOST_NAME\"', 'psql.db_temp_bytes[$DBNAME]', $TIMESTAMP_QUERY, (select temp_bytes from pg_stat_database where datname = '$DBNAME') \ 28 | union all \ 29 | select '\"$HOST_NAME\"', 'psql.db_deleted[$DBNAME]', $TIMESTAMP_QUERY, (select tup_deleted from pg_stat_database where datname = '$DBNAME') \ 30 | union all \ 31 | select '\"$HOST_NAME\"', 'psql.db_fetched[$DBNAME]', $TIMESTAMP_QUERY, (select tup_fetched from pg_stat_database where datname = '$DBNAME') \ 32 | union all \ 33 | select '\"$HOST_NAME\"', 'psql.db_inserted[$DBNAME]', $TIMESTAMP_QUERY, (select tup_inserted from pg_stat_database where datname = '$DBNAME') \ 34 | union all \ 35 | select '\"$HOST_NAME\"', 'psql.db_returned[$DBNAME]', $TIMESTAMP_QUERY, (select tup_returned from pg_stat_database where datname = '$DBNAME') \ 36 | union all \ 37 | select '\"$HOST_NAME\"', 'psql.db_updated[$DBNAME]', $TIMESTAMP_QUERY, (select tup_updated from pg_stat_database where datname = '$DBNAME')" 2>&1 38 | ) 39 | ;; 40 | *) 41 | echo "'$APP_NAME' did not match anything." 42 | exit 43 | ;; 44 | esac 45 | 46 | if [ $? -ne 0 ]; then 47 | echo "$sending_data" 48 | exit 49 | fi 50 | 51 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 52 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 53 | if [ -n "$response" ]; then 54 | echo "$response" 55 | else 56 | echo "$result" 57 | fi 58 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_primary.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # Load the psql connection option parameters. 6 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 7 | 8 | result=$(psql -A -t -X -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -c "select (NOT(pg_is_in_recovery()))::int" 2>&1) 9 | echo "$result" 10 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_server_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================================================================== 3 | # GLOBAL DECLARATIONS 4 | #=============================================================================== 5 | APP_NAME="$1" 6 | PGSHELL_CONFDIR="$2" 7 | HOST_NAME="$3" 8 | ZABBIX_AGENTD_CONF="$4" 9 | PARAM1="$5" 10 | 11 | # Load the psql connection option parameters. 12 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 13 | 14 | TIMESTAMP_QUERY='extract(epoch from now())::int' 15 | 16 | PGVERSION=$(psql -A -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c "SELECT current_setting('server_version_num')") 17 | 18 | if [ $PGVERSION -ge 100000 ]; then 19 | CONN_COND="where backend_type = 'client backend'" 20 | LOCK_COND="and wait_event_type like '%Lock%'" 21 | elif [ $PGVERSION -ge 90600 ]; then 22 | CONN_COND='' 23 | LOCK_COND="where wait_event_type like '%Lock%'" 24 | else 25 | CONN_COND='' 26 | LOCK_COND="where waiting = 'true'" 27 | fi 28 | 29 | #=============================================================================== 30 | # MAIN SCRIPT 31 | #=============================================================================== 32 | case "$APP_NAME" in 33 | pg.transactions) 34 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 35 | "select '\"$HOST_NAME\"', 'psql.tx_commited', $TIMESTAMP_QUERY, (select sum(xact_commit) from pg_stat_database) \ 36 | union all \ 37 | select '\"$HOST_NAME\"', 'psql.tx_rolledback', $TIMESTAMP_QUERY, (select sum(xact_rollback) from pg_stat_database) \ 38 | union all \ 39 | select '\"$HOST_NAME\"', 'psql.active_connections', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'active') \ 40 | union all \ 41 | select '\"$HOST_NAME\"', 'psql.server_connections', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity $CONN_COND) \ 42 | union all \ 43 | select '\"$HOST_NAME\"', 'psql.idle_connections', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'idle') \ 44 | union all \ 45 | select '\"$HOST_NAME\"', 'psql.idle_tx_connections', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'idle in transaction') \ 46 | union all \ 47 | select '\"$HOST_NAME\"', 'psql.locks_waiting', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity $CONN_COND $LOCK_COND) \ 48 | union all \ 49 | select '\"$HOST_NAME\"', 'psql.server_maxcon', $TIMESTAMP_QUERY, (select setting::int from pg_settings where name = 'max_connections')" 2>&1 50 | ) 51 | ;; 52 | pg.bgwriter) 53 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 54 | "select '\"$HOST_NAME\"', 'psql.buffers_alloc', $TIMESTAMP_QUERY, (select buffers_alloc from pg_stat_bgwriter) \ 55 | union all \ 56 | select '\"$HOST_NAME\"', 'psql.buffers_backend', $TIMESTAMP_QUERY, (select buffers_backend from pg_stat_bgwriter) \ 57 | union all \ 58 | select '\"$HOST_NAME\"', 'psql.buffers_backend_fsync' , $TIMESTAMP_QUERY, (select buffers_backend_fsync from pg_stat_bgwriter) \ 59 | union all \ 60 | select '\"$HOST_NAME\"', 'psql.buffers_checkpoint', $TIMESTAMP_QUERY, (select buffers_checkpoint from pg_stat_bgwriter) \ 61 | union all \ 62 | select '\"$HOST_NAME\"', 'psql.buffers_clean', $TIMESTAMP_QUERY, (select buffers_clean from pg_stat_bgwriter) \ 63 | union all \ 64 | select '\"$HOST_NAME\"', 'psql.checkpoints_req', $TIMESTAMP_QUERY, (select checkpoints_req from pg_stat_bgwriter) \ 65 | union all \ 66 | select '\"$HOST_NAME\"', 'psql.checkpoints_timed', $TIMESTAMP_QUERY, (select checkpoints_timed from pg_stat_bgwriter) \ 67 | union all \ 68 | select '\"$HOST_NAME\"', 'psql.maxwritten_clean', $TIMESTAMP_QUERY, (select maxwritten_clean from pg_stat_bgwriter)" 2>&1 69 | ) 70 | ;; 71 | pg.slow_query) 72 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 73 | "select '\"$HOST_NAME\"', 'psql.slow_dml_queries', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'active' and now() - query_start > '$PARAM1 sec'::interval and query ~* '^(insert|update|delete)') \ 74 | union all \ 75 | select '\"$HOST_NAME\"', 'psql.slow_queries', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'active' and now() - query_start > '$PARAM1 sec'::interval) \ 76 | union all \ 77 | select '\"$HOST_NAME\"', 'psql.slow_select_queries', $TIMESTAMP_QUERY, (select count(*) from pg_stat_activity where state = 'active' and now() - query_start > '$PARAM1 sec'::interval and query ilike 'select%')" 2>&1 78 | ) 79 | ;; 80 | *) 81 | echo "'$APP_NAME' did not match anything." 82 | exit 83 | ;; 84 | esac 85 | 86 | if [ $? -ne 0 ]; then 87 | echo "$sending_data" 88 | exit 89 | fi 90 | 91 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 92 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 93 | if [ -n "$response" ]; then 94 | echo "$response" 95 | else 96 | echo "$result" 97 | fi 98 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_simple.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # Load the psql connection option parameters. 6 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 7 | 8 | psql -t -X -A -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -c "select 1" 2>/dev/null 9 | if [ $? -ne 0 ]; then 10 | echo 0 11 | fi 12 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_sr_server_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #=============================================================================== 3 | # GLOBAL DECLARATIONS 4 | #=============================================================================== 5 | APP_NAME="$1" 6 | PGSHELL_CONFDIR="$2" 7 | HOST_NAME="$3" 8 | ZABBIX_AGENTD_CONF="$4" 9 | 10 | TIMESTAMP_QUERY='extract(epoch from now())::int' 11 | 12 | # Load the psql connection option parameters. 13 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 14 | 15 | PGVERSION=$(psql -A -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c "SELECT current_setting('server_version_num')") 16 | 17 | if [ $PGVERSION -ge 100000 ]; then 18 | WRITE_DIFF_FUNC='pg_wal_lsn_diff(sent_lsn, write_lsn)' 19 | REPLAY_DIFF_FUNC='pg_wal_lsn_diff(sent_lsn, replay_lsn)' 20 | LAG_SQL=$(cat <<-EOS 21 | union all 22 | select '"$HOST_NAME"', 'psql.write_lag['||host(client_addr)||']', $TIMESTAMP_QUERY, extract(epoch from (coalesce(write_lag,'00:00:00')))::text as value from pg_stat_replication 23 | union all 24 | select '"$HOST_NAME"', 'psql.flush_lag['||host(client_addr)||']', $TIMESTAMP_QUERY, extract(epoch from (coalesce(flush_lag,'00:00:00')))::text as value from pg_stat_replication 25 | union all 26 | select '"$HOST_NAME"', 'psql.replay_lag['||host(client_addr)||']', $TIMESTAMP_QUERY, extract(epoch from (coalesce(replay_lag,'00:00:00')))::text as value from pg_stat_replication 27 | EOS 28 | ) 29 | else 30 | WRITE_DIFF_FUNC='pg_xlog_location_diff(sent_location, write_location)' 31 | REPLAY_DIFF_FUNC='pg_xlog_location_diff(sent_location, replay_location)' 32 | LAG_SQL='' 33 | fi 34 | 35 | #=============================================================================== 36 | # MAIN SCRIPT 37 | #=============================================================================== 38 | case "$APP_NAME" in 39 | pg.stat_replication) 40 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 41 | "select * from ( \ 42 | select '\"$HOST_NAME\"', 'psql.write_diff['||host(client_addr)||']', $TIMESTAMP_QUERY, $WRITE_DIFF_FUNC::text as value from pg_stat_replication \ 43 | union all \ 44 | select '\"$HOST_NAME\"', 'psql.replay_diff['||host(client_addr)||']', $TIMESTAMP_QUERY, $REPLAY_DIFF_FUNC::text as value from pg_stat_replication \ 45 | union all \ 46 | select '\"$HOST_NAME\"', 'psql.sync_priority['||host(client_addr)||']', $TIMESTAMP_QUERY, sync_priority::text as value from pg_stat_replication \ 47 | union all \ 48 | select '\"$HOST_NAME\"', 'psql.sync_state['||host(client_addr)||']', $TIMESTAMP_QUERY, sync_state::text as value from pg_stat_replication \ 49 | $LAG_SQL 50 | ) as t where value is not null" 2>&1 51 | ) 52 | ;; 53 | pg.sr.status) 54 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $PGDATABASE -c \ 55 | "select '\"$HOST_NAME\"', 'psql.block_query', $TIMESTAMP_QUERY, (select CASE count(setting) when 0 then 1 ELSE (select CASE (select pg_is_in_recovery()::int) when 1 then 1 ELSE (select CASE (select count(*) from pg_stat_replication where sync_priority > 0) when 0 then 0 else 1 END) END) END from pg_settings where name ='synchronous_standby_names' and setting !='') \ 56 | union all \ 57 | SELECT '\"$HOST_NAME\"','psql.confl_tablespace[' || datname || ']',$TIMESTAMP_QUERY,confl_tablespace from pg_stat_database_conflicts where datname not in ('template1','template0') \ 58 | union all \ 59 | SELECT '\"$HOST_NAME\"','psql.confl_lock[' || datname || ']',$TIMESTAMP_QUERY,confl_lock from pg_stat_database_conflicts where datname not in ('template1','template0') \ 60 | union all \ 61 | SELECT '\"$HOST_NAME\"','psql.confl_snapshot[' || datname || ']',$TIMESTAMP_QUERY,confl_snapshot from pg_stat_database_conflicts where datname not in ('template1','template0') \ 62 | union all \ 63 | SELECT '\"$HOST_NAME\"','psql.confl_bufferpin[' || datname || ']',$TIMESTAMP_QUERY,confl_bufferpin from pg_stat_database_conflicts where datname not in ('template1','template0') \ 64 | union all \ 65 | SELECT '\"$HOST_NAME\"','psql.confl_deadlock[' || datname || ']',$TIMESTAMP_QUERY,confl_deadlock from pg_stat_database_conflicts where datname not in ('template1','template0')" 2>&1 66 | ) 67 | ;; 68 | *) 69 | echo "'$APP_NAME' did not match anything." 70 | exit 71 | ;; 72 | esac 73 | 74 | if [ $? -ne 0 ]; then 75 | echo "$sending_data" 76 | exit 77 | fi 78 | 79 | if [ -z "$sending_data" ]; then 80 | echo 0 81 | exit 82 | fi 83 | 84 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 85 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 86 | if [ -n "$response" ]; then 87 | echo "$response" 88 | else 89 | echo "$result" 90 | fi 91 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_standby.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PGSHELL_CONFDIR="$1" 4 | 5 | # Load the psql connection option parameters. 6 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 7 | 8 | result=$(psql -A -t -X -h $PGHOST -p $PGPORT -U $PGROLE -d $PGDATABASE -c "select pg_is_in_recovery()::int" 2>&1) 9 | echo "$result" 10 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_tbl_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_NAME="$1" 4 | PGSHELL_CONFDIR="$2" 5 | HOST_NAME="$3" 6 | ZABBIX_AGENTD_CONF="$4" 7 | DBNAME="$5" 8 | SCHEMANAME="$6" 9 | TABLENAME="$7" 10 | 11 | TIMESTAMP_QUERY='extract(epoch from now())::int' 12 | 13 | # Load the psql connection option parameters. 14 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 15 | 16 | case "$APP_NAME" in 17 | pg.stat_table) 18 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $DBNAME -c \ 19 | "select '\"$HOST_NAME\"', 'psql.table_analyze_count[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select analyze_count from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 20 | union all \ 21 | select '\"$HOST_NAME\"', 'psql.table_autoanalyze_count[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select autoanalyze_count from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 22 | union all \ 23 | select '\"$HOST_NAME\"', 'psql.table_autovacuum_count[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select autovacuum_count from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 24 | union all \ 25 | select '\"$HOST_NAME\"', 'psql.table_heap_cachehit_ratio[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select CASE heap_blks_hit+heap_blks_read WHEN 0 then 100 else round(heap_blks_hit*100/(heap_blks_hit+heap_blks_read), 2) end from pg_statio_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 26 | union all \ 27 | select '\"$HOST_NAME\"', 'psql.table_idx_cachehit_ratio[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select CASE WHEN idx_blks_read is NULL then 0 when idx_blks_hit+idx_blks_read=0 then 100 else round(idx_blks_hit*100/(idx_blks_hit+idx_blks_read + 0.0001), 2) end from pg_statio_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 28 | union all \ 29 | select '\"$HOST_NAME\"', 'psql.table_n_dead_tup[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_dead_tup from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 30 | union all \ 31 | select '\"$HOST_NAME\"', 'psql.table_n_tup_del[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_tup_del from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 32 | union all \ 33 | select '\"$HOST_NAME\"', 'psql.table_n_tup_hot_upd[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_tup_hot_upd from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 34 | union all \ 35 | select '\"$HOST_NAME\"', 'psql.table_idx_scan[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select coalesce(idx_scan,0) from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 36 | union all \ 37 | select '\"$HOST_NAME\"', 'psql.table_seq_tup_read[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select coalesce(seq_tup_read,0) from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 38 | union all \ 39 | select '\"$HOST_NAME\"', 'psql.table_idx_tup_fetch[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select coalesce(idx_tup_fetch,0) from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 40 | union all \ 41 | select '\"$HOST_NAME\"', 'psql.table_n_tup_ins[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_tup_ins from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 42 | union all \ 43 | select '\"$HOST_NAME\"', 'psql.table_n_live_tup[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_live_tup from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 44 | union all \ 45 | select '\"$HOST_NAME\"', 'psql.table_seq_scan[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select seq_scan from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 46 | union all \ 47 | select '\"$HOST_NAME\"', 'psql.table_n_tup_upd[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select n_tup_upd from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') \ 48 | union all \ 49 | select '\"$HOST_NAME\"', 'psql.table_vacuum_count[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select vacuum_count from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') 50 | union all \ 51 | select '\"$HOST_NAME\"', 'psql.table_garbage_ratio[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select round(100*(CASE (n_live_tup+n_dead_tup) WHEN 0 THEN 0 ELSE (n_dead_tup/(n_live_tup+n_dead_tup)::numeric) END),2) from pg_stat_user_tables where schemaname = '$SCHEMANAME' and relname = '$TABLENAME') 52 | union all \ 53 | select '\"$HOST_NAME\"', 'psql.table_total_size[$DBNAME,$SCHEMANAME,$TABLENAME]', $TIMESTAMP_QUERY, (select pg_total_relation_size('${SCHEMANAME}.\"${TABLENAME}\"'))" 2>&1 54 | ) 55 | ;; 56 | *) 57 | echo "'$APP_NAME' did not match anything." 58 | exit 59 | ;; 60 | esac 61 | 62 | if [ $? -ne 0 ]; then 63 | echo "$sending_data" 64 | exit 65 | fi 66 | 67 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 68 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 69 | if [ -n "$response" ]; then 70 | echo "$response" 71 | else 72 | echo "$result" 73 | fi 74 | -------------------------------------------------------------------------------- /pg_monz/usr-local-bin/pgsql_userdb_funcs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_NAME="$1" 4 | PGSHELL_CONFDIR="$2" 5 | HOST_NAME="$3" 6 | ZABBIX_AGENTD_CONF="$4" 7 | DBNAME="$5" 8 | 9 | TIMESTAMP_QUERY='extract(epoch from now())::int' 10 | 11 | # Load the psql connection option parameters. 12 | source $PGSHELL_CONFDIR/pgsql_funcs.conf 13 | 14 | case "$APP_NAME" in 15 | pg.size) 16 | sending_data=$(psql -A --field-separator=' ' -t -X -h $PGHOST -p $PGPORT -U $PGROLE $DBNAME -c \ 17 | "select '\"$HOST_NAME\"', 'psql.db_size[$DBNAME]', $TIMESTAMP_QUERY, (select pg_database_size('$DBNAME')) \ 18 | union all \ 19 | select '\"$HOST_NAME\"', 'psql.db_garbage_ratio[$DBNAME]', $TIMESTAMP_QUERY, ( \ 20 | SELECT round(100*sum( \ 21 | CASE (a.n_live_tup+a.n_dead_tup) WHEN 0 THEN 0 \ 22 | ELSE c.relpages*(a.n_dead_tup/(a.n_live_tup+a.n_dead_tup)::numeric) \ 23 | END \ 24 | )/ sum(c.relpages),2) \ 25 | FROM \ 26 | pg_class as c join pg_stat_all_tables as a on(c.oid = a.relid) where relpages > 0)" 2>&1 27 | ) 28 | ;; 29 | *) 30 | echo "'$APP_NAME' did not match anything." 31 | exit 32 | ;; 33 | esac 34 | 35 | if [ $? -ne 0 ]; then 36 | echo "$sending_data" 37 | exit 38 | fi 39 | 40 | result=$(echo "$sending_data" | zabbix_sender -c $ZABBIX_AGENTD_CONF -v -T -i - 2>&1) 41 | response=$(echo "$result" | awk -F ';' '$1 ~ /^info/ && match($1,/[0-9].*$/) {sum+=substr($1,RSTART,RLENGTH)} END {print sum}') 42 | if [ -n "$response" ]; then 43 | echo "$response" 44 | else 45 | echo "$result" 46 | fi 47 | -------------------------------------------------------------------------------- /pg_monz/usr-local-etc/pgpool_funcs.conf: -------------------------------------------------------------------------------- 1 | PGPOOLHOST=127.0.0.1 2 | PGPOOLPORT=9999 3 | PGPOOLROLE=postgres 4 | PGPOOLDATABASE=postgres 5 | PGPOOLCONF=/usr/local/etc/pgpool.conf 6 | -------------------------------------------------------------------------------- /pg_monz/usr-local-etc/pgsql_funcs.conf: -------------------------------------------------------------------------------- 1 | PGHOST=127.0.0.1 2 | PGPORT=5432 3 | PGROLE=postgres 4 | PGDATABASE=postgres 5 | -------------------------------------------------------------------------------- /pg_monz/zabbix_agentd.d/userparameter_pgsql.conf: -------------------------------------------------------------------------------- 1 | # PostgreSQL user parameter 2 | 3 | # Discovery Rule 4 | # 5 | # Database Discovery 6 | UserParameter=db.list.discovery[*],"$1"/find_dbname.sh "$2" 7 | UserParameter=db_table.list.discovery[*],"$1"/find_dbname_table.sh "$2" 8 | UserParameter=sr.discovery[*],"$1"/find_sr.sh "$2" 9 | UserParameter=sr.status.discovery[*],"$1"/find_sr_client_ip.sh "$2" 10 | UserParameter=sr.db.list.discovery[*],"$1"/find_dbname.sh "$2" 11 | 12 | # For pg_monz 2.0 psql monitoring 13 | # $1: pgsql_*_funcs.sh directory path 14 | # $2: pgsql_funcs.conf directory path 15 | UserParameter=psql.running[*],"$1"/pgsql_simple.sh "$2" 16 | UserParameter=psql.primary_server[*],"$1"/pgsql_primary.sh "$2" 17 | UserParameter=psql.standby_server[*],"$1"/pgsql_standby.sh "$2" 18 | 19 | # For pg_monz 2.0 20 | #--- PostgreSQL user parameter ----------------------------------------------- 21 | # $1: pgsql_*_funcs.sh directory path 22 | # $2: pgsql_funcs.conf directory path 23 | # $3: hostname (which means the designated name specified on Zabbix Web UI) 24 | # $4: zabbix_agentd.conf file path 25 | # $5: DB name (only for LLD) or {$PGSLOWQUERY_TIME_THRESHOLD} ( only for pgsql.get.pg.slow_query ) 26 | # $6: DB schema name (only for LLD) 27 | # $7: DB table name (only for LLD) 28 | #------------------------------------------------------------------------------- 29 | UserParameter=pgsql.get.pg.transactions[*],"$1"/pgsql_server_funcs.sh pg.transactions "$2" "$3" "$4" 30 | UserParameter=pgsql.get.pg.bgwriter[*],"$1"/pgsql_server_funcs.sh pg.bgwriter $2 "$3" "$4" 31 | UserParameter=pgsql.get.pg.slow_query[*],"$1"/pgsql_server_funcs.sh pg.slow_query "$2" "$3" "$4" "$5" 32 | UserParameter=pgsql.get.pg.stat_database[*],"$1"/pgsql_db_funcs.sh pg.stat_database "$2" "$3" "$4" "$5" 33 | UserParameter=pgsql.get.pg.size[*],"$1"/pgsql_userdb_funcs.sh pg.size "$2" "$3" "$4" "$5" 34 | 35 | UserParameter=pgsql.get.pg.stat_table[*],"$1"/pgsql_tbl_funcs.sh pg.stat_table "$2" "$3" "$4" "$5" "$6" "$7" 36 | 37 | #--- PostgreSQL SR user parameter -------------------------------------------- 38 | # $1: pgsql_*_funcs.sh directory path 39 | # $2: pgsql_funcs.conf directory path 40 | # $3: hostname (which means the designated name specified on Zabbix Web UI) 41 | # $4: zabbix_agentd.conf file path 42 | #------------------------------------------------------------------------------- 43 | UserParameter=pgsql.get.pg.stat_replication[*],"$1"/pgsql_sr_server_funcs.sh pg.stat_replication "$2" "$3" "$4" 44 | UserParameter=pgsql.get.pg.sr.status[*],"$1"/pgsql_sr_server_funcs.sh pg.sr.status "$2" "$3" "$4" 45 | 46 | #--- pgpool-II user parameter -------------------------------------------- 47 | # Discovery Rule 48 | UserParameter=backend.discovery[*],"$1"/find_pgpool_backend.sh "$2" 49 | UserParameter=backend.status.discovery[*],"$1"/find_pgpool_backend_ip.sh "$2" 50 | 51 | #--- pgpool-II user parameter -------------------------------------------- 52 | UserParameter=pgpool.running[*],"$1"/pgpool_simple.sh "$2" 53 | UserParameter=pgpool.have_delegate_ip[*],"$1"/pgpool_delegate_ip.sh "$2" 54 | UserParameter=pgpool.get.nodes[*],"$1"/pgpool_backend_status.sh pgpool.nodes "$2" "$3" "$4" 55 | UserParameter=pgpool.get.connections[*],"$1"/pgpool_connections.sh pgpool.connections "$2" "$3" "$4" 56 | UserParameter=pgpool.get.cache[*],"$1"/pgpool_cache.sh pgpool.cache $2 "$3" "$4" 57 | -------------------------------------------------------------------------------- /quick-install.txt: -------------------------------------------------------------------------------- 1 | * How to install pg_monz v2 2 | 3 | 1. requirements 4 | 5 | - Zabbix server version 2.0+ 6 | - monitored PostgreSQL 9.2+ 7 | - monitored pgpool-II 3.4.0 8 | - installing zabbix_agentd to PostgreSQL and pgpool-II host. 9 | - installing zabbix_sender to PostgreSQL and pgpool-II host. 10 | - ServerActive setting in zabbix_agentd.conf (zabbix_sender read this file) 11 | - psql command(and serch path setting) on each PostgreSQL/pgpool server 12 | 13 | 1. Uploading Zabbix template using Zabbix frontend. 14 | 15 | Template_App_PostgreSQL.xml 16 | Template_App_PostgreSQL_SR.xml 17 | Template_App_PostgreSQL_SR_Cluster.xml 18 | Template_App_pgpool-II.xml 19 | Template_App_pgpool-II-36.xml 20 | Template_App_pgpool-II_watchdog.xml 21 | 22 | 2. Copy usr-local-etc files (pgsql_funcs.conf and pgpool_funcs.conf) to "/usr/local/etc" 23 | 24 | #cp usr-local-etc/* /usr/local/etc 25 | 26 | default variables for pgsql_funcs.conf 27 | ---- 28 | PGHOST=127.0.0.1 29 | PGPORT=5432 30 | PGROLE=postgres 31 | PGDATABASE=postgres 32 | ---- 33 | 34 | default variables for pgpool_funcs.conf 35 | ---- 36 | PGPOOLHOST=127.0.0.1 37 | PGPOOLPORT=9999 38 | PGPOOLROLE=postgres 39 | PGPOOLDATABASE=postgres 40 | PGPOOLCONF=/usr/local/etc/pgpool.conf 41 | ---- 42 | 43 | (*) the definition of configuration directory is in the tempalte macro. 44 | {$PGSCRIPT_CONFDIR} 45 | {$PGPOOLSCRIPTS_CONFDIR} 46 | 47 | 3. Copy usr-local-bin files (*.sh) to "/usr/local/bin" 48 | 49 | #cp usr-local-bin/* /usr/local/bin 50 | 51 | (*) the definition of scripts directory is in the template macro. 52 | {$PGSCRIPTDIR} 53 | {$PGPOOLSCRIPTDIR} 54 | 55 | 4. Define groups using Zabbix frontend. 56 | 57 | Create "PostgreSQL" group and add PostgreSQL host to "PostgreSQL" group. 58 | Create "pgpool" group and add pgpool-II host to "pgpool" group. 59 | 60 | Each groups are referenced by Template_App_PostgreSQL_SR_Cluster.xml 61 | and Template_App_pgpool-II_watchdog.xml using {$HOST_GROUP} template macro. 62 | 63 | 5. Check the filepath of zabbix_agentd.conf. 64 | 65 | if your installation of zabbix_agentd.conf is not /etc/zabbix/zabbix_agentd.conf, 66 | add {$ZABBIX_AGENTD_CONF} macro to HOST'S MACRO. 67 | 68 | # the definition of zabbix_agentd.conf path is in the template macro. 69 | {$ZABBIX_AGENTD_CONF} => /etc/zabbix/zabbix_agentd.conf 70 | 71 | 6. Link template to host. 72 | 73 | Link "Template App PostgreSQL SR" to PostgreSQL host. 74 | Link "Template App pgpool-II" to pgpool-II host. 75 | 76 | "Template App PostgreSQL SR Cluster"/ "Template App pgpool-II-watchdog" 77 | are simply counting 78 | -the number of running service (sr/pgpool-II), 79 | -the number of primary server (sr), 80 | -the number of standby server (sr), 81 | -the number of delegate_ip (pgpool-II), 82 | in same {$HOST_GROUP} using zabbix aggregate key. 83 | you want to monitor the split-brain or the number of primary server, 84 | Link the above templates to arbitrary host. 85 | ex) "PostgreSQL Cluster" as a virtual host 86 | --------------------------------------------------------------------------------