diff --git a/pg_stat_monitor--2.2--2.3.sql b/pg_stat_monitor--2.2--2.3.sql index 7172eb6..1647b27 100644 --- a/pg_stat_monitor--2.2--2.3.sql +++ b/pg_stat_monitor--2.2--2.3.sql @@ -5,12 +5,193 @@ DROP FUNCTION pgsm_create_11_view(); DROP VIEW pg_stat_monitor; +DROP FUNCTION pg_stat_monitor_internal; + +CREATE FUNCTION pg_stat_monitor_internal( + IN showtext boolean, + OUT bucket int8, -- 0 + OUT userid oid, + OUT username text, + OUT dbid oid, + OUT datname text, + OUT client_ip int8, + + OUT queryid int8, -- 6 + OUT planid int8, + OUT query text, + OUT query_plan text, + OUT pgsm_query_id int8, + OUT top_queryid int8, + OUT top_query text, + OUT application_name text, + + OUT relations text, -- 14 + OUT cmd_type int, + OUT elevel int, + OUT sqlcode TEXT, + OUT message text, + OUT bucket_start_time timestamptz, + + OUT calls int8, -- 20 + + OUT total_exec_time float8, -- 21 + OUT min_exec_time float8, + OUT max_exec_time float8, + OUT mean_exec_time float8, + OUT stddev_exec_time float8, + + OUT rows int8, -- 26 + + OUT plans int8, -- 27 + + OUT total_plan_time float8, -- 28 + OUT min_plan_time float8, + OUT max_plan_time float8, + OUT mean_plan_time float8, + OUT stddev_plan_time float8, + + OUT shared_blks_hit int8, -- 33 + OUT shared_blks_read int8, + OUT shared_blks_dirtied int8, + OUT shared_blks_written int8, + OUT local_blks_hit int8, + OUT local_blks_read int8, + OUT local_blks_dirtied int8, + OUT local_blks_written int8, + OUT temp_blks_read int8, + OUT temp_blks_written int8, + OUT shared_blk_read_time float8, + OUT shared_blk_write_time float8, + OUT local_blk_read_time float8, + OUT local_blk_write_time float8, + OUT temp_blk_read_time float8, + OUT temp_blk_write_time float8, + + OUT resp_calls text, -- 49 + OUT cpu_user_time float8, + OUT cpu_sys_time float8, + OUT wal_records int8, + OUT wal_fpi int8, + OUT wal_bytes numeric, + OUT wal_buffers_full int8, + OUT comments TEXT, + + OUT jit_functions int8, -- 57 + OUT jit_generation_time float8, + OUT jit_inlining_count int8, + OUT jit_inlining_time float8, + OUT jit_optimization_count int8, + OUT jit_optimization_time float8, + OUT jit_emission_count int8, + OUT jit_emission_time float8, + OUT jit_deform_count int8, + OUT jit_deform_time float8, + + OUT stats_since timestamp with time zone, -- 67 + OUT minmax_stats_since timestamp with time zone, + + OUT toplevel BOOLEAN, -- 69 + OUT bucket_done BOOLEAN +) +RETURNS SETOF record +AS 'MODULE_PATHNAME', 'pg_stat_monitor_2_3' +LANGUAGE C STRICT VOLATILE PARALLEL SAFE; + +CREATE FUNCTION pgsm_create_18_view() RETURNS INT AS +$$ +BEGIN +CREATE VIEW pg_stat_monitor AS SELECT + bucket, + bucket_start_time, + userid, + username, + dbid, + datname, + '0.0.0.0'::inet + client_ip AS client_ip, + pgsm_query_id, + queryid, + toplevel, + top_queryid, + query, + comments, + planid, + query_plan, + top_query, + application_name, + string_to_array(relations, ',') AS relations, + cmd_type, + get_cmd_type(cmd_type) AS cmd_type_text, + elevel, + sqlcode, + message, + calls, + total_exec_time, + min_exec_time, + max_exec_time, + mean_exec_time, + stddev_exec_time, + rows, + shared_blks_hit, + shared_blks_read, + shared_blks_dirtied, + shared_blks_written, + local_blks_hit, + local_blks_read, + local_blks_dirtied, + local_blks_written, + temp_blks_read, + temp_blks_written, + shared_blk_read_time, + shared_blk_write_time, + local_blk_read_time, + local_blk_write_time, + temp_blk_read_time, + temp_blk_write_time, + + (string_to_array(resp_calls, ',')) resp_calls, + cpu_user_time, + cpu_sys_time, + wal_records, + wal_fpi, + wal_bytes, + wal_buffers_full, + bucket_done, + + plans, + total_plan_time, + min_plan_time, + max_plan_time, + mean_plan_time, + stddev_plan_time, + + jit_functions, + jit_generation_time, + jit_inlining_count, + jit_inlining_time, + jit_optimization_count, + jit_optimization_time, + jit_emission_count, + jit_emission_time, + jit_deform_count, + jit_deform_time, + + stats_since, + minmax_stats_since + +FROM pg_stat_monitor_internal(TRUE) +ORDER BY bucket_start_time; +RETURN 0; +END; +$$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION pgsm_create_view() RETURNS INT AS $$ DECLARE ver integer; BEGIN SELECT current_setting('server_version_num') INTO ver; + IF (ver >= 180000) THEN + return pgsm_create_18_view(); + END IF; IF (ver >= 170000) THEN return pgsm_create_17_view(); END IF; @@ -29,5 +210,6 @@ $$ LANGUAGE plpgsql; SELECT pgsm_create_view(); REVOKE ALL ON FUNCTION pgsm_create_view FROM PUBLIC; +REVOKE ALL ON FUNCTION pgsm_create_18_view FROM PUBLIC; GRANT SELECT ON pg_stat_monitor TO PUBLIC; diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 9379343..74e5102 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -37,7 +37,8 @@ typedef enum pgsmVersion { PGSM_V1_0 = 0, PGSM_V2_0, - PGSM_V2_1 + PGSM_V2_1, + PGSM_V2_3, } pgsmVersion; PG_MODULE_MAGIC; @@ -48,7 +49,8 @@ PG_MODULE_MAGIC; #define PG_STAT_MONITOR_COLS_V1_0 52 #define PG_STAT_MONITOR_COLS_V2_0 64 #define PG_STAT_MONITOR_COLS_V2_1 70 -#define PG_STAT_MONITOR_COLS PG_STAT_MONITOR_COLS_V2_1 /* maximum of above */ +#define PG_STAT_MONITOR_COLS_V2_3 71 +#define PG_STAT_MONITOR_COLS PG_STAT_MONITOR_COLS_V2_3 /* maximum of above */ #define PGSM_TEXT_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat_monitor_query" @@ -150,6 +152,7 @@ PG_FUNCTION_INFO_V1(pg_stat_monitor_reset); PG_FUNCTION_INFO_V1(pg_stat_monitor_1_0); PG_FUNCTION_INFO_V1(pg_stat_monitor_2_0); PG_FUNCTION_INFO_V1(pg_stat_monitor_2_1); +PG_FUNCTION_INFO_V1(pg_stat_monitor_2_3); PG_FUNCTION_INFO_V1(pg_stat_monitor); PG_FUNCTION_INFO_V1(get_histogram_timings); PG_FUNCTION_INFO_V1(pg_stat_monitor_hook_stats); @@ -1584,6 +1587,9 @@ pgsm_update_entry(pgsmEntry *entry, entry->counters.walusage.wal_records += walusage->wal_records; entry->counters.walusage.wal_fpi += walusage->wal_fpi; entry->counters.walusage.wal_bytes += walusage->wal_bytes; +#if PG_VERSION_NUM >= 180000 + entry->counters.walusage.wal_buffers_full += walusage->wal_buffers_full; +#endif } if (jitusage) { @@ -1877,6 +1883,10 @@ pgsm_store(pgsmEntry *entry) walusage.wal_fpi = entry->counters.walusage.wal_fpi; walusage.wal_bytes = entry->counters.walusage.wal_bytes; +#if PG_VERSION_NUM >= 180000 + walusage.wal_buffers_full = entry->counters.walusage.wal_buffers_full; +#endif + /* jit */ jitusage.created_functions = entry->counters.jitinfo.jit_functions; memcpy(&jitusage.generation_counter, &entry->counters.jitinfo.instr_generation_counter, sizeof(instr_time)); @@ -2063,6 +2073,13 @@ pg_stat_monitor_2_1(PG_FUNCTION_ARGS) return (Datum) 0; } +Datum +pg_stat_monitor_2_3(PG_FUNCTION_ARGS) +{ + pg_stat_monitor_internal(fcinfo, PGSM_V2_3, true); + return (Datum) 0; +} + /* * Legacy entry point for pg_stat_monitor() API versions 1.0 */ @@ -2116,6 +2133,9 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, case PGSM_V2_1: expected_columns = PG_STAT_MONITOR_COLS_V2_1; break; + case PGSM_V2_3: + expected_columns = PG_STAT_MONITOR_COLS_V2_3; + break; default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -2499,13 +2519,19 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, /* wal_bytes at column number 54 */ values[i++] = wal_bytes; - /* application_name at column number 55 */ + if (api_version >= PGSM_V2_3) + { + /* wal_buffers_full at column number 55 */ + values[i++] = Int64GetDatumFast(tmp.walusage.wal_buffers_full); + } + + /* application_name at column number 56 */ if (strlen(tmp.info.comments) > 0) values[i++] = CStringGetTextDatum(tmp.info.comments); else nulls[i++] = true; - /* blocks are from column number 56 - 63 */ + /* blocks are from column number 57 - 64 */ values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_functions); values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_generation_time); values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_inlining_count); @@ -2516,7 +2542,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_emission_time); if (api_version >= PGSM_V2_1) { - /* at column number 64 */ + /* at column number 65 */ values[i++] = Int64GetDatumFast(tmp.jitinfo.jit_deform_count); values[i++] = Float8GetDatumFast(tmp.jitinfo.jit_deform_time); } @@ -2524,15 +2550,15 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, if (api_version >= PGSM_V2_1) { - /* at column number 66 */ + /* at column number 67 */ values[i++] = TimestampTzGetDatum(entry->stats_since); values[i++] = TimestampTzGetDatum(entry->minmax_stats_since); } - /* toplevel at column number 68 */ + /* toplevel at column number 69 */ values[i++] = BoolGetDatum(toplevel); - /* bucket_done at column number 69 */ + /* bucket_done at column number 70 */ values[i++] = BoolGetDatum(pg_atomic_read_u64(&pgsm->current_wbucket) != bucketid); /* clean up and return the tuplestore */ diff --git a/pg_stat_monitor.h b/pg_stat_monitor.h index cda6802..0e6c7bc 100644 --- a/pg_stat_monitor.h +++ b/pg_stat_monitor.h @@ -308,6 +308,7 @@ typedef struct Wal_Usage int64 wal_records; /* # of WAL records generated */ int64 wal_fpi; /* # of WAL full page images generated */ uint64 wal_bytes; /* total amount of WAL bytes generated */ + int64 wal_buffers_full; /* # of times the WAL buffers became full */ } Wal_Usage; typedef struct Counters diff --git a/regression/expected/functions.out b/regression/expected/functions.out index 9bed45b..39cc309 100644 --- a/regression/expected/functions.out +++ b/regression/expected/functions.out @@ -24,9 +24,10 @@ SELECT routine_schema, routine_name, routine_type, data_type FROM information_sc public | pgsm_create_14_view | FUNCTION | integer public | pgsm_create_15_view | FUNCTION | integer public | pgsm_create_17_view | FUNCTION | integer + public | pgsm_create_18_view | FUNCTION | integer public | pgsm_create_view | FUNCTION | integer public | range | FUNCTION | ARRAY -(13 rows) +(14 rows) SET ROLE u1; SELECT routine_schema, routine_name, routine_type, data_type FROM information_schema.routines WHERE routine_schema = 'public' ORDER BY routine_name COLLATE "C"; diff --git a/regression/expected/functions_1.out b/regression/expected/functions_1.out index 932643e..69c4cfd 100644 --- a/regression/expected/functions_1.out +++ b/regression/expected/functions_1.out @@ -24,9 +24,10 @@ SELECT routine_schema, routine_name, routine_type, data_type FROM information_sc public | pgsm_create_14_view | FUNCTION | integer public | pgsm_create_15_view | FUNCTION | integer public | pgsm_create_17_view | FUNCTION | integer + public | pgsm_create_18_view | FUNCTION | integer public | pgsm_create_view | FUNCTION | integer public | range | FUNCTION | ARRAY -(13 rows) +(14 rows) SET ROLE u1; SELECT routine_schema, routine_name, routine_type, data_type FROM information_schema.routines WHERE routine_schema = 'public' ORDER BY routine_name COLLATE "C"; diff --git a/t/018_column_names.pl b/t/018_column_names.pl index 2f5448a..8c5cbb3 100644 --- a/t/018_column_names.pl +++ b/t/018_column_names.pl @@ -36,7 +36,8 @@ my %pg_versions_pgsm_columns = ( 18 => "application_name,". "shared_blks_hit,shared_blks_read,shared_blks_written,sqlcode,stats_since," . "stddev_exec_time,stddev_plan_time,temp_blk_read_time,temp_blk_write_time," . "temp_blks_read,temp_blks_written,top_query,top_queryid,toplevel," . - "total_exec_time,total_plan_time,userid,username,wal_bytes,wal_fpi,wal_records", + "total_exec_time,total_plan_time,userid,username,wal_buffers_full,wal_bytes," . + "wal_fpi,wal_records", 17 => "application_name,". "bucket,bucket_done,bucket_start_time,calls," . "client_ip,cmd_type,cmd_type_text,comments,cpu_sys_time,cpu_user_time," . diff --git a/t/025_compare_pgss.pl b/t/025_compare_pgss.pl index 5d1bffc..37cdb59 100644 --- a/t/025_compare_pgss.pl +++ b/t/025_compare_pgss.pl @@ -93,10 +93,10 @@ PGSM::append_to_debug_file($stdout); ($cmdret, $stdout, $stderr) = $node->psql('postgres', "SELECT bucket, bucket_start_time, queryid, substr(query,0,30) AS query, calls, rows, total_exec_time, min_exec_time, max_exec_time, mean_exec_time, stddev_exec_time, ROUND(${col_shared_blk_read_time}::numeric,4) AS ${col_shared_blk_read_time}, ROUND(${col_shared_blk_write_time}::numeric,4) AS ${col_shared_blk_write_time}, cpu_user_time, cpu_sys_time FROM pg_stat_monitor WHERE query LIKE '%bench%' ORDER BY query,calls DESC;", extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']); PGSM::append_to_debug_file($stdout); -($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT substr(query,0,30) AS query,calls,rows,wal_records,wal_fpi,wal_bytes FROM pg_stat_statements WHERE query LIKE \'%bench%\' ORDER BY query,calls;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']); +($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT substr(query,0,30) AS query,calls,rows,wal_records,wal_fpi,wal_bytes,wal_buffers_full FROM pg_stat_statements WHERE query LIKE \'%bench%\' ORDER BY query,calls;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']); PGSM::append_to_debug_file($stdout); -($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT bucket, bucket_start_time, substr(query,0,30) AS query,calls, rows, wal_records,wal_fpi,wal_bytes, cmd_type_text FROM pg_stat_monitor WHERE query LIKE \'%bench%\' ORDER BY query,calls;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']); +($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT bucket, bucket_start_time, substr(query,0,30) AS query,calls, rows, wal_records,wal_fpi,wal_bytes,wal_buffers_full, cmd_type_text FROM pg_stat_monitor WHERE query LIKE \'%bench%\' ORDER BY query,calls;', extra_params => ['-a', '-Pformat=aligned','-Ptuples_only=off']); PGSM::append_to_debug_file($stdout); # Compare values for query 'DELETE FROM pgbench_accounts WHERE $1 = $2' @@ -140,6 +140,13 @@ is($stdout,'t',"Compare: wal_fpi is equal."); trim($stdout); is($stdout,'t',"Compare: wal_bytes are equal."); +if ($PGSM::PG_MAJOR_VERSION >= 18) +{ + ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_buffers_full) = SUM(PGSS.wal_buffers_full) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%DELETE FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); + trim($stdout); + is($stdout,'t',"Compare: wal_buffers_full are equal."); +} + # Compare values for query 'INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP)' ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.calls) = SUM(PGSS.calls) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); @@ -189,6 +196,13 @@ is($stdout,'t',"Compare: wal_fpi is equal."); trim($stdout); is($stdout,'t',"Compare: wal_bytes are equal."); +if ($PGSM::PG_MAJOR_VERSION >= 18) +{ + ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_buffers_full) = SUM(PGSS.wal_buffers_full) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%INSERT INTO pgbench_history%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); + trim($stdout); + is($stdout,'t',"Compare: wal_buffers_full are equal."); +} + # Compare values for query 'SELECT abalance FROM pgbench_accounts WHERE aid = $1' ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.calls) = SUM(PGSS.calls) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); @@ -238,6 +252,13 @@ is($stdout,'t',"Compare: wal_fpi is equal."); trim($stdout); is($stdout,'t',"Compare: wal_bytes are equal."); +if ($PGSM::PG_MAJOR_VERSION >= 18) +{ + ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_buffers_full) = SUM(PGSS.wal_buffers_full) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%SELECT abalance FROM pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); + trim($stdout); + is($stdout,'t',"Compare: wal_buffers_full are equal."); +} + # Compare values for query 'UPDATE pgbench_accounts SET abalance = abalance + $1 WHERE aid = $2' ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.calls) = SUM(PGSS.calls) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); trim($stdout); @@ -283,6 +304,13 @@ is($stdout,'t',"Compare: wal_fpi is equal."); trim($stdout); is($stdout,'t',"Compare: wal_bytes are equal."); +if ($PGSM::PG_MAJOR_VERSION >= 18) +{ + ($cmdret, $stdout, $stderr) = $node->psql('postgres', 'SELECT SUM(PGSM.wal_buffers_full) = SUM(PGSS.wal_buffers_full) FROM pg_stat_monitor AS PGSM INNER JOIN pg_stat_statements AS PGSS ON PGSS.query = PGSM.query WHERE PGSM.query LIKE \'%UPDATE pgbench_accounts%\' GROUP BY PGSM.query;', extra_params => ['-Pformat=unaligned','-Ptuples_only=on']); + trim($stdout); + is($stdout,'t',"Compare: wal_buffers_full are equal."); +} + # DROP EXTENSION $stdout = $node->safe_psql('postgres', 'DROP EXTENSION pg_stat_monitor;', extra_params => ['-a']); ok($cmdret == 0, "DROP PGSM EXTENSION");