]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add system view pg_stat_kind_info
authorMichael Paquier <michael@paquier.xyz>
Thu, 2 Jul 2026 00:34:21 +0000 (09:34 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 2 Jul 2026 00:34:21 +0000 (09:34 +0900)
This commit adds support for pg_stat_kind_info, that exposes at SQL
level data about the statistics kinds registered into a backend:
- Meta-data of a stats kind (built-in or custom, some properties).
- Number of entries, if tracking is enabled.

We have discussed the possibility of more fields (like shared memory
size for a single entry); this adds the minimum agreed on.

This is in spirit similar to pg_get_loaded_modules() for custom stats
kinds, this view providing detailed information about the stats kinds
when registered through shared_preload_libraries.

Bump catalog version.

Author: Tristan Partin <tristan@partin.io>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/DI6OFGHJ1B69.25YVDEP3BABRH@partin.io

doc/src/sgml/monitoring.sgml
src/backend/catalog/system_views.sql
src/backend/utils/activity/Makefile
src/backend/utils/activity/meson.build
src/backend/utils/activity/pgstat_kind.c [new file with mode: 0644]
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/test/modules/test_custom_stats/t/001_custom_stats.pl
src/test/regress/expected/rules.out
src/test/regress/expected/stats.out
src/test/regress/sql/stats.sql

index 937d6ce1b573dc59fc643f68d63873115db4941d..12b9ee20d4a89c647bbb79139196860e24cc9597 100644 (file)
@@ -509,6 +509,16 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
      </entry>
      </row>
 
+     <row>
+      <entry><structname>pg_stat_kind_info</structname><indexterm><primary>pg_stat_kind_info</primary></indexterm></entry>
+      <entry>
+       One row for each registered statistics kind, showing information
+       about each kind.
+       See <link linkend="monitoring-pg-stat-kind-info-view">
+       <structname>pg_stat_kind_info</structname></link> for details.
+      </entry>
+     </row>
+
      <row>
       <entry><structname>pg_stat_lock</structname><indexterm><primary>pg_stat_lock</primary></indexterm></entry>
       <entry>
@@ -3303,6 +3313,124 @@ description | Waiting for a newly initialized WAL file to reach durable storage
  </sect2>
 
 
+ <sect2 id="monitoring-pg-stat-kind-info-view">
+  <title><structname>pg_stat_kind_info</structname></title>
+
+  <indexterm>
+   <primary>pg_stat_kind_info</primary>
+  </indexterm>
+
+  <para>
+   The <structname>pg_stat_kind_info</structname> view contains one row for
+   each registered statistics kind, including both built-in and custom kinds.
+  </para>
+
+  <table id="pg-stat-kind-info-view" xreflabel="pg_stat_kind_info">
+   <title><structname>pg_stat_kind_info</structname> View</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        Column Type
+       </para>
+       <para>
+        Description
+       </para>
+      </entry>
+     </row>
+    </thead>
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>id</structfield> <type>integer</type>
+       </para>
+       <para>
+        Numeric identifier of the statistics kind.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>name</structfield> <type>text</type>
+       </para>
+       <para>
+        Name of the statistics kind.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>builtin</structfield> <type>boolean</type>
+       </para>
+       <para>
+        True if this is a built-in statistics kind, false if it was registered
+        by an extension.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>fixed_amount</structfield> <type>boolean</type>
+       </para>
+       <para>
+        True if this kind tracks a fixed amount of data (a single, statically
+        allocated entry), false if it tracks a variable number of entries
+        keyed by object identifier.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>accessed_across_databases</structfield> <type>boolean</type>
+       </para>
+       <para>
+        True if entries of this kind are accessed across databases (cluster-wide
+        statistics), false if they are scoped to a single database.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>write_to_file</structfield> <type>boolean</type>
+       </para>
+       <para>
+        True if entries of this kind are persisted to the statistics file at
+        shutdown and reloaded on startup, false if they are kept only in
+        shared memory.
+       </para>
+      </entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry">
+       <para role="column_definition">
+        <structfield>entry_count</structfield> <type>bigint</type>
+       </para>
+       <para>
+        Number of tracked entries for this kind. For variable-numbered kinds,
+        this is the number of objects currently tracked.
+        <literal>NULL</literal> for fixed-sized statistics kinds, or if the
+        kind does not track entry counts.
+       </para>
+      </entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </sect2>
+
  <sect2 id="monitoring-pg-stat-lock-view">
   <title><structname>pg_stat_lock</structname></title>
 
index 8f129baec906196a04b81b37fdab57b87ff0310c..d10b50f00979082214e0c884ea90f70721a47189 100644 (file)
@@ -1282,6 +1282,17 @@ SELECT
        b.stats_reset
 FROM pg_stat_get_io() b;
 
+CREATE VIEW pg_stat_kind_info AS
+    SELECT
+        k.id,
+        k.name,
+        k.builtin,
+        k.fixed_amount,
+        k.accessed_across_databases,
+        k.write_to_file,
+        k.entry_count
+    FROM pg_stat_get_kind_info() k;
+
 CREATE VIEW pg_stat_wal AS
     SELECT
         w.wal_records,
index ca3ef89bf5997e5a7a1165384ef8f1e0d5bef4e8..5fed953c28a7f1e730901b2cc19d9f3c0bea93ab 100644 (file)
@@ -26,6 +26,7 @@ OBJS = \
        pgstat_database.o \
        pgstat_function.o \
        pgstat_io.o \
+       pgstat_kind.o \
        pgstat_lock.o \
        pgstat_relation.o \
        pgstat_replslot.o \
index 1aa7ece52908cb22acc53ed6ef0502bfb997b230..470b5dac402bd37fd03b7e995711a34726f68126 100644 (file)
@@ -11,6 +11,7 @@ backend_sources += files(
   'pgstat_database.c',
   'pgstat_function.c',
   'pgstat_io.c',
+  'pgstat_kind.c',
   'pgstat_lock.c',
   'pgstat_relation.c',
   'pgstat_replslot.c',
diff --git a/src/backend/utils/activity/pgstat_kind.c b/src/backend/utils/activity/pgstat_kind.c
new file mode 100644 (file)
index 0000000..6c53b7e
--- /dev/null
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgstat_kind.c
+ *       Functions related to statistics kinds.
+ *
+ * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       src/backend/utils/activity/pgstat_kind.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "funcapi.h"
+#include "utils/builtins.h"
+#include "utils/fmgrprotos.h"
+#include "utils/pgstat_internal.h"
+#include "utils/pgstat_kind.h"
+#include "utils/tuplestore.h"
+
+
+/*
+ * pg_stat_get_kind_info
+ *
+ * Get information about the statistics kinds registered into the system.
+ */
+Datum
+pg_stat_get_kind_info(PG_FUNCTION_ARGS)
+{
+#define PG_STAT_KIND_INFO_COLS 7
+       ReturnSetInfo *rsinfo;
+
+       InitMaterializedSRF(fcinfo, 0);
+       rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+       for (int kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
+       {
+               Datum           values[PG_STAT_KIND_INFO_COLS] = {0};
+               bool            nulls[PG_STAT_KIND_INFO_COLS] = {0};
+               const PgStat_KindInfo *info;
+
+               info = pgstat_get_kind_info(kind);
+               if (info == NULL)
+                       continue;
+
+               values[0] = Int32GetDatum(kind);
+               values[1] = CStringGetTextDatum(info->name);
+
+               values[2] = BoolGetDatum(pgstat_is_kind_builtin(kind));
+               values[3] = BoolGetDatum(info->fixed_amount);
+               values[4] = BoolGetDatum(info->accessed_across_databases);
+               values[5] = BoolGetDatum(info->write_to_file);
+
+               /*
+                * When track_entry_count is disabled, use NULL.  Fixed-sized stats
+                * kinds report NULL here.
+                */
+               if (info->track_entry_count)
+                       values[6] = Int64GetDatum(pgstat_get_entry_count(kind));
+               else
+                       nulls[6] = true;
+
+               tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+       }
+
+       return (Datum) 0;
+#undef PG_STAT_KIND_INFO_COLS
+}
index 227d85762a1ed42c5477da68a125eb9d4519c5a2..fa8507761aea15fed50915e61b28567680b9efad 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202607011
+#define CATALOG_VERSION_NO     202607021
 
 #endif
index 9e24b2f6299d3de60079632fe9bd2de3e02a6148..3cb84359adf06dac52537d6a087fd5bb4c9af3c5 100644 (file)
   proargnames => '{backend_pid,backend_type,object,context,reads,read_bytes,read_time,writes,write_bytes,write_time,writebacks,writeback_time,extends,extend_bytes,extend_time,hits,evictions,reuses,fsyncs,fsync_time,stats_reset}',
   prosrc => 'pg_stat_get_backend_io' },
 
+{ oid => '8683', descr => 'statistics: information about statistics kinds',
+  proname => 'pg_stat_get_kind_info', prorows => '20', proretset => 't',
+  provolatile => 'v', proparallel => 'r', prorettype => 'record',
+  proargtypes => '', proallargtypes => '{int4,text,bool,bool,bool,bool,int8}',
+  proargmodes => '{o,o,o,o,o,o,o}',
+  proargnames => '{id,name,builtin,fixed_amount,accessed_across_databases,write_to_file,entry_count}',
+  prosrc => 'pg_stat_get_kind_info' },
+
 { oid => '1136', descr => 'statistics: information about WAL activity',
   proname => 'pg_stat_get_wal', proisstrict => 'f', provolatile => 's',
   proparallel => 'r', prorettype => 'record', proargtypes => '',
index 9e6a7a3857752238ff2f08d3519a12ecc37b61b0..69f2284229e1662483074ff3a3d65d68c9f52f99 100644 (file)
@@ -27,6 +27,18 @@ $node->start;
 $node->safe_psql('postgres', q(CREATE EXTENSION test_custom_var_stats));
 $node->safe_psql('postgres', q(CREATE EXTENSION test_custom_fixed_stats));
 
+# Verify custom stats kinds appear in pg_stat_kind_info.
+my $result = $node->safe_psql(
+       'postgres',
+       q(SELECT id, name, builtin, fixed_amount, accessed_across_databases,
+                write_to_file
+           FROM pg_stat_kind_info
+           WHERE name LIKE 'test_custom%' ORDER BY id));
+is( $result,
+       qq{25|test_custom_var_stats|f|f|t|t
+26|test_custom_fixed_stats|f|t|f|t},
+       "custom stats kinds visible in pg_stat_kind_info");
+
 # Create entries for variable-sized stats.
 $node->safe_psql('postgres',
        q(select test_custom_stats_var_create('entry1', 'Test entry 1')));
@@ -63,7 +75,7 @@ $node->safe_psql('postgres', q(select test_custom_stats_fixed_update()));
 $node->safe_psql('postgres', q(select test_custom_stats_fixed_update()));
 
 # Test data reports.
-my $result = $node->safe_psql('postgres',
+$result = $node->safe_psql('postgres',
        q(select * from test_custom_stats_var_report('entry1')));
 is( $result,
        "entry1|2|Test entry 1",
index a65a5bf0c4fbc4970fb741e0239ab1a0e40012c6..e266f501d871da428a23501643f7cd1c8055e807 100644 (file)
@@ -1967,6 +1967,14 @@ pg_stat_io| SELECT backend_type,
     fsync_time,
     stats_reset
    FROM pg_stat_get_io() b(backend_type, object, context, reads, read_bytes, read_time, writes, write_bytes, write_time, writebacks, writeback_time, extends, extend_bytes, extend_time, hits, evictions, reuses, fsyncs, fsync_time, stats_reset);
+pg_stat_kind_info| SELECT id,
+    name,
+    builtin,
+    fixed_amount,
+    accessed_across_databases,
+    write_to_file,
+    entry_count
+   FROM pg_stat_get_kind_info() k(id, name, builtin, fixed_amount, accessed_across_databases, write_to_file, entry_count);
 pg_stat_lock| SELECT locktype,
     waits,
     wait_time,
index fa550676f8355c7c467033dbc7c4b36d83bf2de3..03cbc1cdef59e3fad300ebd925f39fc2aeaa3b2c 100644 (file)
@@ -113,6 +113,29 @@ walwriter|wal|init
 walwriter|wal|normal
 (95 rows)
 \a
+-- List of registered statistics kinds.
+SELECT id, name, fixed_amount,
+    accessed_across_databases AS across_db, write_to_file
+  FROM pg_stat_kind_info
+  WHERE builtin
+  ORDER BY id;
+ id |     name     | fixed_amount | across_db | write_to_file 
+----+--------------+--------------+-----------+---------------
+  1 | database     | f            | t         | t
+  2 | relation     | f            | f         | t
+  3 | function     | f            | f         | t
+  4 | replslot     | f            | t         | t
+  5 | subscription | f            | t         | t
+  6 | backend      | f            | t         | f
+  7 | archiver     | t            | f         | t
+  8 | bgwriter     | t            | f         | t
+  9 | checkpointer | t            | f         | t
+ 10 | io           | t            | f         | t
+ 11 | lock         | t            | f         | t
+ 12 | slru         | t            | f         | t
+ 13 | wal          | t            | f         | t
+(13 rows)
+
 -- ensure that both seqscan and indexscan plans are allowed
 SET enable_seqscan TO on;
 SET enable_indexscan TO on;
index f5683302a75c0ea5f067ebc818cbd1664e13e899..4c265d1245c7284ff29f54148075ac17afd10cc5 100644 (file)
@@ -14,6 +14,13 @@ SELECT backend_type, object, context FROM pg_stat_io
   ORDER BY backend_type COLLATE "C", object COLLATE "C", context COLLATE "C";
 \a
 
+-- List of registered statistics kinds.
+SELECT id, name, fixed_amount,
+    accessed_across_databases AS across_db, write_to_file
+  FROM pg_stat_kind_info
+  WHERE builtin
+  ORDER BY id;
+
 -- ensure that both seqscan and indexscan plans are allowed
 SET enable_seqscan TO on;
 SET enable_indexscan TO on;