Skip to content

Commit 8a43528

Browse files
author
alexander popov
committed
feat: add new plugin to calculate relations sizes
1 parent 60dd239 commit 8a43528

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

mamonsu/plugins/pgsql/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
__all__ += ['checkpoint', 'oldest', 'pg_locks']
55
__all__ += ['cfs']
66
__all__ += ['archive_command']
7+
__all__ += ['relations_size']
78

89
from . import *
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
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+
def __init__(self, config):
10+
super(Plugin, self).__init__(config)
11+
self.query = None
12+
self.key_rel_size_discovery = "pgsql.relation.size{0}"
13+
14+
15+
def create_query(self):
16+
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+
config_relations = self._plugin_config.get('relations', None)
36+
if config_relations is None or config_relations == '':
37+
self.disable()
38+
raise PluginDisableException ("""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.""")
39+
40+
values = []
41+
for relation in config_relations.split(','):
42+
tmp_rel = relation.split('.')
43+
if len(tmp_rel) == 0:
44+
pass
45+
elif len(tmp_rel) == 1:
46+
values.append("(NULL, '{relation}')".format(relation=tmp_rel[0].strip()))
47+
elif len(tmp_rel) == 2:
48+
values.append(
49+
"('{schema}', '{relation}')".format(schema=tmp_rel[0].strip(), relation=tmp_rel[1].strip()))
50+
else:
51+
self.log.error(
52+
'The relation "{relation}" is not correct. You need to specify "schema.table" in the configuration file for mamonsu. Section: [relationssize], parameter: relations '.format(
53+
relation=relation))
54+
55+
self.query = query_template.format(values=',\n '.join(values))
56+
57+
def run(self, zbx):
58+
if not self.query:
59+
self.create_query()
60+
result = Pooler.query(self.query)
61+
rels = []
62+
for schema, name, pg_total_relation_size, pg_total_relation_size_part in result:
63+
if not schema:
64+
full_name_relation = name
65+
else:
66+
full_name_relation = schema + '.' + name
67+
rels.append({'{#RELATIONNAME}': full_name_relation })
68+
69+
if pg_total_relation_size is None and pg_total_relation_size_part is None:
70+
self.log.error('The relation: "{full_name_relation}" in not correct'.format(full_name_relation = full_name_relation))
71+
size = -1
72+
elif pg_total_relation_size ==-1 or pg_total_relation_size_part ==-1:
73+
self.log.error(
74+
"The relation: {full_name_relation} is lock. "
75+
"You can find this lock in query: "
76+
"SELECT relation::regclass AS lock_relation, mode FROM pg_locks WHERE relation::regclass = 'pg_locks'::regclass;".format(full_name_relation=full_name_relation))
77+
size = -1
78+
else:
79+
size = (pg_total_relation_size or 0) + (pg_total_relation_size_part or 0)
80+
81+
zbx.send('pgsql.relation.size[{0}]'.format(full_name_relation), int(size))
82+
83+
zbx.send('pgsql.relation.size[]', zbx.json({'data': rels}))
84+
85+
86+
def items(self, template):
87+
88+
return ''
89+
90+
def discovery_rules(self, template):
91+
rule = {
92+
'name': 'Relation size discovery',
93+
'key': self.key_rel_size_discovery.format('[{0}]'.format(self.Macros[self.Type])),
94+
}
95+
if Plugin.old_zabbix:
96+
conditions = []
97+
rule['filter'] = '{#RELATIONNAME}:.*'
98+
else:
99+
conditions = [
100+
{
101+
'condition': [
102+
{'macro': '{#RELATIONNAME}',
103+
'value': '.*',
104+
'operator': None,
105+
'formulaid': 'A'}
106+
]
107+
}
108+
]
109+
items = [
110+
{'key': self.right_type(self.key_rel_size_discovery, var_discovery="{#RELATIONNAME},"),
111+
'name': 'Relation size: {#RELATIONNAME}',
112+
'units': Plugin.UNITS.bytes,
113+
'value_type': Plugin.VALUE_TYPE.numeric_unsigned,
114+
'delay': self.plugin_config('interval')},
115+
]
116+
graphs = [
117+
{
118+
'name': 'PostgreSQL relation size: {#RELATIONNAME}',
119+
'type': 1,
120+
'items': [
121+
{'color': '00CC00',
122+
'key': self.right_type(self.key_rel_size_discovery, var_discovery="{#RELATIONNAME},")}]
123+
},
124+
]
125+
return template.discovery_rule(rule=rule, conditions=conditions, items=items, graphs=graphs)

packaging/conf/example.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,14 @@ interval = 2
167167
[agentapi]
168168
interval = 60
169169

170+
# Metrics with sizes of relations.
171+
# Relations - comma separated list of objects - tables and endexes (schema.relation) to calculate relations size.
172+
# Example:
173+
# relations="pg_catalog.pg_class,pg_catalog.pg_user"
174+
# If the ralation is block some operation lile vacuum full or create index, the result will be -1
175+
# by default this plagin disabled. To enable this plagin - write bellow enabled = False and define list or relation for count size.
176+
[relationssize]
177+
enabled = False
178+
relations=pg_catalog.pg_class,pg_catalog.pg_user
179+
interval = 500
180+

0 commit comments

Comments
 (0)