Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
- Connection strings can be excluded from dumps now
- Restartpoints stats added to the reports (when available)
- Improvements in summary dashboard
- Server network identity collection (server_hostname, server_ip, server_port)
via dblink. Hostname is populated when the *hostname* extension is present
on the monitored server; IP/port are populated via *inet_server_addr()*
/*inet_server_port()* with a *pg_settings* fallback. Reports show a
"Network Information" section when data is available. Enable regression
tests with *make installcheck USE_HOSTNAME=1*.
- Other fixes and improvements

## 4.10
Expand Down
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ REGRESS += \
kcache_drop_extension
endif

# hostname extension tests
ifdef USE_HOSTNAME
REGRESS += \
hostname_create_extension \
server_management \
samples_and_reports \
sizes_collection \
hostname_feature \
export_import \
retention_and_baselines \
hostname_drop_extension
endif

PG_CONFIG ?= pg_config

ifdef USE_PGXS
Expand Down Expand Up @@ -75,6 +88,7 @@ sample = \
sample/get_sized_bounds.sql \
sample/init_sample.sql \
sample/pg_wait_sampling.sql \
sample/hostname.sql \
sample/query_pg_stat_archiver.sql \
sample/query_pg_stat_bgwriter.sql \
sample/query_pg_stat_io.sql \
Expand Down
24 changes: 22 additions & 2 deletions data/report_struct.sql
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ VALUES
']}'
']}'
']'::jsonb),
(1, 'rep_settings', NULL, 11, NULL, NULL, NULL, NULL, NULL,
(1, 'rep_settings', NULL, 12, NULL, NULL, NULL, NULL, NULL,
'[{'
'"type": "row_table",'
'"source": "settings",'
Expand All @@ -45,6 +45,16 @@ VALUES
'{"id": "stmt_cnt", "class": "table_obj_value", "caption": "Stmts Captured"}, '
'{"id": "max_cnt", "class": "table_obj_value", "caption": "pg_stat_statements.max"}'
']}]'::jsonb),
(1, 'netinfo', NULL, 11, NULL, NULL, 'server_hostname', NULL, NULL,
'[{
"type": "row_table",
"source": "netinfo",
"columns": [
{"id": "server_hostname", "class": "table_obj_value", "caption": "Hostname"},
{"id": "server_ip", "class": "table_obj_value", "caption": "IP Address"},
{"id": "server_port", "class": "table_obj_value", "caption": "Port"}
]
}]'::jsonb),
(1, 'srvstat', NULL, 200, 'Server statistics', 'Server statistics', NULL, NULL, NULL, NULL),
(1, 'actsesshdr', NULL, 250, 'Session states', 'Session states observed by subsamples', 'act_backend', NULL,
'{"class": "notice", "text": "Statistics about session states exceeding capturing thresholds."}', NULL),
Expand Down Expand Up @@ -2225,7 +2235,7 @@ VALUES
'{"id": ["report_end1", "report_end2"], "class": "table_obj_value", "caption": "end"}'
']}'
']}]'::jsonb),
(2, 'rep_settings', NULL, 11, NULL, NULL, NULL, NULL, NULL,
(2, 'rep_settings', NULL, 12, NULL, NULL, NULL, NULL, NULL,
'[{'
'"type": "row_table",'
'"source": "settings",'
Expand All @@ -2249,6 +2259,16 @@ VALUES
'{"id": "stmt_cnt", "class": "table_obj_value", "caption": "Stmts Captured"}, '
'{"id": "max_cnt", "class": "table_obj_value", "caption": "pg_stat_statements.max"}'
']}]'::jsonb),
(2, 'netinfo', NULL, 11, NULL, NULL, 'server_hostname', NULL, NULL,
'[{
"type": "row_table",
"source": "netinfo",
"columns": [
{"id": "server_hostname", "class": "table_obj_value", "caption": "Hostname"},
{"id": "server_ip", "class": "table_obj_value", "caption": "IP Address"},
{"id": "server_port", "class": "table_obj_value", "caption": "Port"}
]
}]'::jsonb),
(2, 'srvstat', NULL, 300, 'Server statistics', 'Server statistics', NULL, NULL, NULL, NULL),
(2, 'actsesshdr', NULL, 350, 'Session states', 'Session states observed by subsamples', 'act_backend', NULL,
'{"class": "notice", "text": "Statistics about session states exceeding capturing thresholds."}', NULL),
Expand Down
7 changes: 7 additions & 0 deletions expected/hostname_create_extension.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE SCHEMA IF NOT EXISTS profile;
CREATE SCHEMA IF NOT EXISTS dblink;
CREATE SCHEMA IF NOT EXISTS statements;
CREATE EXTENSION dblink SCHEMA dblink;
CREATE EXTENSION pg_stat_statements SCHEMA statements;
CREATE EXTENSION hostname;
CREATE EXTENSION pg_profile SCHEMA profile;
24 changes: 24 additions & 0 deletions expected/hostname_drop_extension.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Drop test objects */
DROP TABLE profile.grow_table;
DROP TABLE profile.test_rel_storage_params1;
DROP TABLE profile.test_rel_storage_params2;
DROP FUNCTION profile.dummy_func();
DROP FUNCTION profile.grow_table_trg_f();
DROP FUNCTION profile.get_ids;
DROP FUNCTION profile.get_sources;
DROP FUNCTION profile.get_report_sections;
DROP FUNCTION profile.check_dataset_queries;
/* Testing drop server with data */
SELECT * FROM profile.drop_server('local');
drop_server
-------------
1
(1 row)

DROP EXTENSION pg_profile;
DROP EXTENSION hostname;
DROP EXTENSION IF EXISTS pg_stat_statements;
DROP EXTENSION IF EXISTS dblink;
DROP SCHEMA profile;
DROP SCHEMA dblink;
DROP SCHEMA statements;
113 changes: 113 additions & 0 deletions expected/hostname_feature.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/* == Testing hostname/network identity feature == */
/* This test validates the server network identity feature
when the hostname extension is available.
NOTE: This runs after samples_and_reports which already took samples,
so we use existing sample data rather than taking new samples. */
SET client_min_messages = WARNING;
/* === Verify schema columns exist === */
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'profile'
AND table_name = 'servers'
AND column_name IN ('server_hostname', 'server_ip', 'server_port')
ORDER BY column_name;
column_name | data_type
-----------------+-----------
server_hostname | text
server_ip | text
server_port | integer
(3 rows)

SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'profile'
AND table_name = 'samples'
AND column_name IN ('server_hostname', 'server_ip', 'server_port')
ORDER BY column_name;
column_name | data_type
-----------------+-----------
server_hostname | text
server_ip | text
server_port | integer
(3 rows)

/* === Verify functions exist === */
SELECT proname, pronargs
FROM pg_proc
WHERE pronamespace = 'profile'::regnamespace
AND proname = 'collect_system_info'
ORDER BY proname;
proname | pronargs
---------------------+----------
collect_system_info | 3
(1 row)

/* === Test that show_servers includes network columns === */
SELECT
server_hostname IS NOT NULL AS has_hostname,
server_ip IS NOT NULL AS has_ip,
server_port IS NOT NULL AS has_port
FROM profile.show_servers()
WHERE server_name = 'local';
has_hostname | has_ip | has_port
--------------+--------+----------
t | t | t
(1 row)

/* === Verify servers table was populated by earlier samples === */
SELECT
server_hostname IS NOT NULL AS has_hostname,
server_ip IS NOT NULL AS has_ip,
server_port IS NOT NULL AS has_port
FROM profile.servers
WHERE server_name = 'local';
has_hostname | has_ip | has_port
--------------+--------+----------
t | t | t
(1 row)

/* === Verify samples table was populated === */
SELECT
server_hostname IS NOT NULL AS has_hostname,
server_ip IS NOT NULL AS has_ip,
server_port IS NOT NULL AS has_port
FROM profile.samples
WHERE server_id = 1
ORDER BY sample_id DESC
LIMIT 1;
has_hostname | has_ip | has_port
--------------+--------+----------
t | t | t
(1 row)

/* === Verify server_hostname feature flag is set === */
SELECT
(profile.get_report_context(1, 1, 2) #>> '{report_features,server_hostname}')::boolean
AS hostname_feature_enabled;
hostname_feature_enabled
--------------------------
t
(1 row)

/* === Test export includes new columns === */
CREATE TABLE profile.hostname_export AS SELECT * FROM profile.export_data();
SELECT count(*) > 0 AS export_has_data
FROM profile.hostname_export;
export_has_data
-----------------
t
(1 row)

SELECT
(row_data::json->>'server_hostname') IS NOT NULL AS export_has_hostname,
(row_data::json->>'server_ip') IS NOT NULL AS export_has_ip,
(row_data::json->>'server_port') IS NOT NULL AS export_has_port
FROM profile.hostname_export
WHERE section_id = 1
AND (row_data::json->>'server_hostname') IS NOT NULL
LIMIT 1;
export_has_hostname | export_has_ip | export_has_port
---------------------+---------------+-----------------
(0 rows)

DROP TABLE profile.hostname_export;
6 changes: 3 additions & 3 deletions expected/server_management.out
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ FROM profile.servers WHERE server_name != 'local';
(1 row)

SELECT * FROM profile.show_servers() where server_name != 'local';
server_name | connstr | enabled | max_sample_age | description
----------------+------------------------------------------+---------+----------------+----------------------
srvtestrenamed | dbname=postgres host=localhost port=5433 | t | 3 | Server description 2
server_name | server_hostname | server_ip | server_port | connstr | enabled | max_sample_age | description
----------------+-----------------+-----------+-------------+------------------------------------------+---------+----------------+----------------------
srvtestrenamed | | | | dbname=postgres host=localhost port=5433 | t | 3 | Server description 2
(1 row)

SELECT * FROM profile.drop_server('srvtestrenamed');
Expand Down
48 changes: 38 additions & 10 deletions management/export.sql
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,10 @@ BEGIN
rows.size_smp_wnd_start,
rows.size_smp_wnd_dur,
rows.size_smp_interval,
rows.srv_settings
rows.srv_settings,
rows.server_hostname,
rows.server_ip,
rows.server_port
FROM %I AS rows WHERE $2 IS NULL OR server_id = $2) dt$sql$,
r_result.relname
)
Expand Down Expand Up @@ -333,7 +336,10 @@ BEGIN
imp_srv.size_smp_wnd_start imp_size_smp_wnd_start,
imp_srv.size_smp_wnd_dur imp_size_smp_wnd_dur,
imp_srv.size_smp_interval imp_size_smp_interval,
imp_srv.srv_settings imp_srv_settings
imp_srv.srv_settings imp_srv_settings,
imp_srv.server_hostname imp_server_hostname,
imp_srv.server_ip imp_server_ip,
imp_srv.server_port imp_server_port
FROM
jsonb_to_recordset($1) as
imp_srv(
Expand All @@ -349,7 +355,10 @@ BEGIN
size_smp_wnd_start time with time zone,
size_smp_wnd_dur interval hour to second,
size_smp_interval interval day to minute,
srv_settings jsonb
srv_settings jsonb,
server_hostname text,
server_ip text,
server_port integer
)
JOIN %s d ON
(d.section_id = $2 AND d.row_data->>'name' = 'system_identifier'
Expand Down Expand Up @@ -392,7 +401,10 @@ BEGIN
size_smp_wnd_start,
size_smp_wnd_dur,
size_smp_interval,
srv_settings
srv_settings,
server_hostname,
server_ip,
server_port
) = (
r_result.imp_server_db_exclude,
r_result.imp_server_connstr,
Expand All @@ -401,7 +413,10 @@ BEGIN
r_result.imp_size_smp_wnd_start,
r_result.imp_size_smp_wnd_dur,
r_result.imp_size_smp_interval,
r_result.imp_srv_settings
r_result.imp_srv_settings,
r_result.imp_server_hostname,
r_result.imp_server_ip,
r_result.imp_server_port
)
WHERE server_id = r_result.local_server_id
AND last_sample_id < r_result.imp_server_last_sample_id;
Expand All @@ -425,7 +440,10 @@ BEGIN
size_smp_wnd_start,
size_smp_wnd_dur,
size_smp_interval,
srv_settings)
srv_settings,
server_hostname,
server_ip,
server_port)
VALUES (
r_result.imp_server_name,
r_result.imp_server_description,
Expand All @@ -438,7 +456,10 @@ BEGIN
r_result.imp_size_smp_wnd_start,
r_result.imp_size_smp_wnd_dur,
r_result.imp_size_smp_interval,
r_result.imp_srv_settings
r_result.imp_srv_settings,
r_result.imp_server_hostname,
r_result.imp_server_ip,
r_result.imp_server_port
)
RETURNING server_id INTO new_server_id;
tmp_srv_map := jsonb_set(
Expand Down Expand Up @@ -657,15 +678,22 @@ BEGIN
LOOP
FETCH data INTO datarow;
EXIT WHEN NOT FOUND;
INSERT INTO samples(server_id, sample_id, sample_time)
INSERT INTO samples(server_id, sample_id, sample_time,
server_hostname, server_ip, server_port)
SELECT
(srv_map ->> dr.server_id::text)::integer,
dr.sample_id,
dr.sample_time
dr.sample_time,
dr.server_hostname,
dr.server_ip,
dr.server_port
FROM json_to_record(datarow.row_data) AS dr(
server_id integer,
sample_id integer,
sample_time timestamp(0) with time zone
sample_time timestamp(0) with time zone,
server_hostname text,
server_ip text,
server_port integer
)
JOIN
servers s_ctl ON
Expand Down
Loading