Commit 4a25bc14 authored by Robert Haas's avatar Robert Haas

Add client_hostname field to pg_stat_activity.

Peter Eisentraut, reviewed by Steve Singer, Alvaro Herrera, and me.
parent a3e8486d
...@@ -245,14 +245,17 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re ...@@ -245,14 +245,17 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<entry><structname>pg_stat_activity</><indexterm><primary>pg_stat_activity</primary></indexterm></entry> <entry><structname>pg_stat_activity</><indexterm><primary>pg_stat_activity</primary></indexterm></entry>
<entry>One row per server process, showing database OID, database <entry>One row per server process, showing database OID, database
name, process <acronym>ID</>, user OID, user name, application name, name, process <acronym>ID</>, user OID, user name, application name,
client's address and port number, times at which the server process, client's address, hostname (if available), and port number, times at
current transaction, and current query began execution, process's waiting which the server process, current transaction, and current query began
status, and text of the current query. execution, process's waiting status, and text of the current query.
The columns that report data on the current query are available unless The columns that report data on the current query are available unless
the parameter <varname>track_activities</varname> has been turned off. the parameter <varname>track_activities</varname> has been turned off.
Furthermore, these columns are only visible if the user examining Furthermore, these columns are only visible if the user examining
the view is a superuser or the same as the user owning the process the view is a superuser or the same as the user owning the process
being reported on. being reported on. The client's hostname will be available only if
<xref linkend="guc-log-hostname"> is set or if the user's hostname
needed to be looked up during <filename>pg_hba.conf</filename>
processing.
</entry> </entry>
</row> </row>
...@@ -297,14 +300,18 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re ...@@ -297,14 +300,18 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<row> <row>
<entry><structname>pg_stat_replication</><indexterm><primary>pg_stat_replication</primary></indexterm></entry> <entry><structname>pg_stat_replication</><indexterm><primary>pg_stat_replication</primary></indexterm></entry>
<entry>One row per WAL sender process, showing process <acronym>ID</>, <entry>One row per WAL sender process, showing process <acronym>ID</>,
user OID, user name, application name, client's address and port number, user OID, user name, application name, client's address, hostname
time at which the server process began execution, and the current WAL (if available) and port number, time at which the server process began
sender state and transaction log location. In addition, the standby execution, and the current WAL sender state and transaction log
reports the last transaction log position it received and wrote, the last location. In addition, the standby reports the last transaction log
position it flushed to disk, and the last position it replayed, and this position it received and wrote, the last position it flushed to disk,
information is also displayed here. The columns detailing what exactly and the last position it replayed, and this information is also
the connection is doing are only visible if the user examining the view displayed here. The columns detailing what exactly the connection is
is a superuser. doing are only visible if the user examining the view is a superuser.
The client's hostname will be available only if
<xref linkend="guc-log-hostname"> is set or if the user's hostname
needed to be looked up during <filename>pg_hba.conf</filename>
processing.
</entry> </entry>
</row> </row>
......
...@@ -495,6 +495,7 @@ CREATE VIEW pg_stat_activity AS ...@@ -495,6 +495,7 @@ CREATE VIEW pg_stat_activity AS
U.rolname AS usename, U.rolname AS usename,
S.application_name, S.application_name,
S.client_addr, S.client_addr,
S.client_hostname,
S.client_port, S.client_port,
S.backend_start, S.backend_start,
S.xact_start, S.xact_start,
...@@ -512,6 +513,7 @@ CREATE VIEW pg_stat_replication AS ...@@ -512,6 +513,7 @@ CREATE VIEW pg_stat_replication AS
U.rolname AS usename, U.rolname AS usename,
S.application_name, S.application_name,
S.client_addr, S.client_addr,
S.client_hostname,
S.client_port, S.client_port,
S.backend_start, S.backend_start,
W.state, W.state,
......
...@@ -2223,6 +2223,7 @@ pgstat_fetch_global(void) ...@@ -2223,6 +2223,7 @@ pgstat_fetch_global(void)
static PgBackendStatus *BackendStatusArray = NULL; static PgBackendStatus *BackendStatusArray = NULL;
static PgBackendStatus *MyBEEntry = NULL; static PgBackendStatus *MyBEEntry = NULL;
static char *BackendClientHostnameBuffer = NULL;
static char *BackendAppnameBuffer = NULL; static char *BackendAppnameBuffer = NULL;
static char *BackendActivityBuffer = NULL; static char *BackendActivityBuffer = NULL;
...@@ -2240,11 +2241,13 @@ BackendStatusShmemSize(void) ...@@ -2240,11 +2241,13 @@ BackendStatusShmemSize(void)
mul_size(NAMEDATALEN, MaxBackends)); mul_size(NAMEDATALEN, MaxBackends));
size = add_size(size, size = add_size(size,
mul_size(pgstat_track_activity_query_size, MaxBackends)); mul_size(pgstat_track_activity_query_size, MaxBackends));
size = add_size(size,
mul_size(NAMEDATALEN, MaxBackends));
return size; return size;
} }
/* /*
* Initialize the shared status array and activity/appname string buffers * Initialize the shared status array and several string buffers
* during postmaster startup. * during postmaster startup.
*/ */
void void
...@@ -2286,6 +2289,24 @@ CreateSharedBackendStatus(void) ...@@ -2286,6 +2289,24 @@ CreateSharedBackendStatus(void)
} }
} }
/* Create or attach to the shared client hostname buffer */
size = mul_size(NAMEDATALEN, MaxBackends);
BackendClientHostnameBuffer = (char *)
ShmemInitStruct("Backend Client Host Name Buffer", size, &found);
if (!found)
{
MemSet(BackendClientHostnameBuffer, 0, size);
/* Initialize st_clienthostname pointers. */
buffer = BackendClientHostnameBuffer;
for (i = 0; i < MaxBackends; i++)
{
BackendStatusArray[i].st_clienthostname = buffer;
buffer += NAMEDATALEN;
}
}
/* Create or attach to the shared activity buffer */ /* Create or attach to the shared activity buffer */
size = mul_size(pgstat_track_activity_query_size, MaxBackends); size = mul_size(pgstat_track_activity_query_size, MaxBackends);
BackendActivityBuffer = (char *) BackendActivityBuffer = (char *)
...@@ -2386,16 +2407,21 @@ pgstat_bestart(void) ...@@ -2386,16 +2407,21 @@ pgstat_bestart(void)
beentry->st_databaseid = MyDatabaseId; beentry->st_databaseid = MyDatabaseId;
beentry->st_userid = userid; beentry->st_userid = userid;
beentry->st_clientaddr = clientaddr; beentry->st_clientaddr = clientaddr;
beentry->st_clienthostname[0] = '\0';
beentry->st_waiting = false; beentry->st_waiting = false;
beentry->st_appname[0] = '\0'; beentry->st_appname[0] = '\0';
beentry->st_activity[0] = '\0'; beentry->st_activity[0] = '\0';
/* Also make sure the last byte in each string area is always 0 */ /* Also make sure the last byte in each string area is always 0 */
beentry->st_clienthostname[NAMEDATALEN - 1] = '\0';
beentry->st_appname[NAMEDATALEN - 1] = '\0'; beentry->st_appname[NAMEDATALEN - 1] = '\0';
beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0'; beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0';
beentry->st_changecount++; beentry->st_changecount++;
Assert((beentry->st_changecount & 1) == 0); Assert((beentry->st_changecount & 1) == 0);
if (MyProcPort && MyProcPort->remote_hostname)
strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, NAMEDATALEN);
/* Update app name to current GUC setting */ /* Update app name to current GUC setting */
if (application_name) if (application_name)
pgstat_report_appname(application_name); pgstat_report_appname(application_name);
......
...@@ -506,7 +506,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -506,7 +506,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
tupdesc = CreateTemplateTupleDesc(11, false); tupdesc = CreateTemplateTupleDesc(12, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0);
...@@ -517,7 +517,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -517,7 +517,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", TIMESTAMPTZOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start", TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", TIMESTAMPTZOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start", TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", INETOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr", INETOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_port", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname", TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port", INT4OID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc); funcctx->tuple_desc = BlessTupleDesc(tupdesc);
...@@ -569,8 +570,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -569,8 +570,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (funcctx->call_cntr < funcctx->max_calls) if (funcctx->call_cntr < funcctx->max_calls)
{ {
/* for each row */ /* for each row */
Datum values[11]; Datum values[12];
bool nulls[11]; bool nulls[12];
HeapTuple tuple; HeapTuple tuple;
PgBackendStatus *beentry; PgBackendStatus *beentry;
SockAddr zero_clientaddr; SockAddr zero_clientaddr;
...@@ -647,6 +648,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -647,6 +648,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
{ {
nulls[9] = true; nulls[9] = true;
nulls[10] = true; nulls[10] = true;
nulls[11] = true;
} }
else else
{ {
...@@ -671,13 +673,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -671,13 +673,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
{ {
nulls[9] = true; nulls[9] = true;
nulls[10] = true; nulls[10] = true;
nulls[11] = true;
} }
else else
{ {
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host); clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
values[9] = DirectFunctionCall1(inet_in, values[9] = DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host)); CStringGetDatum(remote_host));
values[10] = Int32GetDatum(atoi(remote_port)); if (beentry->st_clienthostname)
values[10] = CStringGetTextDatum(beentry->st_clienthostname);
else
nulls[10] = true;
values[11] = Int32GetDatum(atoi(remote_port));
} }
} }
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX) else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
...@@ -689,13 +696,15 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -689,13 +696,15 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
* errors. * errors.
*/ */
nulls[9] = true; nulls[9] = true;
values[10] = DatumGetInt32(-1); nulls[10] = true;
values[11] = DatumGetInt32(-1);
} }
else else
{ {
/* Unknown address type, should never happen */ /* Unknown address type, should never happen */
nulls[9] = true; nulls[9] = true;
nulls[10] = true; nulls[10] = true;
nulls[11] = true;
} }
} }
} }
...@@ -709,6 +718,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -709,6 +718,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[8] = true; nulls[8] = true;
nulls[9] = true; nulls[9] = true;
nulls[10] = true; nulls[10] = true;
nulls[11] = true;
} }
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201102161 #define CATALOG_VERSION_NO 201102171
#endif #endif
...@@ -3073,7 +3073,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 f f ...@@ -3073,7 +3073,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 f f
DESCR("statistics: number of auto analyzes for a table"); DESCR("statistics: number of auto analyzes for a table");
DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ )); DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 0 f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ ));
DESCR("statistics: currently active backend IDs"); DESCR("statistics: currently active backend IDs");
DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,23}" "{i,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ )); DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
DESCR("statistics: information about currently active backends"); DESCR("statistics: information about currently active backends");
DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25}" "{o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,apply_location}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ )); DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25}" "{o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,apply_location}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
DESCR("statistics: information about currently active replication"); DESCR("statistics: information about currently active replication");
......
...@@ -628,6 +628,7 @@ typedef struct PgBackendStatus ...@@ -628,6 +628,7 @@ typedef struct PgBackendStatus
Oid st_databaseid; Oid st_databaseid;
Oid st_userid; Oid st_userid;
SockAddr st_clientaddr; SockAddr st_clientaddr;
char *st_clienthostname; /* MUST be null-terminated */
/* Is backend currently waiting on an lmgr lock? */ /* Is backend currently waiting on an lmgr lock? */
bool st_waiting; bool st_waiting;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment