From e2500f1c610d2f73b53e353b98856a90db4cc452 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Thu, 18 Sep 2025 15:55:01 +0530 Subject: [PATCH 2/2] Address review comments Among others rename total_txns and total_bytes to total_wal_txns and total_wal_bytes respectively. Reviewed-by: Bertrand Drouvot Reviewed-by: Shveta Malik --- contrib/test_decoding/expected/stats.out | 58 +++++++++++------------ contrib/test_decoding/sql/stats.sql | 17 +++---- contrib/test_decoding/t/001_repl_stats.pl | 6 +-- doc/src/sgml/logicaldecoding.sgml | 6 +-- doc/src/sgml/monitoring.sgml | 18 +++---- src/backend/catalog/system_views.sql | 4 +- src/backend/utils/adt/pgstatfuncs.c | 4 +- src/include/catalog/pg_proc.dat | 2 +- src/test/regress/expected/rules.out | 6 +-- 9 files changed, 61 insertions(+), 60 deletions(-) diff --git a/contrib/test_decoding/expected/stats.out b/contrib/test_decoding/expected/stats.out index d19fe6a1c61..4834b3460a6 100644 --- a/contrib/test_decoding/expected/stats.out +++ b/contrib/test_decoding/expected/stats.out @@ -37,17 +37,17 @@ SELECT pg_stat_force_next_flush(); (1 row) --- total_txns may vary based on the background activity but sent_txns should --- always be 1 since the background transactions are always skipped. Filtered --- bytes would be set only when there's a change that was passed to the plugin --- but was filtered out. Depending upon the background transactions, filtered --- bytes may or may not be zero. -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; - slot_name | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | sent_bytes | filtered_bytes -------------------------+------------+-------------+------------+-------------+------------------+------------+---------------- - regression_slot_stats1 | t | t | t | t | 1 | t | t - regression_slot_stats2 | t | t | t | t | 1 | t | t - regression_slot_stats3 | t | t | t | t | 1 | t | t +-- total_wal_txns may vary based on the background activity but plugin_sent_txns +-- should always be 1 since the background transactions are always skipped. +-- Filtered bytes would be set only when there's a change that was passed to the +-- plugin but was filtered out. Depending upon the background transactions, +-- filtered bytes may or may not be zero. +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; + slot_name | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | sent_bytes | filtered_bytes +------------------------+------------+-------------+----------------+-----------------+------------------+------------+---------------- + regression_slot_stats1 | t | t | t | t | 1 | t | t + regression_slot_stats2 | t | t | t | t | 1 | t | t + regression_slot_stats3 | t | t | t | t | 1 | t | t (3 rows) RESET logical_decoding_work_mem; @@ -58,12 +58,12 @@ SELECT pg_stat_reset_replication_slot('regression_slot_stats1'); (1 row) -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; - slot_name | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | sent_bytes | filtered_bytes -------------------------+------------+-------------+------------+-------------+------------------+------------+---------------- - regression_slot_stats1 | t | t | f | f | | | - regression_slot_stats2 | t | t | t | t | 1 | t | t - regression_slot_stats3 | t | t | t | t | 1 | t | t +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; + slot_name | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | sent_bytes | filtered_bytes +------------------------+------------+-------------+----------------+-----------------+------------------+------------+---------------- + regression_slot_stats1 | t | t | f | f | | | + regression_slot_stats2 | t | t | t | t | 1 | t | t + regression_slot_stats3 | t | t | t | t | 1 | t | t (3 rows) -- reset stats for all slots @@ -73,27 +73,27 @@ SELECT pg_stat_reset_replication_slot(NULL); (1 row) -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; - slot_name | spill_txns | spill_count | total_txns | total_bytes | plugin_sent_txns | plugin_sent_bytes | plugin_filtered_bytes -------------------------+------------+-------------+------------+-------------+------------------+-------------------+----------------------- - regression_slot_stats1 | t | t | f | f | | | - regression_slot_stats2 | t | t | f | f | | | - regression_slot_stats3 | t | t | f | f | | | +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; + slot_name | spill_txns | spill_count | total_wal_txns | total_wal_bytes | plugin_sent_txns | plugin_sent_bytes | plugin_filtered_bytes +------------------------+------------+-------------+----------------+-----------------+------------------+-------------------+----------------------- + regression_slot_stats1 | t | t | f | f | | | + regression_slot_stats2 | t | t | f | f | | | + regression_slot_stats3 | t | t | f | f | | | (3 rows) -- verify accessing/resetting stats for non-existent slot does something reasonable SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); - slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_txns | total_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset ---------------+------------+-------------+-------------+-------------+--------------+--------------+------------+-------------+-----------------------+------------------+-------------------+------------- - do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | + slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_wal_txns | total_wal_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset +--------------+------------+-------------+-------------+-------------+--------------+--------------+----------------+-----------------+-----------------------+------------------+-------------------+------------- + do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | (1 row) SELECT pg_stat_reset_replication_slot('do-not-exist'); ERROR: replication slot "do-not-exist" does not exist SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); - slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_txns | total_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset ---------------+------------+-------------+-------------+-------------+--------------+--------------+------------+-------------+-----------------------+------------------+-------------------+------------- - do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | + slot_name | spill_txns | spill_count | spill_bytes | stream_txns | stream_count | stream_bytes | total_wal_txns | total_wal_bytes | plugin_filtered_bytes | plugin_sent_txns | plugin_sent_bytes | stats_reset +--------------+------------+-------------+-------------+-------------+--------------+--------------+----------------+-----------------+-----------------------+------------------+-------------------+------------- + do-not-exist | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | | | (1 row) -- spilling the xact diff --git a/contrib/test_decoding/sql/stats.sql b/contrib/test_decoding/sql/stats.sql index 1077cea5855..99f513902d3 100644 --- a/contrib/test_decoding/sql/stats.sql +++ b/contrib/test_decoding/sql/stats.sql @@ -15,21 +15,22 @@ SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats1', NULL, SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats2', NULL, NULL, 'skip-empty-xacts', '1'); SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot_stats3', NULL, NULL, 'skip-empty-xacts', '1'); SELECT pg_stat_force_next_flush(); --- total_txns may vary based on the background activity but sent_txns should --- always be 1 since the background transactions are always skipped. Filtered --- bytes would be set only when there's a change that was passed to the plugin --- but was filtered out. Depending upon the background transactions, filtered --- bytes may or may not be zero. -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; + +-- total_wal_txns may vary based on the background activity but plugin_sent_txns +-- should always be 1 since the background transactions are always skipped. +-- Filtered bytes would be set only when there's a change that was passed to the +-- plugin but was filtered out. Depending upon the background transactions, +-- filtered bytes may or may not be zero. +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; RESET logical_decoding_work_mem; -- reset stats for one slot, others should be unaffected SELECT pg_stat_reset_replication_slot('regression_slot_stats1'); -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; -- reset stats for all slots SELECT pg_stat_reset_replication_slot(NULL); -SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_txns > 0 AS total_txns, total_bytes > 0 AS total_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; +SELECT slot_name, spill_txns = 0 AS spill_txns, spill_count = 0 AS spill_count, total_wal_txns > 0 AS total_wal_txns, total_wal_bytes > 0 AS total_wal_bytes, plugin_sent_txns, plugin_sent_bytes, plugin_filtered_bytes FROM pg_stat_replication_slots ORDER BY slot_name; -- verify accessing/resetting stats for non-existent slot does something reasonable SELECT * FROM pg_stat_get_replication_slot('do-not-exist'); diff --git a/contrib/test_decoding/t/001_repl_stats.pl b/contrib/test_decoding/t/001_repl_stats.pl index 76dd86fc420..756fc691ed6 100644 --- a/contrib/test_decoding/t/001_repl_stats.pl +++ b/contrib/test_decoding/t/001_repl_stats.pl @@ -28,8 +28,8 @@ sub test_slot_stats # guaranteed that such transactions would be present. my $result = $node->safe_psql( 'postgres', qq[ - SELECT slot_name, total_txns > 0 AS total_txn, - total_bytes > 0 AS total_bytes, + SELECT slot_name, total_wal_txns > 0 AS total_txn, + total_wal_bytes > 0 AS total_bytes, plugin_sent_txns > 0 AS sent_txn, plugin_sent_bytes > 0 AS sent_bytes, plugin_filtered_bytes >= 0 AS filtered_bytes @@ -71,7 +71,7 @@ $node->poll_query_until( 'postgres', qq[ SELECT count(slot_name) >= 4 FROM pg_stat_replication_slots WHERE slot_name ~ 'regression_slot' - AND total_txns > 0 AND total_bytes > 0; + AND total_wal_txns > 0 AND total_wal_bytes > 0; ]) or die "Timed out while waiting for statistics to be updated"; # Test to drop one of the replication slot and verify replication statistics data is diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml index 8ac10cda90c..3952f68e806 100644 --- a/doc/src/sgml/logicaldecoding.sgml +++ b/doc/src/sgml/logicaldecoding.sgml @@ -956,11 +956,11 @@ typedef struct OutputPluginStats } OutputPluginStats; sentTxns is the number of transactions sent downstream - by the output plugin. sentBytes is the amount of data + by the output plugin. sentBytes is the amount of data, in bytes, sent downstream by the output plugin. - OutputPluginWrite is expected to update this counter + OutputPluginWrite will update this counter if ctx->stats is initialized by the output plugin. - filteredBytes is the size of changes in bytes that are + filteredBytes is the size of changes, in bytes, that are filtered out by the output plugin. Function ReorderBufferChangeSize may be used to find the size of filtered ReorderBufferChange. diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index e121f55c9c2..fbe03ffd670 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1633,19 +1633,19 @@ description | Waiting for a newly initialized WAL file to reach durable storage - total_txns bigint + total_wal_txns bigint - Number of decoded transactions sent to the decoding output plugin for - this slot. This counts top-level transactions only, and is not incremented - for subtransactions. Note that this includes the transactions that are - streamed and/or spilled. + Number of decoded transactions from WAL sent to the decoding output + plugin for this slot. This counts top-level transactions only, and is + not incremented for subtransactions. Note that this includes the + transactions that are streamed and/or spilled. - total_bytesbigint + total_wal_bytesbigint Amount of transaction data decoded for sending transactions to the @@ -1660,9 +1660,9 @@ description | Waiting for a newly initialized WAL file to reach durable storage plugin_filtered_bytes bigint - Amount of changes, from total_bytes, filtered + Amount of changes, from total_wal_bytes, filtered out by the output plugin and not sent downstream. Please note that it - does not include the changes filtered before a change is handed over to + does not include the changes filtered before a change is sent to the output plugin, e.g. the changes filtered by origin. The count is maintained by the output plugin mentioned in plugin. It is NULL when statistics is not @@ -1680,7 +1680,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage counts top-level transactions only, and is not incremented for subtransactions. These transactions are subset of transctions sent to the decoding plugin. Hence this count is expected to be lesser than or - equal to total_txns. The count is maintained + equal to total_wal_txns. The count is maintained by the output plugin mentioned in plugin. It is NULL when statistics is not initialized or immediately after a reset or when not maintained by the output plugin. diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index d38c21150b0..9e8e32b5849 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -1060,8 +1060,8 @@ CREATE VIEW pg_stat_replication_slots AS s.stream_txns, s.stream_count, s.stream_bytes, - s.total_txns, - s.total_bytes, + s.total_wal_txns, + s.total_wal_bytes, s.plugin_filtered_bytes, s.plugin_sent_txns, s.plugin_sent_bytes, diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 796dacddcfb..15bafe63b24 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -2125,9 +2125,9 @@ pg_stat_get_replication_slot(PG_FUNCTION_ARGS) INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stream_bytes", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_txns", + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_wal_txns", INT8OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_bytes", + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_wal_bytes", INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 10, "plugin_filtered_bytes", INT8OID, -1, 0); diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 7519941bcf3..9e4f6620214 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -5689,7 +5689,7 @@ proparallel => 'r', prorettype => 'record', proargtypes => 'text', proallargtypes => '{text,text,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,int8,timestamptz}', proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o}', - proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,total_txns,total_bytes,plugin_filtered_bytes,plugin_sent_txns,plugin_sent_bytes,stats_reset}', + proargnames => '{slot_name,slot_name,spill_txns,spill_count,spill_bytes,stream_txns,stream_count,stream_bytes,total_wal_txns,total_wal_bytes,plugin_filtered_bytes,plugin_sent_txns,plugin_sent_bytes,stats_reset}', prosrc => 'pg_stat_get_replication_slot' }, { oid => '6230', descr => 'statistics: check if a stats object exists', diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 2a048af3569..2a401552a7a 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -2139,14 +2139,14 @@ pg_stat_replication_slots| SELECT s.slot_name, s.stream_txns, s.stream_count, s.stream_bytes, - s.total_txns, - s.total_bytes, + s.total_wal_txns, + s.total_wal_bytes, s.plugin_filtered_bytes, s.plugin_sent_txns, s.plugin_sent_bytes, s.stats_reset FROM pg_replication_slots r, - LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, total_txns, total_bytes, plugin_filtered_bytes, plugin_sent_txns, plugin_sent_bytes, stats_reset) + LATERAL pg_stat_get_replication_slot((r.slot_name)::text) s(slot_name, spill_txns, spill_count, spill_bytes, stream_txns, stream_count, stream_bytes, total_wal_txns, total_wal_bytes, plugin_filtered_bytes, plugin_sent_txns, plugin_sent_bytes, stats_reset) WHERE (r.datoid IS NOT NULL); pg_stat_slru| SELECT name, blks_zeroed, -- 2.34.1