Compare commits
2 Commits
ebb084aa9d
...
24d1214855
| Author | SHA1 | Date | |
|---|---|---|---|
| 24d1214855 | |||
| 3c39d8aa97 |
@ -8,14 +8,21 @@ metrics:
|
||||
0: >
|
||||
SELECT datname AS dbname
|
||||
FROM pg_database
|
||||
|
||||
# Note: If the user lacks sufficient privileges, these fields will be NULL.
|
||||
# The WHERE clause is intended to prevent Zabbix from discovering a
|
||||
# connection it cannot monitor. Ideally this would generate an error
|
||||
# instead.
|
||||
discover_rep:
|
||||
type: set
|
||||
query:
|
||||
0: >
|
||||
SELECT client_addr || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') AS repid,
|
||||
SELECT host(client_addr) || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') AS repid,
|
||||
client_addr,
|
||||
state
|
||||
FROM pg_stat_replication
|
||||
WHERE state IS NOT NULL
|
||||
|
||||
discover_slots:
|
||||
type: set
|
||||
query:
|
||||
@ -36,6 +43,7 @@ metrics:
|
||||
active
|
||||
FROM pg_replication_slots
|
||||
|
||||
|
||||
##
|
||||
# cluster-wide metrics
|
||||
##
|
||||
@ -85,7 +93,6 @@ metrics:
|
||||
FROM pg_stat_bgwriter bg
|
||||
CROSS JOIN pg_stat_checkpointer cp
|
||||
|
||||
|
||||
io_per_backend:
|
||||
type: set
|
||||
query:
|
||||
@ -108,6 +115,7 @@ metrics:
|
||||
FROM pg_stat_io
|
||||
GROUP BY backend_type
|
||||
|
||||
|
||||
##
|
||||
# Per-database metrics
|
||||
##
|
||||
@ -210,14 +218,20 @@ metrics:
|
||||
# FROM pg_class c
|
||||
# CROSS JOIN LATERAL pg_sequence_parameters(c.oid) AS s
|
||||
# WHERE c.relkind = 'S'
|
||||
100000: >
|
||||
SELECT COALESCE(MAX(pg_sequence_last_value(c.oid)::float / sp.maximum_value), 0) AS max_usage
|
||||
FROM pg_class c
|
||||
CROSS JOIN LATERAL pg_sequence_parameters(c.oid) AS sp
|
||||
WHERE c.relkind = 'S'
|
||||
100000: SELECT COALESCE(MAX(last_value::float / max_value), 0) AS max_usage FROM pg_sequences;
|
||||
test_args:
|
||||
dbname: postgres
|
||||
|
||||
sequence_visibility:
|
||||
type: row
|
||||
query:
|
||||
100000: >
|
||||
SELECT COUNT(*) FILTER (WHERE has_sequence_privilege(c.oid, 'SELECT,USAGE'::text)) AS readable_sequences,
|
||||
COUNT(*) AS total_sequences
|
||||
FROM pg_class AS c
|
||||
WHERE relkind = 'S';
|
||||
|
||||
|
||||
##
|
||||
# Per-replication metrics
|
||||
##
|
||||
@ -237,7 +251,7 @@ metrics:
|
||||
NULL AS replay_lag,
|
||||
sync_state
|
||||
FROM pg_stat_replication
|
||||
WHERE client_addr || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') = %(repid)s
|
||||
WHERE host(client_addr) || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') = %(repid)s
|
||||
100000: >
|
||||
SELECT pid, usename,
|
||||
EXTRACT(EPOCH FROM backend_start)::integer AS backend_start,
|
||||
@ -250,7 +264,8 @@ metrics:
|
||||
COALESCE(EXTRACT(EPOCH FROM flush_lag), 0)::integer AS flush_lag,
|
||||
COALESCE(EXTRACT(EPOCH FROM replay_lag), 0)::integer AS replay_lag,
|
||||
sync_state
|
||||
FROM pg_stat_replication WHERE client_addr || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') = %(repid)s
|
||||
FROM pg_stat_replication
|
||||
WHERE host(client_addr) || '_' || regexp_replace(application_name, '[ ,]', '_', 'g') = %(repid)s
|
||||
test_args:
|
||||
repid: 127.0.0.1_test_rep
|
||||
|
||||
@ -264,24 +279,25 @@ metrics:
|
||||
90400: >
|
||||
SELECT NULL as active_pid,
|
||||
xmin,
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn) AS restart_bytes,
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)::bigint AS restart_bytes,
|
||||
NULL AS confirmed_flush_bytes
|
||||
FROM pg_replication_slots WHERE slot_name = %(slot)s
|
||||
90600: >
|
||||
SELECT active_pid,
|
||||
xmin,
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn) AS restart_bytes,
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), confirmed_flush_lsn) AS confirmed_flush_bytes
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)::bigint AS restart_bytes,
|
||||
pg_xlog_location_diff(pg_current_xlog_location(), confirmed_flush_lsn)::bigint AS confirmed_flush_bytes
|
||||
FROM pg_replication_slots WHERE slot_name = %(slot)s
|
||||
100000: >
|
||||
SELECT active_pid,
|
||||
xmin,
|
||||
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS restart_bytes,
|
||||
pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) AS confirmed_flush_bytes
|
||||
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)::bigint AS restart_bytes,
|
||||
pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)::bigint AS confirmed_flush_bytes
|
||||
FROM pg_replication_slots WHERE slot_name = %(slot)s
|
||||
test_args:
|
||||
slot: test_slot
|
||||
|
||||
|
||||
##
|
||||
# Debugging
|
||||
##
|
||||
|
||||
16
src/pgmon.py
16
src/pgmon.py
@ -27,6 +27,8 @@ from urllib.parse import urlparse, parse_qs
|
||||
import requests
|
||||
import re
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
VERSION = "1.0.3"
|
||||
|
||||
# Configuration
|
||||
@ -391,6 +393,16 @@ def get_query(metric, version):
|
||||
raise MetricVersionError("Missing metric query for PostgreSQL {}".format(version))
|
||||
|
||||
|
||||
def json_encode_special(obj):
|
||||
"""
|
||||
Encoder function to handle types the standard JSON package doesn't know what
|
||||
to do with
|
||||
"""
|
||||
if isinstance(obj, Decimal):
|
||||
return float(obj)
|
||||
raise TypeError(f'Cannot serialize object of {type(obj)}')
|
||||
|
||||
|
||||
def run_query_no_retry(pool, return_type, query, args):
|
||||
"""
|
||||
Run the query with no explicit retry code
|
||||
@ -408,11 +420,11 @@ def run_query_no_retry(pool, return_type, query, args):
|
||||
elif return_type == "row":
|
||||
if len(res) == 0:
|
||||
return "[]"
|
||||
return json.dumps(res[0])
|
||||
return json.dumps(res[0], default=json_encode_special)
|
||||
elif return_type == "column":
|
||||
if len(res) == 0:
|
||||
return "[]"
|
||||
return json.dumps([list(r.values())[0] for r in res])
|
||||
return json.dumps([list(r.values())[0] for r in res], default=json_encode_special)
|
||||
elif return_type == "set":
|
||||
return json.dumps(res)
|
||||
except:
|
||||
|
||||
@ -5,6 +5,8 @@ import tempfile
|
||||
|
||||
import logging
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
import pgmon
|
||||
|
||||
# Silence most logging output
|
||||
@ -789,3 +791,17 @@ metrics:
|
||||
# Make sure we can pull the RSS file (we assume the 9.6 series won't be getting
|
||||
# any more updates)
|
||||
self.assertEqual(pgmon.get_latest_version(), 90624)
|
||||
|
||||
def test_json_encode_special(self):
|
||||
# Confirm that we're getting the right type
|
||||
self.assertFalse(isinstance(Decimal('0.5'), float))
|
||||
self.assertTrue(isinstance(pgmon.json_encode_special(Decimal('0.5')), float))
|
||||
|
||||
# Make sure we get sane values
|
||||
self.assertEqual(pgmon.json_encode_special(Decimal('0.5')), 0.5)
|
||||
self.assertEqual(pgmon.json_encode_special(Decimal('12')), 12.0)
|
||||
|
||||
# Make sure we can still fail for other types
|
||||
self.assertRaises(
|
||||
TypeError, pgmon.json_encode_special, object
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user