From f32c4a3edbc49440305cc4edf775121147e6e259 Mon Sep 17 00:00:00 2001 From: Hari Babu Date: Mon, 8 Jan 2018 14:20:50 +1100 Subject: [PATCH 2/2] remote_server_info column addtion to pg_stat_wal_receiver This column provides the remote server information of the WAL receiver connection to the remote host. --- doc/src/sgml/monitoring.sgml | 9 ++++- src/backend/catalog/system_views.sql | 1 + .../libpqwalreceiver/libpqwalreceiver.c | 44 ++++++++++++++++++++++ src/backend/replication/walreceiver.c | 21 ++++++++++- src/include/catalog/pg_proc.h | 2 +- src/include/replication/walreceiver.h | 10 +++++ src/test/regress/expected/rules.out | 3 +- 7 files changed, 85 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 8a9793644f..9a6aac45f5 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -2022,11 +2022,18 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i text Replication slot name used by this WAL receiver + + remote_server_info + text + + Effective remote server connection info string used by this WAL receiver. + + conninfo text - Connection string used by this WAL receiver, + Initial connection string used by this WAL receiver, with security-sensitive fields obfuscated. diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 5652e9ee6d..b0f74ed9bc 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -750,6 +750,7 @@ CREATE VIEW pg_stat_wal_receiver AS s.latest_end_lsn, s.latest_end_time, s.slot_name, + s.remote_server_info, s.conninfo FROM pg_stat_get_wal_receiver() s WHERE s.pid IS NOT NULL; diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index f9aec0531a..488c1c2dde 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -53,6 +53,7 @@ static WalReceiverConn *libpqrcv_connect(const char *conninfo, char **err); static void libpqrcv_check_conninfo(const char *conninfo); static char *libpqrcv_get_conninfo(WalReceiverConn *conn); +static char *libpqrcv_get_remote_server_info(WalReceiverConn *conn); static char *libpqrcv_identify_system(WalReceiverConn *conn, TimeLineID *primary_tli, int *server_version); @@ -82,6 +83,7 @@ static WalReceiverFunctionsType PQWalReceiverFunctions = { libpqrcv_connect, libpqrcv_check_conninfo, libpqrcv_get_conninfo, + libpqrcv_get_remote_server_info, libpqrcv_identify_system, libpqrcv_readtimelinehistoryfile, libpqrcv_startstreaming, @@ -282,6 +284,47 @@ libpqrcv_get_conninfo(WalReceiverConn *conn) return retval; } +/* + * Return a user-displayable remote server information. + */ +static char * +libpqrcv_get_remote_server_info(WalReceiverConn *conn) +{ + PQconninfoOption *conn_opts; + PQconninfoOption *conn_opt; + PQExpBufferData buf; + char *retval; + + Assert(conn->streamConn != NULL); + + initPQExpBuffer(&buf); + conn_opts = PQeffectiveConninfo(conn->streamConn); + + if (conn_opts == NULL) + ereport(ERROR, + (errmsg("could not parse connection string: %s", + _("out of memory")))); + + /* build a clean connection string from pieces */ + for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++) + { + if ((strcmp(conn_opt->keyword, "host") == 0) || + (strcmp(conn_opt->keyword, "hostaddr") == 0) || + (strcmp(conn_opt->keyword, "port") == 0)) + { + appendPQExpBuffer(&buf, "%s%s=%s", + buf.len == 0 ? "" : " ", + conn_opt->keyword, conn_opt->val); + } + } + + PQconninfoFree(conn_opts); + + retval = PQExpBufferDataBroken(buf) ? NULL : pstrdup(buf.data); + termPQExpBuffer(&buf); + return retval; +} + /* * Check that primary's system identifier matches ours, and fetch the current * timeline ID of the primary. diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c index a39a98ff18..b93b843b2d 100644 --- a/src/backend/replication/walreceiver.c +++ b/src/backend/replication/walreceiver.c @@ -189,6 +190,7 @@ WalReceiverMain(void) { char conninfo[MAXCONNINFO]; char *tmp_conninfo; + char *tmp_remote_server_info; char slotname[NAMEDATALEN]; XLogRecPtr startpoint; TimeLineID startpointTLI; @@ -311,16 +313,25 @@ WalReceiverMain(void) * conninfo, for security. */ tmp_conninfo = walrcv_get_conninfo(wrconn); + tmp_remote_server_info = walrcv_get_remote_server_info(wrconn); SpinLockAcquire(&walrcv->mutex); memset(walrcv->conninfo, 0, MAXCONNINFO); if (tmp_conninfo) strlcpy((char *) walrcv->conninfo, tmp_conninfo, MAXCONNINFO); + + memset(walrcv->remote_server_info, 0, MAXCONNINFO); + if (tmp_remote_server_info) + strlcpy((char *) walrcv->remote_server_info, tmp_remote_server_info, MAXCONNINFO); + walrcv->ready_to_display = true; SpinLockRelease(&walrcv->mutex); if (tmp_conninfo) pfree(tmp_conninfo); + if (tmp_remote_server_info) + pfree(tmp_remote_server_info); + first_stream = true; for (;;) { @@ -1404,6 +1415,7 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) TimestampTz latest_end_time; char slotname[NAMEDATALEN]; char conninfo[MAXCONNINFO]; + char remote_server_info[MAXCONNINFO]; /* Take a lock to ensure value consistency */ SpinLockAcquire(&WalRcv->mutex); @@ -1419,6 +1431,7 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) latest_end_lsn = WalRcv->latestWalEnd; latest_end_time = WalRcv->latestWalEndTime; strlcpy(slotname, (char *) WalRcv->slotname, sizeof(slotname)); + strlcpy(remote_server_info, (char *) WalRcv->remote_server_info, sizeof(remote_server_info)); strlcpy(conninfo, (char *) WalRcv->conninfo, sizeof(conninfo)); SpinLockRelease(&WalRcv->mutex); @@ -1482,10 +1495,14 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS) nulls[10] = true; else values[10] = CStringGetTextDatum(slotname); - if (*conninfo == '\0') + if (*remote_server_info == '\0') nulls[11] = true; else - values[11] = CStringGetTextDatum(conninfo); + values[11] = CStringGetTextDatum(remote_server_info); + if (*conninfo == '\0') + nulls[12] = true; + else + values[12] = CStringGetTextDatum(conninfo); } /* Returns the record as Datum */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 298e0ae2f0..f043d88797 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -2883,7 +2883,7 @@ DATA(insert OID = 3318 ( pg_stat_get_progress_info PGNSP PGUID 12 1 100 0 0 DESCR("statistics: information about progress of backends running maintenance command"); DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 0 f f f f f t s r 0 0 2249 "" "{23,25,3220,3220,3220,3220,1186,1186,1186,23,25}" "{o,o,o,o,o,o,o,o,o,o,o}" "{pid,state,sent_lsn,write_lsn,flush_lsn,replay_lsn,write_lag,flush_lag,replay_lag,sync_priority,sync_state}" _null_ _null_ pg_stat_get_wal_senders _null_ _null_ _null_ )); DESCR("statistics: information about currently active replication"); -DATA(insert OID = 3317 ( pg_stat_get_wal_receiver PGNSP PGUID 12 1 0 0 0 f f f f f f s r 0 0 2249 "" "{23,25,3220,23,3220,23,1184,1184,3220,1184,25,25}" "{o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,status,receive_start_lsn,receive_start_tli,received_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,slot_name,conninfo}" _null_ _null_ pg_stat_get_wal_receiver _null_ _null_ _null_ )); +DATA(insert OID = 3317 ( pg_stat_get_wal_receiver PGNSP PGUID 12 1 0 0 0 f f f f f f s r 0 0 2249 "" "{23,25,3220,23,3220,23,1184,1184,3220,1184,25,25,25}" "{o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,status,receive_start_lsn,receive_start_tli,received_lsn,received_tli,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time,slot_name,remote_server_info,conninfo}" _null_ _null_ pg_stat_get_wal_receiver _null_ _null_ _null_ )); DESCR("statistics: information about WAL receiver"); DATA(insert OID = 6118 ( pg_stat_get_subscription PGNSP PGUID 12 1 0 0 0 f f f f f f s r 1 0 2249 "26" "{26,26,26,23,3220,1184,1184,3220,1184}" "{i,o,o,o,o,o,o,o,o}" "{subid,subid,relid,pid,received_lsn,last_msg_send_time,last_msg_receipt_time,latest_end_lsn,latest_end_time}" _null_ _null_ pg_stat_get_subscription _null_ _null_ _null_ )); DESCR("statistics: information about subscription"); diff --git a/src/include/replication/walreceiver.h b/src/include/replication/walreceiver.h index ea7967f6fc..2f0f33ad03 100644 --- a/src/include/replication/walreceiver.h +++ b/src/include/replication/walreceiver.h @@ -108,6 +108,12 @@ typedef struct */ char conninfo[MAXCONNINFO]; + /* + * connection string; effectively used to connect to the primary, and later + * clobbered to hide security-sensitive fields. + */ + char remote_server_info[MAXCONNINFO]; + /* * replication slot name; is also used for walreceiver to connect with the * primary @@ -197,6 +203,7 @@ typedef WalReceiverConn *(*walrcv_connect_fn) (const char *conninfo, bool logica char **err); typedef void (*walrcv_check_conninfo_fn) (const char *conninfo); typedef char *(*walrcv_get_conninfo_fn) (WalReceiverConn *conn); +typedef char *(*walrcv_get_remote_server_info_fn) (WalReceiverConn *conn); typedef char *(*walrcv_identify_system_fn) (WalReceiverConn *conn, TimeLineID *primary_tli, int *server_version); @@ -227,6 +234,7 @@ typedef struct WalReceiverFunctionsType walrcv_connect_fn walrcv_connect; walrcv_check_conninfo_fn walrcv_check_conninfo; walrcv_get_conninfo_fn walrcv_get_conninfo; + walrcv_get_remote_server_info_fn walrcv_get_remote_server_info; walrcv_identify_system_fn walrcv_identify_system; walrcv_readtimelinehistoryfile_fn walrcv_readtimelinehistoryfile; walrcv_startstreaming_fn walrcv_startstreaming; @@ -246,6 +254,8 @@ extern PGDLLIMPORT WalReceiverFunctionsType *WalReceiverFunctions; WalReceiverFunctions->walrcv_check_conninfo(conninfo) #define walrcv_get_conninfo(conn) \ WalReceiverFunctions->walrcv_get_conninfo(conn) +#define walrcv_get_remote_server_info(conn) \ + WalReceiverFunctions->walrcv_get_remote_server_info(conn) #define walrcv_identify_system(conn, primary_tli, server_version) \ WalReceiverFunctions->walrcv_identify_system(conn, primary_tli, server_version) #define walrcv_readtimelinehistoryfile(conn, tli, filename, content, size) \ diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index f1c1b44d6f..5d757c141e 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1970,8 +1970,9 @@ pg_stat_wal_receiver| SELECT s.pid, s.latest_end_lsn, s.latest_end_time, s.slot_name, + s.remote_server_info, s.conninfo - FROM pg_stat_get_wal_receiver() s(pid, status, receive_start_lsn, receive_start_tli, received_lsn, received_tli, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time, slot_name, conninfo) + FROM pg_stat_get_wal_receiver() s(pid, status, receive_start_lsn, receive_start_tli, received_lsn, received_tli, last_msg_send_time, last_msg_receipt_time, latest_end_lsn, latest_end_time, slot_name, remote_server_info, conninfo) WHERE (s.pid IS NOT NULL); pg_stat_xact_all_tables| SELECT c.oid AS relid, n.nspname AS schemaname, -- 2.15.0.windows.1