Skip to content

Commit 3516a88

Browse files
author
Alexander Popov
committed
feat: PGPRO-3923, add new plugin relationssize
1 parent 722d456 commit 3516a88

File tree

5 files changed

+154
-8
lines changed

5 files changed

+154
-8
lines changed

mamonsu/plugins/pgsql/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
__all__ += ['cfs']
66
__all__ += ['archive_command']
77
__all__ += ['prepared_transaction']
8+
__all__ += ['relations_size']
89

910
from . import *
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from mamonsu.plugins.pgsql.plugin import PgsqlPlugin as Plugin
4+
from .pool import Pooler
5+
from mamonsu.lib.plugin import PluginDisableException
6+
7+
8+
class RelationsSize(Plugin):
9+
DEFAULT_CONFIG = {'enabled': 'False'}
10+
11+
def __init__(self, config):
12+
super(Plugin, self).__init__(config)
13+
if self.is_enabled():
14+
self.relations = None
15+
self.key_rel_size_discovery = "pgsql.relation.size{0}"
16+
self.query_template = """SELECT relation.schema
17+
, relation.name
18+
, CASE WHEN l.mode = 'AccessExclusiveLock' THEN '-1'
19+
ELSE (pg_total_relation_size(cl.oid))
20+
END AS pg_total_relation_size
21+
, CASE WHEN l.mode = 'AccessExclusiveLock' THEN '-1'
22+
ELSE (sum(pg_total_relation_size(inh.inhrelid)))
23+
END AS pg_total_relation_size_part
24+
FROM (VALUES {values}) as relation (schema,name)
25+
LEFT JOIN pg_catalog.pg_class cl ON cl.relname = relation.name
26+
LEFT JOIN pg_catalog.pg_namespace ns ON ns.oid = cl.relnamespace AND ns.nspname=relation.schema
27+
LEFT JOIN pg_catalog.pg_inherits inh ON inh.inhparent = cl.oid
28+
LEFT JOIN pg_catalog.pg_locks l ON l.relation = cl.oid AND l.mode= 'AccessExclusiveLock' AND l.locktype = 'relation'
29+
LEFT JOIN pg_catalog.pg_locks l_part ON l_part.relation = inh.inhrelid AND l.mode= 'AccessExclusiveLock' AND l.locktype = 'relation'
30+
GROUP BY relation.schema
31+
, relation.name
32+
, l.mode
33+
, cl.oid"""
34+
35+
def create_relations(self):
36+
config_relations = self._plugin_config.get('relations', None)
37+
if config_relations is None or config_relations == '':
38+
self.disable()
39+
raise PluginDisableException(
40+
"""Disable plugin and exit, because the parameter 'relations' in section [relationssize] is not set. Set this parameter like relations=pg_catalog.pg_class,pg_catalog.pg_user to count size if needed and restart.""")
41+
42+
self.relations = []
43+
for relation in config_relations.split(','):
44+
tmp_rel = relation.split('.')
45+
if len(tmp_rel) == 3:
46+
self.relations.append([tmp_rel[0].strip(), tmp_rel[1].strip(), tmp_rel[2].strip()])
47+
else:
48+
self.log.error(
49+
'The relation "{relation}" is not correct. You need to specify "database_name.schema.table" in the configuration file for mamonsu. Section: [relationssize], parameter: relations '.format(
50+
relation=relation))
51+
52+
def run(self, zbx):
53+
if not self.relations:
54+
self.create_relations()
55+
rels = []
56+
all_databases = Pooler.databases()
57+
for database_name, schema, relation in self.relations:
58+
rels.append({'{#RELATIONNAME}': database_name + '.' + schema + '.' + relation})
59+
if not (database_name in all_databases):
60+
self.log.error(
61+
'''The database: "{database_name}" do not exists. '''
62+
'''Check the the parameter "relations" in section [relatonssize].'''.format(
63+
database_name=database_name))
64+
else:
65+
result = Pooler.query(query=self.query_template.format(
66+
values="('{schema}','{relation}')".format(schema=schema, relation=relation)), db=database_name)
67+
for schema, name, pg_total_relation_size, pg_total_relation_size_part in result:
68+
full_name_relation = database_name + '.' + schema + '.' + relation
69+
70+
if pg_total_relation_size is None and pg_total_relation_size_part is None:
71+
self.log.error('The relation: "{full_name_relation}" in not correct'.format(
72+
full_name_relation=full_name_relation))
73+
size = -1
74+
elif pg_total_relation_size == -1 or pg_total_relation_size_part == -1:
75+
self.log.error(
76+
"The relation: {full_name_relation} is locked. "
77+
"You can find this lock in query: "
78+
"SELECT relation::regclass AS lock_relation, mode FROM pg_locks "
79+
"WHERE relation::regclass = 'pg_locks'::regclass;".format(
80+
full_name_relation=full_name_relation))
81+
size = -1
82+
else:
83+
size = (pg_total_relation_size or 0) + (pg_total_relation_size_part or 0)
84+
85+
zbx.send('pgsql.relation.size[{0}]'.format(full_name_relation), int(size))
86+
87+
zbx.send('pgsql.relation.size[]', zbx.json({'data': rels}))
88+
89+
def discovery_rules(self, template):
90+
rule = {
91+
'name': 'Relation size discovery',
92+
'key': self.key_rel_size_discovery.format('[{0}]'.format(self.Macros[self.Type])),
93+
}
94+
if Plugin.old_zabbix:
95+
conditions = []
96+
rule['filter'] = '{#RELATIONNAME}:.*'
97+
else:
98+
conditions = [
99+
{
100+
'condition': [
101+
{'macro': '{#RELATIONNAME}',
102+
'value': '.*',
103+
'operator': None,
104+
'formulaid': 'A'}
105+
]
106+
}
107+
]
108+
items = [
109+
{'key': self.right_type(self.key_rel_size_discovery, var_discovery="{#RELATIONNAME},"),
110+
'name': 'Relation size: {#RELATIONNAME}',
111+
'units': Plugin.UNITS.bytes,
112+
'value_type': Plugin.VALUE_TYPE.numeric_unsigned,
113+
'delay': self.plugin_config('interval')},
114+
]
115+
graphs = [
116+
{
117+
'name': 'PostgreSQL relation size: {#RELATIONNAME}',
118+
'type': 1,
119+
'items': [
120+
{'color': '00CC00',
121+
'key': self.right_type(self.key_rel_size_discovery, var_discovery="{#RELATIONNAME},")}]
122+
},
123+
]
124+
return template.discovery_rule(rule=rule, conditions=conditions, items=items, graphs=graphs)

packaging/conf/example.conf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,15 @@ enabled = False
184184
interval = 300
185185
backup_dirs = /backup_dir1,/backup_dir2
186186
pg_probackup_path = /usr/bin/pg_probackup-11
187+
188+
# Get size of relations defined in this section
189+
# Relations - comma separated list of objects - tables and endexes (database_name.schema.relation) used to calculate relations size.
190+
# Example:
191+
# relations=postgres.pg_catalog.pg_class,postgres.pg_catalog.pg_user
192+
# If the relation is blocked by some process such as vacuum full or create index, the result will be -1
193+
# by default this plugin disabled. To enable this plugin - set bellow "enabled = False" and define a list of relations.
194+
[relationssize]
195+
enabled = False
196+
relations=postgres.pg_catalog.pg_class,postgres.pg_catalog.pg_user
197+
interval = 300
198+

packaging/conf/example_win32.conf

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,13 @@ interval = 60
177177
max_prepared_transaction_time = 60
178178
interval = 60
179179

180-
# Get size of backup catalogs stroring all WAL and backup files using pg_probackup
181-
# (https://github.com/postgrespro/pg_probackup)
182-
# Trigger fires if some backup has bad status e.g. (ERROR,CORRUPT,ORPHAN).
183-
#[pgprobackup]
184-
#enabled = False
185-
#interval = 300
186-
#backup_dirs = /backup_dir1,/backup_dir2
187-
#pg_probackup_path = /usr/bin/pg_probackup-11
180+
# Get size of relations defined in this section
181+
# Relations - comma separated list of objects - tables and endexes (database_name.schema.relation) used to calculate relations size.
182+
# Example:
183+
# relations=postgres.pg_catalog.pg_class,postgres.pg_catalog.pg_user
184+
# If the relation is blocked by some process such as vacuum full or create index, the result will be -1
185+
# by default this plugin disabled. To enable this plugin - set bellow "enabled = False" and define a list of relations.
186+
[relationssize]
187+
enabled = False
188+
relations=postgres.pg_catalog.pg_class,postgres.pg_catalog.pg_user
189+
interval = 300

tests/check.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,12 @@ level = DEBUG
172172
[preparedtransaction]
173173
max_prepared_transaction_time = 60
174174
interval = 60
175+
176+
[relationssize]
177+
enabled = True
178+
relations=postgres.pg_catalog.pg_class,postgres.pg_catalog.pg_user
179+
interval = 60
180+
175181
EOF
176182
mamonsu bootstrap -U postgres mamonsu -M mamonsu
177183
##/etc/init.d/mamonsu start
@@ -191,6 +197,7 @@ grep utilization /tmp/localhost.log || exit 7
191197
grep 'pgsql\.uptime' /tmp/localhost.log || exit 7
192198
grep 'pgsql\.prepared\.count' /tmp/localhost.log || exit 7
193199
grep 'pgsql\.prepared\.oldest' /tmp/localhost.log || exit 7
200+
grep 'pgsql\.relation\.size' /tmp/localhost.log || exit 7
194201

195202
## error in zabbix server
196203
(mamonsu zabbix item error $ZABBIX_CLIENT_HOST | grep ZBX_NOTSUPPORTED) && exit 8

0 commit comments

Comments
 (0)