Skip to content

Commit 342d27e

Browse files
committed
v2.2.2: add cfs plugin
1 parent 2979e4b commit 342d27e

File tree

14 files changed

+1102
-28
lines changed

14 files changed

+1102
-28
lines changed

mamonsu/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
__author__ = 'Dmitry Vasilyev'
22
__author_email__ = '[email protected]'
33
__description__ = 'Monitoring agent for PostgreSQL'
4-
__version__ = '2.2.1'
4+
__version__ = '2.2.2'
55
__licence__ = 'BSD'
66

77
__url__ = 'https://github.com/postgrespro/mamonsu'

mamonsu/lib/sender.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44

55
from mamonsu.lib.plugin import Plugin
6+
import mamonsu.lib.platform as platform
67

78

89
class Sender():
@@ -25,15 +26,18 @@ def add_sender(self, sender):
2526
self._senders.append(sender)
2627

2728
# resend all values to senders
28-
def send(self, key, value, delta=None, host=None, clock=None):
29+
def send(self, key, value, delta=None, host=None, clock=None, only_positive_speed=False):
2930

3031
if clock is None:
3132
clock = int(time.time())
3233

3334
hash_key = self._hash(key, host)
3435
if delta is not None:
35-
if isinstance(value, float) or isinstance(value, int):
36+
if isinstance(value, float) or isinstance(value, platform.INTEGER_TYPES):
3637
if hash_key in self._last_values:
38+
if only_positive_speed and (self._last_values[hash_key][0] > value):
39+
self._last_values[hash_key] = (value, clock)
40+
return
3741
last_value, last_time = self._last_values[hash_key]
3842
self._last_values[hash_key] = (value, clock)
3943
if delta == Plugin.DELTA.speed_per_second:

mamonsu/plugins/pgsql/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
__all__ += ['health', 'instance', 'xlog']
33
__all__ += ['pg_stat_statement', 'pg_buffercache', 'pg_wait_sampling']
44
__all__ += ['checkpoint', 'oldest', 'pg_locks']
5+
__all__ += ['cfs']
56

67
from . import *

mamonsu/plugins/pgsql/cfs.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from mamonsu.plugins.pgsql.plugin import PgsqlPlugin as Plugin
4+
from .pool import Pooler
5+
6+
7+
class Cfs(Plugin):
8+
9+
Interval = 5 * 60
10+
11+
DEFAULT_CONFIG = {'force_enable': str(False)}
12+
13+
compressed_ratio_sql = """
14+
select
15+
n.nspname || '.' || c.relname as table_name,
16+
cfs_compression_ratio(c.oid::regclass) as ratio,
17+
(pg_catalog.pg_total_relation_size(c.oid::regclass) - pg_catalog.pg_indexes_size(c.oid::regclass)) as compressed_size
18+
from
19+
pg_catalog.pg_class as c
20+
left join pg_catalog.pg_namespace n on n.oid = c.relnamespace
21+
where c.reltablespace in (select oid from pg_catalog.pg_tablespace where spcoptions::text ~ 'compression')
22+
and c.relkind IN ('r','v','m','S','f','')
23+
24+
union all
25+
26+
select
27+
n.nspname || '.' || c.relname as table_name,
28+
cfs_compression_ratio(c.oid::regclass) as ratio,
29+
pg_catalog.pg_total_relation_size(c.oid::regclass) as compressed_size -- pg_toast included
30+
from
31+
pg_catalog.pg_class as c
32+
left join pg_catalog.pg_namespace n on n.oid = c.relnamespace
33+
where c.reltablespace in (select oid from pg_catalog.pg_tablespace where spcoptions::text ~ 'compression')
34+
and c.relkind = 'i' and n.nspname <> 'pg_toast';
35+
"""
36+
37+
activity_sql = """
38+
select
39+
cfs_gc_activity_processed_bytes(), -- writed
40+
cfs_gc_activity_processed_pages() * 8 * 1024, -- scanned
41+
cfs_gc_activity_processed_files(), -- writed
42+
cfs_gc_activity_scanned_files(); -- scanned
43+
"""
44+
45+
prev = {}
46+
47+
def run(self, zbx):
48+
49+
if self.plugin_config('force_enable') == 'False':
50+
self.disable_and_exit_if_not_pgpro_ee()
51+
52+
relations, compressed_size, non_compressed_size = [], 0, 0
53+
for db in Pooler.databases:
54+
for row in Pooler.query(self.compressed_ratio_sql, db):
55+
relation_name = '{0}.{1}'.format(db, row[0])
56+
relations.append({'{#COMPRESSED_RELATION}': relation_name})
57+
compressed_size += row[2]
58+
non_compressed_size += row[2] * row[1]
59+
zbx.send('pgsql.cfs.relation[{0}]'.format(row[0]), row[1])
60+
zbx.send('pgsql.cfs.discovery_compressed_relations[]', zbx.json({'data': relations}))
61+
zbx.send('pgsql.cfs.activity[total_compress_ratio]', non_compressed_size / compressed_size)
62+
del(relations, compressed_size, non_compressed_size)
63+
64+
info = Pooler.query(self.activity_sql)[0]
65+
zbx.send('pgsql.cfs.activity[writed_bytes]', info[0], delta=self.DELTA_SPEED, only_positive_speed=True)
66+
zbx.send('pgsql.cfs.activity[scanned_bytes]', info[1], delta=self.DELTA_SPEED, only_positive_speed=True)
67+
68+
# calculate current compress ratio
69+
if ('writed_bytes' in self.prev) and ('scanned_bytes' in self.prev):
70+
if info[0] > self.prev['writed_bytes'] and info[1] > self.prev['scanned_bytes']:
71+
val = (self.prev['scanned_bytes'] - info[1]) / ((self.prev['writed_bytes'] - info[0]) * self.Interval)
72+
zbx.send('pgsql.cfs.activity[current_compress_ratio]', val)
73+
self.prev['writed_bytes'] = info[0]
74+
self.prev['scanned_bytes'] = info[1]
75+
76+
zbx.send('pgsql.cfs.activity[compressed_files]', info[2], delta=self.DELTA_SPEED, only_positive_speed=True)
77+
zbx.send('pgsql.cfs.activity[scanned_files]', info[3], delta=self.DELTA_SPEED, only_positive_speed=True)
78+
79+
def items(self, template):
80+
return template.item({
81+
'name': 'PostgreSQL cfs compression: Writed byte/s',
82+
'key': 'pgsql.cfs.activity[writed_bytes]',
83+
'delay': self.Interval
84+
}) + template.item({
85+
'name': 'PostgreSQL cfs compression: Scanned byte/s',
86+
'key': 'pgsql.cfs.activity[scanned_bytes]',
87+
'delay': self.Interval
88+
}) + template.item({
89+
'name': 'PostgreSQL cfs compression: compressed files/s',
90+
'key': 'pgsql.cfs.activity[compressed_files]',
91+
'delay': self.Interval
92+
}) + template.item({
93+
'name': 'PostgreSQL cfs compression: scanned files/s',
94+
'key': 'pgsql.cfs.activity[scanned_files]',
95+
'delay': self.Interval
96+
}) + template.item({
97+
'name': 'PostgreSQL cfs compression: current ratio',
98+
'key': 'pgsql.cfs.activity[current_compress_ratio]',
99+
'delay': self.Interval
100+
}) + template.item({
101+
'name': 'PostgreSQL cfs compression: total ratio',
102+
'key': 'pgsql.cfs.activity[total_compress_ratio]',
103+
'delay': self.Interval
104+
})
105+
106+
def graphs(self, template):
107+
result = template.graph({
108+
'name': 'PostgreSQL cfs compression: current ratio',
109+
'items': [{
110+
'key': 'pgsql.cfs.activity[current_compress_ratio]',
111+
'color': '00CC00'
112+
}]
113+
})
114+
result += template.graph({
115+
'name': 'PostgreSQL cfs compression: compressed files',
116+
'items': [{
117+
'key': 'pgsql.cfs.activity[compressed_files]',
118+
'color': '00CC00'
119+
}]
120+
})
121+
result += template.graph({
122+
'name': 'PostgreSQL cfs compression: writed bytes',
123+
'items': [{
124+
'key': 'pgsql.cfs.activity[writed_bytes]',
125+
'color': '00CC00'
126+
}]
127+
})
128+
return result
129+
130+
def discovery_rules(self, template):
131+
rule = {
132+
'name': 'Compressed relations discovery',
133+
'key': 'pgsql.cfs.discovery_compressed_relations[]',
134+
'filter': '{#COMPRESSED_RELATION}:.*'
135+
}
136+
items = [
137+
{'key': 'pgsql.cfs.relation[{#COMPRESSED_RELATION}]',
138+
'name': 'Relation {#COMPRESSED_RELATION}: compression ratio',
139+
'delay': self.Interval}
140+
]
141+
graphs = [
142+
{
143+
'name': 'Relation {#COMPRESSED_RELATION}: compression ratio',
144+
'delay': self.Interval,
145+
'items': [
146+
{'color': '00CC00',
147+
'key': 'pgsql.cfs.relation[{#COMPRESSED_RELATION}]'}]
148+
},
149+
]
150+
return template.discovery_rule(rule=rule, items=items, graphs=graphs)

mamonsu/plugins/pgsql/driver/_connection.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
class ConnectionInfo(object):
1111

1212
def __init__(self, info={}):
13-
self._connection_info = info
14-
self.host = info.get('host') or os.environ.get('PGHOST')
15-
self.port = info.get('port') or int(os.environ.get('PGPORT') or 5432)
16-
self.user = info.get('user') or os.environ.get('PGUSER')
17-
self.passwd = info.get('passwd') or os.environ.get('PGPASSWORD')
18-
self.db = info.get('db') or os.environ.get('PGDATABASE')
19-
self.timeout = info.get('timeout') or int(
13+
self.info = info
14+
self.host = self.info.get('host') or os.environ.get('PGHOST')
15+
self.port = self.info.get('port') or int(os.environ.get('PGPORT') or 5432)
16+
self.user = self.info.get('user') or os.environ.get('PGUSER')
17+
self.passwd = self.info.get('passwd') or os.environ.get('PGPASSWORD')
18+
self.db = self.info.get('db') or os.environ.get('PGDATABASE')
19+
self.timeout = self.info.get('timeout') or int(
2020
os.environ.get('PGTIMEOUT') or 1)
21-
self.appname = info.get('appname') or os.environ.get('PGAPPNAME')
21+
self.appname = self.info.get('appname') or os.environ.get('PGAPPNAME')
2222
self.log = logging.getLogger('PGSQL-({0})'.format(self.conn_str()))
2323

2424
def conn_str(self):

mamonsu/plugins/pgsql/driver/pool.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ def __init__(self):
5050
}
5151

5252
def connection_string(self, db=None):
53-
self._init_conn_(db)
53+
self._init_connection(db)
5454
return self.all_connections[db].conn_str()
5555

5656
def query(self, query, db=None):
5757
if db is None:
5858
db = self.db
59-
self._init_conn_(db)
59+
self._init_connection(db)
6060
return self.all_connections[db].query(query)
6161

6262
def server_version(self, db=None):
@@ -115,7 +115,7 @@ def is_pgpro(self, db=None):
115115
return self._cache['pgpro'][db]
116116

117117
def is_pgpro_ee(self, db=None):
118-
if not self.is_pgpro(self, db):
118+
if not self.is_pgpro(db):
119119
return False
120120
if db in self._cache['pgproee']:
121121
return self._cache['pgproee'][db]
@@ -149,9 +149,9 @@ def get_sql(self, typ, db=None):
149149
def run_sql_type(self, typ, db=None):
150150
return self.query(self.get_sql(typ, db), db)
151151

152-
def _init_conn_(self, db):
153-
conn = self.all_connections.get(db)
154-
if conn is None:
155-
info = self._connection_info
152+
def _init_connection(self, db):
153+
if db not in self.all_connections:
154+
# create new connection
155+
info = self.info
156156
info['db'] = db
157157
self.all_connections[db] = Connection(info)

mamonsu/plugins/pgsql/oldest.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,20 @@ def run(self, zbx):
3030
zbx.send('pgsql.oldest[query_time]', query)
3131

3232
def graphs(self, template):
33-
graph = {
33+
result = template.graph({
3434
'name': 'PostgreSQL oldest query running time',
3535
'items': [{
3636
'key': 'pgsql.oldest[query_time]',
3737
'color': '00CC00'
3838
}]
39-
}
40-
result = template.graph(graph)
41-
graph = {
39+
})
40+
result += template.graph({
4241
'name': 'PostgreSQL age of oldest xid',
4342
'items': [{
4443
'key': 'pgsql.oldest[xid_age]',
4544
'color': '00CC00'
4645
}]
47-
}
48-
result += template.graph(graph)
46+
})
4947
return result
5048

5149
def items(self, template):

mamonsu/plugins/pgsql/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ def disable_and_exit_if_extension_is_not_installed(self, ext, db=None):
4444
def disable_and_exit_if_not_pgpro_ee(self, db=None):
4545
if not Pooler.is_pgpro_ee(db):
4646
raise PluginDisableException("""Disable plugin and exit, because \
47-
PostgresPro Enterprise Edition is not detected [instance: '{1}']
47+
PostgresPro Enterprise Edition is not detected [instance: '{0}']
4848
""".format(Pooler.connection_string(db)))

mamonsu/plugins/pgsql/pool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# -*- coding: utf-8 -*-
22

33
from mamonsu.plugins.pgsql.driver.pool import Pool
4-
Pooler = Pool()
4+
Pooler = Pool() # create connection with environment var

mamonsu/plugins/system/linux/disk_stats.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def run(self, zbx):
4141
zbx.send('system.disk.write[{0}]'.format(
4242
dev), write, self.DELTA_SPEED)
4343
zbx.send('system.disk.utilization[{0}]'.format(
44-
dev), ticks/10, self.DELTA_SPEED)
44+
dev), ticks / 10, self.DELTA_SPEED)
4545

4646
zbx.send('system.disk.all_read[]', all_read, self.DELTA_SPEED)
4747
zbx.send('system.disk.all_write[]', all_write, self.DELTA_SPEED)

0 commit comments

Comments
 (0)