11# -*- coding: utf-8 -*-
22
3+ from distutils .version import LooseVersion
34from mamonsu .plugins .pgsql .plugin import PgsqlPlugin as Plugin
45from .pool import Pooler
56from mamonsu .lib .zbx_template import ZbxTemplate
@@ -16,6 +17,11 @@ class Databases(Plugin):
1617 " datistemplate = false and datname = :'p1';"
1718 query_age = "select age(datfrozenxid) from pg_catalog.pg_database where datistemplate = false " \
1819 "and datname = :'p1';"
20+ query_invalid_indexes = "SELECT count(*) " \
21+ "FROM pg_catalog.pg_class, pg_catalog.pg_index " \
22+ "WHERE pg_catalog.pg_index.indisvalid = false " \
23+ "AND pg_catalog.pg_index.indexrelid = pg_catalog.pg_class.oid " \
24+ "AND substring(pg_catalog.pg_class.relname, '([^_]+$)') ~ '^cc{0}';"
1925
2026 # queries for zabbix agent
2127 query_agent_discovery = "SELECT json_build_object ('data',json_agg(json_build_object('{#DATABASE}',d.datname)))" \
@@ -26,10 +32,14 @@ class Databases(Plugin):
2632 key_db_age = "pgsql.database.max_age{0}"
2733 key_db_bloating_tables = "pgsql.database.bloating_tables{0}"
2834 key_autovacumm = "pgsql.autovacumm.count{0}"
35+ key_invalid_rebuilt_indexes = "pgsql.database.invalid_rebuilt_indexes{0}"
36+ key_invalid_old_indexes = "pgsql.database.invalid_old_indexes{0}"
2937
3038 DEFAULT_CONFIG = {'min_rows' : str (50 ), 'bloat_scale' : str (0.2 )}
3139
3240 def run (self , zbx ):
41+ if Pooler .server_version_greater ('12' ):
42+ self .query_invalid_indexes = self .query_invalid_indexes [:- 1 ] + " AND pg_catalog.pg_class.oid NOT IN (SELECT index_relid FROM pg_catalog.pg_stat_progress_create_index);"
3343 result = Pooler .query ('select \
3444 datname, pg_database_size(datname::text), age(datfrozenxid) \
3545 from pg_catalog.pg_database where datistemplate = false' )
@@ -49,6 +59,18 @@ def run(self, zbx):
4959 zbx .send (
5060 'pgsql.database.bloating_tables[{0}]' .format (info [0 ]),
5161 int (bloat_count ))
62+ invalid_rebuilt_indexes_count = Pooler .query (
63+ self .query_invalid_indexes .format ('new' ),
64+ info [0 ])[0 ][0 ]
65+ invalid_old_indexes_count = Pooler .query (
66+ self .query_invalid_indexes .format ('old' ),
67+ info [0 ])[0 ][0 ]
68+ zbx .send (
69+ 'pgsql.database.invalid_rebuilt_indexes[{0}]' .format (info [0 ]),
70+ int (invalid_rebuilt_indexes_count ))
71+ zbx .send (
72+ 'pgsql.database.invalid_old_indexes[{0}]' .format (info [0 ]),
73+ int (invalid_old_indexes_count ))
5274 zbx .send ('pgsql.database.discovery[]' , zbx .json ({'data' : dbs }))
5375 del dbs , bloat_count
5476
@@ -100,6 +122,12 @@ def discovery_rules(self, template, dashboard=False):
100122 'delay' : self .plugin_config ('interval' )},
101123 {'key' : self .right_type (self .key_db_bloating_tables , var_discovery = "{#DATABASE}," ),
102124 'name' : 'Count of bloating tables in database: {#DATABASE}' ,
125+ 'delay' : self .plugin_config ('interval' )},
126+ {'key' : self .right_type (self .key_invalid_rebuilt_indexes , var_discovery = "{#DATABASE}," ),
127+ 'name' : 'Count of indexes corrupted during REINDEX in database: {#DATABASE}' ,
128+ 'delay' : self .plugin_config ('interval' )},
129+ {'key' : self .right_type (self .key_invalid_old_indexes , var_discovery = "{#DATABASE}," ),
130+ 'name' : 'Count of old invalid indexes in database: {#DATABASE}' ,
103131 'delay' : self .plugin_config ('interval' )}
104132 ]
105133 graphs = [
@@ -129,15 +157,30 @@ def discovery_rules(self, template, dashboard=False):
129157 'yaxisside' : 1 }]
130158 }
131159 ]
132- return template .discovery_rule (rule = rule , conditions = conditions , items = items , graphs = graphs )
160+ triggers = [{
161+ 'name' : 'PostgreSQL corrupted indexes during REINDEX in database '
162+ '{#DATABASE} (hostname={HOSTNAME} value={ITEM.LASTVALUE})' ,
163+ 'expression' : '{#TEMPLATE:pgsql.database.invalid_rebuilt_indexes[{#DATABASE}].last()}>0' },
164+ {
165+ 'name' : 'PostgreSQL old invalid indexes in database '
166+ '{#DATABASE} (hostname={HOSTNAME} value={ITEM.LASTVALUE})' ,
167+ 'expression' : '{#TEMPLATE:pgsql.database.invalid_old_indexes[{#DATABASE}].last()}>0' }
168+ ]
169+ return template .discovery_rule (rule = rule , conditions = conditions , items = items , graphs = graphs , triggers = triggers )
133170
134171 def keys_and_queries (self , template_zabbix ):
172+ if LooseVersion (self .VersionPG ) >= LooseVersion ('12' ):
173+ self .query_invalid_indexes = self .query_invalid_indexes [:- 1 ] + " AND pg_catalog.pg_class.oid NOT IN (SELECT index_relid FROM pg_catalog.pg_stat_progress_create_index);"
135174 result = ['{0},$2 $1 -c "{1}"' .format (self .key_autovacumm .format ("[*]" ), Pooler .SQL ['count_autovacuum' ][0 ]),
136175 '{0},$2 $1 -c "{1}"' .format (self .key_db_discovery .format ("[*]" ), self .query_agent_discovery ),
137176 '{0},echo "{1}" | $3 $2 -v p1="$1"' .format (self .key_db_size .format ("[*]" ), self .query_size ),
138177 '{0},echo "{1}" | $3 $2 -v p1="$1"' .format (self .key_db_age .format ("[*]" ), self .query_age ),
139178 '{0},$3 $2 -d "$1" -c "{1}"' .format (self .key_db_bloating_tables .format ("[*]" ),
140179 self .query_bloating_tables .format (
141180 self .plugin_config ('bloat_scale' ),
142- self .plugin_config ('min_rows' )))]
181+ self .plugin_config ('min_rows' ))),
182+ '{0},$3 $2 -d "$1" -c "{1}"' .format (self .key_invalid_rebuilt_indexes .format ("[*]" ),
183+ self .query_invalid_indexes .format ('new' )),
184+ '{0},$3 $2 -d "$1" -c "{1}"' .format (self .key_invalid_old_indexes .format ("[*]" ),
185+ self .query_invalid_indexes .format ('old' ))]
143186 return template_zabbix .key_and_query (result )
0 commit comments