Added connections (backend) usage to postgres monitoring (#8126)
* Added connections (backend) usage to postgres monitoring * Adjusted PostgreSQL connection usage against server version * Changed PostgreSQL connection usage against server version * Fixed chart PG Backend Usage family and improved documentation
Manuel Pombo committed
Feb 28, 2020 at 16:21 UTC
822381f5e7fe9fa48a88a164b44edad8fa67ed6f
3 files changed
+121
-9
collectors/python.d.plugin/postgres/README.md
+13
-8
@@ -16,44 +16,49 @@ Following charts are drawn:
16
17
- active
18
19
-3. **Write-Ahead Logging Statistics** files/s
19
+3. **Current Backend Processe Usage** percentage
20
+
21
+ - used
22
+ - available
23
+
24
+4. **Write-Ahead Logging Statistics** files/s
25
26
- total
27
- ready
28
- done
29
25
-4. **Checkpoints** writes/s
30
+5. **Checkpoints** writes/s
31
32
- scheduled
33
- requested
34
30
-5. **Current connections to db** count
35
+6. **Current connections to db** count
36
37
- connections
38
34
-6. **Tuples returned from db** tuples/s
39
+7. **Tuples returned from db** tuples/s
40
41
- sequential
42
- bitmap
43
39
-7. **Tuple reads from db** reads/s
44
+8. **Tuple reads from db** reads/s
45
46
- disk
47
- cache
48
44
-8. **Transactions on db** transactions/s
49
+9. **Transactions on db** transactions/s
50
51
- committed
52
- rolled back
53
49
-9. **Tuples written to db** writes/s
54
+10. **Tuples written to db** writes/s
55
56
- inserted
57
- updated
58
- deleted
59
- conflicts
60
56
-10. **Locks on db** count per type
61
+11. **Locks on db** count per type
62
63
- locks
64
collectors/python.d.plugin/postgres/postgres.chart.py
+100
-1
@@ -39,6 +39,7 @@ CONN_PARAM_SSL_KEY = 'sslkey'
39
QUERY_NAME_WAL = 'WAL'
40
QUERY_NAME_ARCHIVE = 'ARCHIVE'
41
QUERY_NAME_BACKENDS = 'BACKENDS'
42
+QUERY_NAME_BACKEND_USAGE = 'BACKEND_USAGE'
43
QUERY_NAME_TABLE_STATS = 'TABLE_STATS'
44
QUERY_NAME_INDEX_STATS = 'INDEX_STATS'
45
QUERY_NAME_DATABASE = 'DATABASE'
@@ -76,6 +77,10 @@ METRICS = {
77
'backends_active',
78
'backends_idle'
79
],
80
+ QUERY_NAME_BACKEND_USAGE: [
81
+ 'available',
82
+ 'used'
83
+ ],
84
QUERY_NAME_INDEX_STATS: [
85
'index_count',
86
'index_size'
@@ -139,6 +144,10 @@ METRICS = {
144
145
NO_VERSION = 0
146
DEFAULT = 'DEFAULT'
147
+V72 = 'V72'
148
+V82 = 'V82'
149
+V91 = 'V91'
150
+V92 = 'V92'
151
V96 = 'V96'
152
V10 = 'V10'
153
V11 = 'V11'
@@ -235,6 +244,76 @@ FROM pg_stat_activity;
244
""",
245
}
246
247
+QUERY_BACKEND_USAGE = {
248
+ DEFAULT: """
249
+SELECT
250
+ COUNT(1) as used,
251
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
252
+ - COUNT(1) AS available
253
+FROM pg_catalog.pg_stat_activity
254
+WHERE backend_type IN ('client backend', 'background worker');
255
+""",
256
+ V10: """
257
+SELECT
258
+ SUM(s.conn) as used,
259
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
260
+ - SUM(s.conn) AS available
261
+FROM (
262
+ SELECT 's' as type, COUNT(1) as conn
263
+ FROM pg_catalog.pg_stat_activity
264
+ WHERE backend_type IN ('client backend', 'background worker')
265
+ UNION ALL
266
+ SELECT 'r', COUNT(1)
267
+ FROM pg_catalog.pg_stat_replication
268
+) as s;
269
+""",
270
+ V92: """
271
+SELECT
272
+ SUM(s.conn) as used,
273
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
274
+ - SUM(s.conn) AS available
275
+FROM (
276
+ SELECT 's' as type, COUNT(1) as conn
277
+ FROM pg_catalog.pg_stat_activity
278
+ WHERE query NOT LIKE 'autovacuum: %%'
279
+ UNION ALL
280
+ SELECT 'r', COUNT(1)
281
+ FROM pg_catalog.pg_stat_replication
282
+) as s;
283
+""",
284
+ V91: """
285
+SELECT
286
+ SUM(s.conn) as used,
287
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
288
+ - SUM(s.conn) AS available
289
+FROM (
290
+ SELECT 's' as type, COUNT(1) as conn
291
+ FROM pg_catalog.pg_stat_activity
292
+ WHERE current_query NOT LIKE 'autovacuum: %%'
293
+ UNION ALL
294
+ SELECT 'r', COUNT(1)
295
+ FROM pg_catalog.pg_stat_replication
296
+) as s;
297
+""",
298
+ V82: """
299
+SELECT
300
+ COUNT(1) as used,
301
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
302
+ - COUNT(1) AS available
303
+FROM pg_catalog.pg_stat_activity
304
+WHERE current_query NOT LIKE 'autovacuum: %%';
305
+""",
306
+ V72: """
307
+SELECT
308
+ COUNT(1) as used,
309
+ current_setting('max_connections')::int - current_setting('superuser_reserved_connections')::int
310
+ - COUNT(1) AS available
311
+FROM pg_catalog.pg_stat_activity s
312
+JOIN pg_catalog.pg_database d ON d.oid = s.datid
313
+WHERE d.datallowconn;
314
+""",
315
+}
316
+
317
QUERY_TABLE_STATS = {
318
DEFAULT: """
319
SELECT
@@ -528,10 +607,21 @@ SELECT
607
""",
608
}
609
531
-
610
def query_factory(name, version=NO_VERSION):
611
if name == QUERY_NAME_BACKENDS:
612
return QUERY_BACKEND[DEFAULT]
613
+ elif name == QUERY_NAME_BACKEND_USAGE:
614
+ if version < 80200:
615
+ return QUERY_BACKEND_USAGE[V72]
616
+ if version < 90100:
617
+ return QUERY_BACKEND_USAGE[V82]
618
+ if version < 90200:
619
+ return QUERY_BACKEND_USAGE[V91]
620
+ if version < 100000:
621
+ return QUERY_BACKEND_USAGE[V92]
622
+ elif version < 120000:
623
+ return QUERY_BACKEND_USAGE[V10]
624
+ return QUERY_BACKEND_USAGE[DEFAULT]
625
elif name == QUERY_NAME_TABLE_STATS:
626
return QUERY_TABLE_STATS[DEFAULT]
627
elif name == QUERY_NAME_INDEX_STATS:
@@ -588,6 +678,7 @@ ORDER = [
678
'db_stat_connections',
679
'database_size',
680
'backend_process',
681
+ 'backend_usage',
682
'index_count',
683
'index_size',
684
'table_count',
@@ -674,6 +765,13 @@ CHARTS = {
765
['backends_idle', 'idle', 'absolute']
766
]
767
},
768
+ 'backend_usage': {
769
+ 'options': [None, '% of Connections in use', 'percentage', 'backend processes', 'postgres.backend_usage', 'stacked'],
770
+ 'lines': [
771
+ ['available', 'available', 'percentage-of-absolute-row'],
772
+ ['used', 'used', 'percentage-of-absolute-row']
773
+ ]
774
+ },
775
'index_count': {
776
'options': [None, 'Total indexes', 'index', 'indexes', 'postgres.index_count', 'line'],
777
'lines': [
@@ -970,6 +1068,7 @@ class Service(SimpleService):
1068
def populate_queries(self):
1069
self.queries[query_factory(QUERY_NAME_DATABASE)] = METRICS[QUERY_NAME_DATABASE]
1070
self.queries[query_factory(QUERY_NAME_BACKENDS)] = METRICS[QUERY_NAME_BACKENDS]
1071
+ self.queries[query_factory(QUERY_NAME_BACKEND_USAGE, self.server_version)] = METRICS[QUERY_NAME_BACKEND_USAGE]
1072
self.queries[query_factory(QUERY_NAME_LOCKS)] = METRICS[QUERY_NAME_LOCKS]
1073
self.queries[query_factory(QUERY_NAME_BGWRITER)] = METRICS[QUERY_NAME_BGWRITER]
1074
self.queries[query_factory(QUERY_NAME_DIFF_LSN, self.server_version)] = METRICS[QUERY_NAME_WAL_WRITES]
web/gui/dashboard_info.js
+8
@@ -1402,6 +1402,14 @@ netdataDashboard.context = {
1402
'</ul>' +
1403
'For more information see <a href="https://www.postgresql.org/docs/current/static/warm-standby.html#STREAMING-REPLICATION-SLOTS" target="_blank">Replication Slots</a>.'
1404
},
1405
+ 'postgres.backend_usage': {
1406
+ info: 'Connections usage against maximum connections allowed, as defined in the <i>max_connections</i> setting.<ul>' +
1407
+ '<li><strong>available:</strong> maximum new connections allowed.</li>' +
1408
+ '<li><strong>used:</strong> connections currently in use.</li>' +
1409
+ '</ul>' +
1410
+ 'Assuming non-superuser accounts are being used to connect to Postgres (so <i>superuser_reserved_connections</i> are subtracted from <i>max_connections</i>).<br/>' +
1411
+ 'For more information see <a href="https://www.postgresql.org/docs/current/runtime-config-connection.html" target="_blank">Connections and Authentication</a>.'
1412
+ },
1413
1414
1415
// ------------------------------------------------------------------------