1
1
# -*- coding: utf-8 -*-
2
2
3
+ from distutils .version import LooseVersion
3
4
from mamonsu .plugins .pgsql .plugin import PgsqlPlugin as Plugin
4
5
from .pool import Pooler
5
6
from mamonsu .lib .zbx_template import ZbxTemplate
@@ -16,6 +17,11 @@ class Databases(Plugin):
16
17
" datistemplate = false and datname = :'p1';"
17
18
query_age = "select age(datfrozenxid) from pg_catalog.pg_database where datistemplate = false " \
18
19
"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}';"
19
25
20
26
# queries for zabbix agent
21
27
query_agent_discovery = "SELECT json_build_object ('data',json_agg(json_build_object('{#DATABASE}',d.datname)))" \
@@ -26,10 +32,14 @@ class Databases(Plugin):
26
32
key_db_age = "pgsql.database.max_age{0}"
27
33
key_db_bloating_tables = "pgsql.database.bloating_tables{0}"
28
34
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}"
29
37
30
38
DEFAULT_CONFIG = {'min_rows' : str (50 ), 'bloat_scale' : str (0.2 )}
31
39
32
40
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);"
33
43
result = Pooler .query ('select \
34
44
datname, pg_database_size(datname::text), age(datfrozenxid) \
35
45
from pg_catalog.pg_database where datistemplate = false' )
@@ -49,6 +59,18 @@ def run(self, zbx):
49
59
zbx .send (
50
60
'pgsql.database.bloating_tables[{0}]' .format (info [0 ]),
51
61
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 ))
52
74
zbx .send ('pgsql.database.discovery[]' , zbx .json ({'data' : dbs }))
53
75
del dbs , bloat_count
54
76
@@ -100,6 +122,12 @@ def discovery_rules(self, template, dashboard=False):
100
122
'delay' : self .plugin_config ('interval' )},
101
123
{'key' : self .right_type (self .key_db_bloating_tables , var_discovery = "{#DATABASE}," ),
102
124
'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}' ,
103
131
'delay' : self .plugin_config ('interval' )}
104
132
]
105
133
graphs = [
@@ -129,15 +157,30 @@ def discovery_rules(self, template, dashboard=False):
129
157
'yaxisside' : 1 }]
130
158
}
131
159
]
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 )
133
170
134
171
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);"
135
174
result = ['{0},$2 $1 -c "{1}"' .format (self .key_autovacumm .format ("[*]" ), Pooler .SQL ['count_autovacuum' ][0 ]),
136
175
'{0},$2 $1 -c "{1}"' .format (self .key_db_discovery .format ("[*]" ), self .query_agent_discovery ),
137
176
'{0},echo "{1}" | $3 $2 -v p1="$1"' .format (self .key_db_size .format ("[*]" ), self .query_size ),
138
177
'{0},echo "{1}" | $3 $2 -v p1="$1"' .format (self .key_db_age .format ("[*]" ), self .query_age ),
139
178
'{0},$3 $2 -d "$1" -c "{1}"' .format (self .key_db_bloating_tables .format ("[*]" ),
140
179
self .query_bloating_tables .format (
141
180
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' ))]
143
186
return template_zabbix .key_and_query (result )
0 commit comments