diff --git a/.github/workflows/mamonsu-tests-dev.yml b/.github/workflows/mamonsu-tests-dev.yml
index c259768..41f1f3b 100644
--- a/.github/workflows/mamonsu-tests-dev.yml
+++ b/.github/workflows/mamonsu-tests-dev.yml
@@ -45,6 +45,9 @@ jobs:
- docker_os: 'ubuntu:24.04'
pg_version: '16'
zabbix_version: '6.4.13'
+ - docker_os: 'ubuntu:24.04'
+ pg_version: '18'
+ zabbix_version: '6.4.13'
exclude:
- docker_os: 'centos:8'
pg_version: '12'
diff --git a/.github/workflows/mamonsu-tests-master.yml b/.github/workflows/mamonsu-tests-master.yml
index af22e98..d1a7943 100644
--- a/.github/workflows/mamonsu-tests-master.yml
+++ b/.github/workflows/mamonsu-tests-master.yml
@@ -45,6 +45,9 @@ jobs:
- docker_os: 'ubuntu:24.04'
pg_version: '16'
zabbix_version: '6.4.13'
+ - docker_os: 'ubuntu:24.04'
+ pg_version: '18'
+ zabbix_version: '6.4.13'
exclude:
# excludes PG 15, 16 on CentOS
- docker_os: 'centos:7'
diff --git a/documentation/metrics.md b/documentation/metrics.md
index d507a8e..ccdaebc 100644
--- a/documentation/metrics.md
+++ b/documentation/metrics.md
@@ -2374,6 +2374,69 @@ Default config:
*Buffers Written During Checkpoints* maps `buffers_written`.
+- **Done Checkpoints**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Checkpoints: Done (in hour) |
+
+
+ | Key |
+ pgsql.checkpoint[count_done] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Speed Per Second |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *Done Checkpoints* maps `num_done`.
+
+- **SLRU Written**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Checkpoints: SLRU Written (in hour) |
+
+
+ | Key |
+ pgsql.checkpoint[slru_written] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Speed Per Second |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *SLRU Written* maps `slru_written`.
### Graphs
@@ -2920,6 +2983,70 @@ Default config:
*Checksum Failures* maps `checksum_failures`.
+- **Parallel Workers To Launch**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Instance: Parallel Workers To Launch |
+
+
+ | Key |
+ pgsql.parallel[instance_to_launch] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Simple Change |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *Parallel Workers To Launch* maps `parallel_workers_to_launch`.
+
+- **Parallel Workers Launched**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Instance: Parallel Workers Launched |
+
+
+ | Key |
+ pgsql.parallel[instance_launched] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Simple Change |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *Parallel Workers Launched* maps `parallel_workers_launched`.
+
### Graphs
@@ -4001,6 +4128,37 @@ Default config:
*Amount of WAL Records* maps `wal_records`.
+- **WAL Buffers Full**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Statements: WAL Buffers Full |
+
+
+ | Key |
+ pgsql.stat[wal_buffers_full] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Simple Change |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *WAL Buffers Full* maps `wal_buffers_full`.
- **Dirty Bytes**
@@ -4298,6 +4456,70 @@ Default config:
*pg_stat_statements.max Exceeding Count* maps `dealloc`.
+- **Parallel Workers To Launch**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Statements: Parallel Workers To Launch |
+
+
+ | Key |
+ pgsql.parallel[statements_to_launch] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Simple Change |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *Parallel Workers To Launch* maps `parallel_workers_to_launch`.
+
+- **Parallel Workers Launched**
+
+ Zabbix item:
+
+
+ | Name |
+ PostgreSQL Statements: Parallel Workers Launched |
+
+
+ | Key |
+ pgsql.parallel[statements_launched] |
+
+
+ | Type |
+ Numeric (float) |
+
+
+ | Units |
+ |
+
+
+ | Delta |
+ Simple Change |
+
+
+ | Supported Version |
+ 18+ |
+
+
+
+ *Parallel Workers Launched* maps `parallel_workers_launched`.
+
### Graphs
diff --git a/github-actions-tests/metrics.sh b/github-actions-tests/metrics.sh
index 5ea6694..c7c37db 100644
--- a/github-actions-tests/metrics.sh
+++ b/github-actions-tests/metrics.sh
@@ -64,6 +64,7 @@ for metric in $(cat ${METRICS_FILE}); do
GREP=$( mamonsu agent metric-get ${metric} | grep "pgsql\|sys\|mamonsu" )
if [ -z "$GREP" ]; then
echo "---> ERROR: Cannot found metric $metric"
+ mamonsu agent metric-list
exit 11
fi
done
diff --git a/github-actions-tests/sources/metrics-linux-18.txt b/github-actions-tests/sources/metrics-linux-18.txt
new file mode 100644
index 0000000..3e0c098
--- /dev/null
+++ b/github-actions-tests/sources/metrics-linux-18.txt
@@ -0,0 +1,123 @@
+mamonsu.memory.rss[max]
+mamonsu.plugin.errors[]
+mamonsu.plugin.keepalive[]
+pgsql.archive_command[archived_files]
+pgsql.archive_command[count_files_to_archive]
+pgsql.archive_command[failed_trying_to_archive]
+pgsql.archive_command[size_files_to_archive]
+pgsql.autovacuum.count[]
+pgsql.autovacuum.utilization[]
+pgsql.bgwriter[buffers_alloc]
+pgsql.bgwriter[buffers_clean]
+pgsql.bgwriter[maxwritten_clean]
+pgsql.blocks[hit]
+pgsql.blocks[read]
+pgsql.checkpoint[checkpoint_sync_time]
+pgsql.checkpoint[count_timed]
+pgsql.checkpoint[count_wal]
+pgsql.checkpoint[write_time]
+pgsql.checkpoint[count_done]
+pgsql.checkpoint[slru_written]
+pgsql.connections[active]
+pgsql.connections[disabled]
+pgsql.connections[fastpath_function_call]
+pgsql.connections[idle]
+pgsql.connections[idle_in_transaction]
+pgsql.connections[idle_in_transaction_aborted]
+pgsql.connections[max_connections]
+pgsql.connections[other]
+pgsql.connections[total]
+pgsql.connections[waiting]
+pgsql.database.discovery[]
+pgsql.database.bloating_tables[mamonsu_test_db]
+pgsql.database.bloating_tables[postgres]
+pgsql.database.invalid_indexes[mamonsu_test_db]
+pgsql.database.invalid_indexes[postgres]
+pgsql.database.max_age[mamonsu_test_db]
+pgsql.database.max_age[postgres]
+pgsql.database.size[mamonsu_test_db]
+pgsql.database.size[postgres]
+pgsql.events[checksum_failures]
+pgsql.events[conflicts]
+pgsql.events[deadlocks]
+pgsql.events[xact_rollback]
+pgsql.oldest[transaction_time]
+pgsql.oldest[xid_age]
+pgsql.ping[]
+pgsql.pg_locks[accessexclusive]
+pgsql.pg_locks[accessshare]
+pgsql.pg_locks[exclusive]
+pgsql.pg_locks[rowexclusive]
+pgsql.pg_locks[rowshare]
+pgsql.pg_locks[share]
+pgsql.pg_locks[sharerowexclusive]
+pgsql.pg_locks[shareupdateexclusive]
+pgsql.parallel[instance_to_launch]
+pgsql.parallel[instance_launched]
+pgsql.parallel[queries]
+pgsql.parallel[statements_to_launch]
+pgsql.parallel[statements_launched]
+pgsql.prepared.count
+pgsql.prepared.oldest
+pgsql.relation.size[]
+pgsql.relation.size[mamonsu_test_db.mamonsu.config]
+pgsql.relation.size[postgres.pg_catalog.pg_class]
+pgsql.replication.non_active_slots[]
+pgsql.replication_lag[sec]
+pgsql.replication_lag[sec]
+pgsql.stat[wal_buffers_full]
+pgsql.temp[bytes]
+pgsql.temp[files]
+pgsql.transactions[committed]
+pgsql.tuples[deleted]
+pgsql.tuples[fetched]
+pgsql.tuples[inserted]
+pgsql.tuples[returned]
+pgsql.tuples[updated]
+pgsql.uptime[]
+pgsql.wal.buffers_full[]
+pgsql.wal.count[]
+pgsql.wal.fpi.count[]
+pgsql.wal.records.count[]
+pgsql.wal.sync_time[]
+pgsql.wal.write[]
+pgsql.wal.write_time[]
+system.cpu[idle]
+system.cpu[iowait]
+system.cpu[irq]
+system.cpu[nice]
+system.cpu[softirq]
+system.cpu[system]
+system.cpu[user]
+system.disk.discovery[]
+system.disk.all_read[]
+system.disk.all_write[]
+system.disk.all_read_b[]
+system.disk.all_write_b[]
+system.la[1]
+system.memory[active]
+system.memory[available]
+system.memory[buffers]
+system.memory[cached]
+system.memory[committed]
+system.memory[inactive]
+system.memory[mapped]
+system.memory[page_tables]
+system.memory[slab]
+system.memory[swap]
+system.memory[swap_cache]
+system.memory[total]
+system.memory[vmalloc_used]
+system.memory[unused]
+system.memory[used]
+system.net.discovery[]
+system.open_files[]
+system.processes[blocked]
+system.processes[forkrate]
+system.processes[running]
+system.vfs.discovery[]
+system.vfs.free[/]
+system.vfs.percent_free[/]
+system.vfs.percent_inode_free[/]
+system.vfs.used[/]
+system.uptime[]
diff --git a/mamonsu/plugins/pgsql/checkpoint.py b/mamonsu/plugins/pgsql/checkpoint.py
index c1ca9ac..bb663db 100644
--- a/mamonsu/plugins/pgsql/checkpoint.py
+++ b/mamonsu/plugins/pgsql/checkpoint.py
@@ -8,6 +8,7 @@
class Checkpoint(Plugin):
AgentPluginType = "pg"
Interval = 60 * 5
+ FactorIndex = 6
key = "pgsql.checkpoint{0}"
@@ -86,6 +87,18 @@ def __init__(self, config):
("PostgreSQL Checkpoints: Write/Sync", "FF5656", 1),
Plugin.UNITS.ms, Plugin.DELTA.speed_per_second, 1)
]
+ if Pooler.server_version_greater("18"):
+ self.Items += [
+ ("num_done", "count_done",
+ "Done (in hour)",
+ ("PostgreSQL Checkpoints: Done (in hour)", "00CC00", 0),
+ Plugin.UNITS.none, Plugin.DELTA.speed_per_second, 60 * 60),
+
+ ("slru_written", "slru_written",
+ "SLRU Written (in hour)",
+ ("PostgreSQL Checkpoints: SLRU Written (in hour)", "00CC00", 0),
+ Plugin.UNITS.none, Plugin.DELTA.speed_per_second, 60 * 60)
+ ]
def run(self, zbx):
columns = [x[0] for x in self.Items]
@@ -174,8 +187,8 @@ def triggers(self, template, dashboard=False):
def keys_and_queries(self, template_zabbix):
result = []
- for num, item in enumerate(self.Items):
- if num > 1:
+ for item in self.Items:
+ if item[self.FactorIndex] == 1:
result.append(
"{0}[*],$2 $1 -c \"{1}\"".format(self.key.format("." + item[1]), self.query.format(item[0])))
else:
diff --git a/mamonsu/plugins/pgsql/instance.py b/mamonsu/plugins/pgsql/instance.py
index c0a3a9c..b7aa74c 100644
--- a/mamonsu/plugins/pgsql/instance.py
+++ b/mamonsu/plugins/pgsql/instance.py
@@ -68,6 +68,17 @@ class Instance(Plugin):
("PostgreSQL Instance: Events", "006AAE", 0),
Plugin.UNITS.none, Plugin.DELTA.simple_change)
]
+ Items_pg_18 = [
+ # key, zbx_key, description,
+ # ('graph name', color, side), units, delta
+ ("parallel_workers_to_launch", "parallel[instance_to_launch]", "",
+ ("PostgreSQL Instance: Parallel Workers To Launch", "00CC00", 0),
+ Plugin.UNITS.none, Plugin.DELTA.simple_change),
+
+ ("parallel_workers_launched", "parallel[instance_launched]", "",
+ ("PostgreSQL Instance: Parallel Workers Launched", "00CC00", 0),
+ Plugin.UNITS.none, Plugin.DELTA.simple_change)
+ ]
key_server_mode = "pgsql.server_mode{0}"
query_server_mode = """
@@ -86,8 +97,9 @@ class Instance(Plugin):
def run(self, zbx):
all_items = self.Items
if Pooler.server_version_greater("12.0"):
- all_items = self.Items + self.Items_pg_12
-
+ all_items += self.Items_pg_12
+ if Pooler.server_version_greater("18.0"):
+ all_items += self.Items_pg_18
columns = ["sum(COALESCE({0}, 0)) as {0}".format(x[0]) for x in all_items]
result = Pooler.query("""
SELECT {0}
@@ -102,7 +114,7 @@ def run(self, zbx):
def items(self, template, dashboard=False):
result = ""
- for num, item in enumerate(self.Items + self.Items_pg_12):
+ for num, item in enumerate(self.Items + self.Items_pg_12 + self.Items_pg_18):
if self.Type == "mamonsu":
delta = Plugin.DELTA.as_is
else:
@@ -154,7 +166,7 @@ def graphs(self, template, dashboard=False):
result = ""
for name in self.graphs_name.values():
items = []
- for num, item in enumerate(self.Items + self.Items_pg_12):
+ for num, item in enumerate(self.Items + self.Items_pg_12 + self.Items_pg_18):
if item[3][0] == name:
# split each item to get values for keys of both agent type and mamonsu type
keys = item[1].split("[")
@@ -201,10 +213,11 @@ def triggers(self, template, dashboard=False):
def keys_and_queries(self, template_zabbix):
result = []
- if Pooler.server_version_less("11"):
- all_items = self.Items
- else:
- all_items = self.Items + self.Items_pg_12
+ all_items = self.Items
+ if Pooler.server_version_greater("12.0"):
+ all_items += self.Items_pg_12
+ if Pooler.server_version_greater("18.0"):
+ all_items += self.Items_pg_18
for item in all_items:
# split each item to get values for keys of both agent type and mamonsu type
keys = item[1].split("[")
diff --git a/mamonsu/plugins/pgsql/statements.py b/mamonsu/plugins/pgsql/statements.py
index bab41ea..23783dd 100644
--- a/mamonsu/plugins/pgsql/statements.py
+++ b/mamonsu/plugins/pgsql/statements.py
@@ -88,6 +88,29 @@ class Statements(Plugin):
("PostgreSQL Statements Info: Last Statistics Reset Time", "9C8A4E", 0))
]
+ Items_pg_18 = [
+ ("parallel[statements_to_launch]",
+ "sum(parallel_workers_to_launch)",
+ "Number of parallel workers planned to be launched",
+ Plugin.UNITS.none,
+ Plugin.DELTA.simple_change,
+ ("PostgreSQL Statements: Parallel Workers To Launch", "87C2B9", 0)),
+
+ ("parallel[statements_launched]",
+ "sum(parallel_workers_launched)",
+ "Number of parallel workers actually launched",
+ Plugin.UNITS.none,
+ Plugin.DELTA.simple_change,
+ ("PostgreSQL Statements: Parallel Workers Launched", "793F5D", 0)),
+
+ ("stat[wal_buffers_full]",
+ "sum(wal_buffers_full)",
+ "Number of times the WAL buffers became full",
+ Plugin.UNITS.none,
+ Plugin.DELTA.simple_change,
+ ("PostgreSQL Statements: WAL Buffers Full", "9C8A4E", 0)),
+ ]
+
Items_pgpro_stats_1_8 = [
("stat[read_bytes]",
"(sum(shared_blks_read+local_blks_read+temp_blks_read)*8*1024)::bigint",
@@ -168,6 +191,8 @@ def run(self, zbx):
self.Items[3][1] = self.Items[3][1].format("blk_read_time")
self.Items[4][1] = self.Items[4][1].format("blk_write_time")
self.Items[5][1] = self.Items[5][1].format("total_exec_time+total_plan_time", "blk_read_time-blk_write_time")
+ if Pooler.server_version_greater("18"):
+ all_items += self.Items_pg_18
all_items += self.Items_pg_13
info_view = 'pgpro_stats_info'
if self.extension == "pg_stat_statements":
@@ -210,7 +235,7 @@ def items(self, template, dashboard=False):
delta = Plugin.DELTA.as_is
else:
delta = Plugin.DELTA.speed_per_second
- for item in self.Items + self.Items_pg_13 + self.Items_pg_14:
+ for item in self.Items + self.Items_pg_13 + self.Items_pg_14 + self.Items_pg_18:
# split each item to get values for keys of both agent type and mamonsu type
keys = item[0].split("[")
result += template.item({
@@ -229,7 +254,7 @@ def graphs(self, template, dashboard=False):
result = ""
for graph_item in self.all_graphs:
items = []
- for item in self.Items + self.Items_pg_13:
+ for item in self.Items + self.Items_pg_13 + self.Items_pg_18:
if item[5][0] == graph_item[0]:
keys = item[0].split("[")
items.append({
@@ -271,6 +296,8 @@ def keys_and_queries(self, template_zabbix):
self.Items[5][1] = self.Items[5][1].format("total_exec_time+total_plan_time")
if Pooler.is_pgpro() or Pooler.is_pgpro_ee():
all_items += self.Items_pg_13
+ if Pooler.server_version_greater("18"):
+ all_items += self.Items_pg_18
columns = [x[1] for x in all_items]
@@ -287,6 +314,7 @@ def keys_and_queries(self, template_zabbix):
extension_schema=extension_schema),
i + 1))
+ # Info view
if Pooler.server_version_greater("14"):
info_view = 'pgpro_stats_info'
if self.extension == "pg_stat_statements":