From 920ef77125d3b81eb76e43b3ddfc0276155d4ca9 Mon Sep 17 00:00:00 2001
From: Huseyin Demir <huseyin.d3r@gmail.com>
Date: Sat, 16 May 2026 19:19:36 +0200
Subject: [PATCH] Add WAL segment file counts to pg_stat_checkpointer

Expose cumulative WAL segment file management counters in
pg_stat_checkpointer as segs_added, segs_removed, and segs_recycled.

These counters are accumulated from CheckpointStats in LogCheckpointEnd(),
which is called at the end of both CreateCheckPoint() and
CreateRestartPoint(), so all checkpoint and restartpoint activity is
captured. The values are routed through the pgstat infrastructure, giving
them reset support via pg_stat_reset_shared('checkpointer') and
persistence across postmaster restarts, consistent with the existing
buffers_written and slru_written counters.

When applied on top of the patch that counts WAL segment creations by
all processes (not only the checkpointer), segs_added reflects creation
by any backend or the WAL receiver. On unpatched master it retains the
narrower checkpointer-preallocation semantics.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---
 doc/src/sgml/monitoring.sgml                  | 30 +++++++++++++++++++
 src/backend/access/transam/xlog.c             |  5 ++++
 src/backend/catalog/system_views.sql          |  3 ++
 .../utils/activity/pgstat_checkpointer.c      |  6 ++++
 src/backend/utils/adt/pgstatfuncs.c           | 18 +++++++++++
 src/include/catalog/catversion.h              |  2 +-
 src/include/catalog/pg_proc.dat               | 12 ++++++++
 src/include/pgstat.h                          |  3 ++
 8 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 08d5b824552..0c5f80bda61 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3587,6 +3587,36 @@ description | Waiting for a newly initialized WAL file to reach durable storage
       </para></entry>
      </row>
 
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>segs_added</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of WAL segment files created since the last statistics reset.
+       Includes segments created by any backend process or the WAL receiver,
+       not only those preallocated by the checkpointer.
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>segs_removed</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of WAL segment files deleted since the last statistics reset
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>segs_recycled</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of WAL segment files recycled (renamed for future use) since
+       the last statistics reset
+      </para></entry>
+     </row>
+
      <row>
       <entry role="catalog_table_entry"><para role="column_definition">
        <structfield>stats_reset</structfield> <type>timestamp with time zone</type>
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index d34e34a56c5..06ab3ed92f4 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -7205,6 +7205,11 @@ LogCheckpointEnd(bool restartpoint, int flags)
 	PendingCheckpointerStats.write_time += write_msecs;
 	PendingCheckpointerStats.sync_time += sync_msecs;
 
+	/* Accumulate WAL segment file counts. */
+	PendingCheckpointerStats.segs_added += CheckpointStats.ckpt_segs_added;
+	PendingCheckpointerStats.segs_removed += CheckpointStats.ckpt_segs_removed;
+	PendingCheckpointerStats.segs_recycled += CheckpointStats.ckpt_segs_recycled;
+
 	/*
 	 * All of the published timing statistics are accounted for.  Only
 	 * continue if a log message is to be written.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 73a1c1c4670..f32e74a7169 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1256,6 +1256,9 @@ CREATE VIEW pg_stat_checkpointer AS
         pg_stat_get_checkpointer_sync_time() AS sync_time,
         pg_stat_get_checkpointer_buffers_written() AS buffers_written,
         pg_stat_get_checkpointer_slru_written() AS slru_written,
+        pg_stat_get_checkpointer_segs_added() AS segs_added,
+        pg_stat_get_checkpointer_segs_removed() AS segs_removed,
+        pg_stat_get_checkpointer_segs_recycled() AS segs_recycled,
         pg_stat_get_checkpointer_stat_reset_time() AS stats_reset;
 
 CREATE VIEW pg_stat_io AS
diff --git a/src/backend/utils/activity/pgstat_checkpointer.c b/src/backend/utils/activity/pgstat_checkpointer.c
index 1f70194b7a7..16ba8c4ae39 100644
--- a/src/backend/utils/activity/pgstat_checkpointer.c
+++ b/src/backend/utils/activity/pgstat_checkpointer.c
@@ -56,6 +56,9 @@ pgstat_report_checkpointer(void)
 	CHECKPOINTER_ACC(sync_time);
 	CHECKPOINTER_ACC(buffers_written);
 	CHECKPOINTER_ACC(slru_written);
+	CHECKPOINTER_ACC(segs_added);
+	CHECKPOINTER_ACC(segs_removed);
+	CHECKPOINTER_ACC(segs_recycled);
 #undef CHECKPOINTER_ACC
 
 	pgstat_end_changecount_write(&stats_shmem->changecount);
@@ -136,5 +139,8 @@ pgstat_checkpointer_snapshot_cb(void)
 	CHECKPOINTER_COMP(sync_time);
 	CHECKPOINTER_COMP(buffers_written);
 	CHECKPOINTER_COMP(slru_written);
+	CHECKPOINTER_COMP(segs_added);
+	CHECKPOINTER_COMP(segs_removed);
+	CHECKPOINTER_COMP(segs_recycled);
 #undef CHECKPOINTER_COMP
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6f9c9c72de5..d71fb8baef3 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1290,6 +1290,24 @@ pg_stat_get_checkpointer_slru_written(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->slru_written);
 }
 
+Datum
+pg_stat_get_checkpointer_segs_added(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->segs_added);
+}
+
+Datum
+pg_stat_get_checkpointer_segs_removed(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->segs_removed);
+}
+
+Datum
+pg_stat_get_checkpointer_segs_recycled(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->segs_recycled);
+}
+
 Datum
 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
 {
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index a1416260abc..234142d0e3d 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202605131
+#define CATALOG_VERSION_NO	202605161
 
 #endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index be157a5fbe9..4edd2531d28 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6020,6 +6020,18 @@
   proname => 'pg_stat_get_checkpointer_slru_written', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => '',
   prosrc => 'pg_stat_get_checkpointer_slru_written' },
+{ oid => '6015', descr => 'statistics: WAL segment files added since last reset',
+  proname => 'pg_stat_get_checkpointer_segs_added', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => '',
+  prosrc => 'pg_stat_get_checkpointer_segs_added' },
+{ oid => '6016', descr => 'statistics: WAL segment files removed since last reset',
+  proname => 'pg_stat_get_checkpointer_segs_removed', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => '',
+  prosrc => 'pg_stat_get_checkpointer_segs_removed' },
+{ oid => '6017', descr => 'statistics: WAL segment files recycled since last reset',
+  proname => 'pg_stat_get_checkpointer_segs_recycled', provolatile => 's',
+  proparallel => 'r', prorettype => 'int8', proargtypes => '',
+  prosrc => 'pg_stat_get_checkpointer_segs_recycled' },
 { oid => '6314', descr => 'statistics: last reset for the checkpointer',
   proname => 'pg_stat_get_checkpointer_stat_reset_time', provolatile => 's',
   proparallel => 'r', prorettype => 'timestamptz', proargtypes => '',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index dfa2e837638..73226bdad07 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -269,6 +269,9 @@ typedef struct PgStat_CheckpointerStats
 	PgStat_Counter sync_time;
 	PgStat_Counter buffers_written;
 	PgStat_Counter slru_written;
+	PgStat_Counter segs_added;		/* WAL segments created since last reset */
+	PgStat_Counter segs_removed;	/* WAL segments deleted since last reset */
+	PgStat_Counter segs_recycled;	/* WAL segments recycled since last reset */
 	TimestampTz stat_reset_timestamp;
 } PgStat_CheckpointerStats;
 
-- 
2.50.1 (Apple Git-155)

