Commit 4744c1a0 authored by Neil Conway's avatar Neil Conway

Complete the following TODO items:

* Add session start time to pg_stat_activity
* Add the client IP address and port to pg_stat_activity

Original patch from Magnus Hagander, code review by Neil Conway. Catalog
version bumped. This patch sends the client IP address and port number in
every statistics message; that's not ideal, but will be fixed up shortly.
parent d8c21181
<!--
$PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.27 2004/12/28 19:08:58 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/monitoring.sgml,v 1.28 2005/05/09 11:31:32 neilc Exp $
-->
<chapter id="monitoring">
......@@ -221,15 +221,16 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<row>
<entry><structname>pg_stat_activity</></entry>
<entry>One row per server process, showing process
<acronym>ID</>, database, user, current query, and the time at
which the current query began execution. The columns that report
data on the current query are only available if the parameter
<varname>stats_command_string</varname> has been turned on.
Furthermore, these columns read as null unless the user examining
the view is a superuser or the same as the user owning the process
being reported on. (Note that because of the
collector's reporting delay, current query will only be up-to-date for
long-running queries.)</entry>
<acronym>ID</>, database, user, current query, the time at which
the current query began execution, the time at which the backend
was started and the client address and port number. The columns
that report data on the current query are only available if the
parameter <varname>stats_command_string</varname> has been
turned on. Furthermore, these columns read as null unless the
user examining the view is a superuser or the same as the user
owning the process being reported on. (Note that because of the
collector's reporting delay, the current query will only be
up-to-date for long-running queries.)</entry>
</row>
<row>
......@@ -509,7 +510,7 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<entry><type>set of integer</type></entry>
<entry>
Set of currently active backend process IDs (from 1 to the
number of active backend processes). See usage example in the text.
number of active backend processes). See usage example in the text
</entry>
</row>
......@@ -568,6 +569,38 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
</entry>
</row>
<row>
<entry><literal><function>pg_stat_get_backend_start</function>(<type>integer</type>)</literal></entry>
<entry><type>timestamp with time zone</type></entry>
<entry>
The time at which the given backend process was started, or
null if the current user is not a superuser nor the same user
as that of the session being queried
</entry>
</row>
<row>
<entry><literal><function>pg_stat_get_backend_client_addr</function>(<type>integer</type>)</literal></entry>
<entry><type>inet</type></entry>
<entry>
The IP address of the client connected to the given
backend. Null if the connection is over a Unix domain
socket. Also null if the current user is not a superuser nor
the same user as that of the session being queried
</entry>
</row>
<row>
<entry><literal><function>pg_stat_get_backend_client_port</function>(<type>integer</type>)</literal></entry>
<entry><type>integer</type></entry>
<entry>
The IP port number of the client connected to the given
backend. -1 if the connection is over a Unix domain
socket. Null if the current user is not a superuser nor the
same user as that of the session being queried
</entry>
</row>
<row>
<entry><literal><function>pg_stat_reset</function>()</literal></entry>
<entry><type>boolean</type></entry>
......
......@@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.11 2005/01/01 20:44:14 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.12 2005/05/09 11:31:32 neilc Exp $
*/
CREATE VIEW pg_user AS
......@@ -237,7 +237,10 @@ CREATE VIEW pg_stat_activity AS
pg_stat_get_backend_userid(S.backendid) AS usesysid,
U.usename AS usename,
pg_stat_get_backend_activity(S.backendid) AS current_query,
pg_stat_get_backend_activity_start(S.backendid) AS query_start
pg_stat_get_backend_activity_start(S.backendid) AS query_start,
pg_stat_get_backend_start(S.backendid) AS backend_start,
pg_stat_get_backend_client_addr(S.backendid) AS client_addr,
pg_stat_get_backend_client_port(S.backendid) AS client_port
FROM pg_database D,
(SELECT pg_stat_get_backend_idset() AS backendid) AS S,
pg_shadow U
......
......@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.92 2005/04/14 20:32:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.93 2005/05/09 11:31:33 neilc Exp $
* ----------
*/
#include "postgres.h"
......@@ -1300,6 +1300,7 @@ pgstat_setheader(PgStat_MsgHdr *hdr, int mtype)
hdr->m_procpid = MyProcPid;
hdr->m_databaseid = MyDatabaseId;
hdr->m_userid = GetSessionUserId();
memcpy(&hdr->m_clientaddr, &MyProcPort->raddr, sizeof(hdr->m_clientaddr));
}
......@@ -2032,12 +2033,15 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
beentry->databaseid = msg->m_databaseid;
beentry->procpid = msg->m_procpid;
beentry->userid = msg->m_userid;
beentry->start_sec =
GetCurrentAbsoluteTimeUsec(&beentry->start_usec);
beentry->activity_start_sec = 0;
beentry->activity_start_usec = 0;
memcpy(&beentry->clientaddr, &msg->m_clientaddr, sizeof(beentry->clientaddr));
MemSet(beentry->activity, 0, PGSTAT_ACTIVITY_SIZE);
/*
* Lookup or create the database entry for this backends DB.
* Lookup or create the database entry for this backend's DB.
*/
dbentry = (PgStat_StatDBEntry *) hash_search(pgStatDBHash,
(void *) &(msg->m_databaseid),
......@@ -2072,9 +2076,7 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
HASH_ELEM | HASH_FUNCTION);
}
/*
* Count number of connects to the database
*/
/* Count the number of connects to the database */
dbentry->n_connects++;
return 0;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.20 2004/12/31 22:01:22 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.21 2005/05/09 11:31:33 neilc Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -22,6 +22,9 @@
#include "nodes/execnodes.h"
#include "pgstat.h"
#include "utils/hsearch.h"
#include "utils/inet.h"
#include "utils/builtins.h"
#include "libpq/ip.h"
/* bogus ... these externs should be in a header file */
extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
......@@ -41,6 +44,9 @@ extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
......@@ -357,6 +363,117 @@ pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
PG_RETURN_TIMESTAMPTZ(result);
}
Datum
pg_stat_get_backend_start(PG_FUNCTION_ARGS)
{
PgStat_StatBeEntry *beentry;
int32 beid;
AbsoluteTime sec;
int usec;
TimestampTz result;
beid = PG_GETARG_INT32(0);
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
PG_RETURN_NULL();
if (!superuser() && beentry->userid != GetUserId())
PG_RETURN_NULL();
sec = beentry->start_sec;
usec = beentry->start_usec;
if (sec == 0 && usec == 0)
PG_RETURN_NULL();
result = AbsoluteTimeUsecToTimestampTz(sec, usec);
PG_RETURN_TIMESTAMPTZ(result);
}
Datum
pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
{
PgStat_StatBeEntry *beentry;
int32 beid;
char remote_host[NI_MAXHOST];
int ret;
beid = PG_GETARG_INT32(0);
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
PG_RETURN_NULL();
if (!superuser() && beentry->userid != GetUserId())
PG_RETURN_NULL();
switch (beentry->clientaddr.addr.ss_family)
{
case AF_INET:
#ifdef HAVE_IPV6
case AF_INET6:
#endif
break;
default:
PG_RETURN_NULL();
}
remote_host[0] = '\0';
ret = getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
remote_host, sizeof(remote_host),
NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV);
if (ret)
PG_RETURN_NULL();
PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host)));
}
Datum
pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
{
PgStat_StatBeEntry *beentry;
int32 beid;
char remote_port[NI_MAXSERV];
int ret;
beid = PG_GETARG_INT32(0);
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
PG_RETURN_NULL();
if (!superuser() && beentry->userid != GetUserId())
PG_RETURN_NULL();
switch (beentry->clientaddr.addr.ss_family)
{
case AF_INET:
#ifdef HAVE_IPV6
case AF_INET6:
#endif
break;
case AF_UNIX:
PG_RETURN_INT32(-1);
default:
PG_RETURN_NULL();
}
remote_port[0] = '\0';
ret = getnameinfo_all(&beentry->clientaddr.addr,
beentry->clientaddr.salen,
NULL, 0,
remote_port, sizeof(remote_port),
NI_NUMERICHOST | NI_NUMERICSERV);
if (ret)
PG_RETURN_NULL();
PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
}
Datum
pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
......
......@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.266 2005/04/30 20:31:37 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.267 2005/05/09 11:31:34 neilc Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200504301
#define CATALOG_VERSION_NO 200505091
#endif
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.360 2005/04/30 20:31:38 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.361 2005/05/09 11:31:34 neilc Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -2822,6 +2822,12 @@ DATA(insert OID = 1940 ( pg_stat_get_backend_activity PGNSP PGUID 12 f f t f s
DESCR("Statistics: Current query of backend");
DATA(insert OID = 2094 ( pg_stat_get_backend_activity_start PGNSP PGUID 12 f f t f s 1 1184 "23" _null_ _null_ _null_ pg_stat_get_backend_activity_start - _null_));
DESCR("Statistics: Start time for current query of backend");
DATA(insert OID = 1391 ( pg_stat_get_backend_start PGNSP PGUID 12 f f t f s 1 1184 "23" _null_ _null_ _null_ pg_stat_get_backend_start - _null_));
DESCR("Statistics: Start time for current backend session");
DATA(insert OID = 1392 ( pg_stat_get_backend_client_addr PGNSP PGUID 12 f f t f s 1 869 "23" _null_ _null_ _null_ pg_stat_get_backend_client_addr - _null_));
DESCR("Statistics: Address of client connected to backend");
DATA(insert OID = 1393 ( pg_stat_get_backend_client_port PGNSP PGUID 12 f f t f s 1 23 "23" _null_ _null_ _null_ pg_stat_get_backend_client_port - _null_));
DESCR("Statistics: Port number of client connected to backend");
DATA(insert OID = 1941 ( pg_stat_get_db_numbackends PGNSP PGUID 12 f f t f s 1 23 "26" _null_ _null_ _null_ pg_stat_get_db_numbackends - _null_ ));
DESCR("Statistics: Number of backends in database");
DATA(insert OID = 1942 ( pg_stat_get_db_xact_commit PGNSP PGUID 12 f f t f s 1 20 "26" _null_ _null_ _null_ pg_stat_get_db_xact_commit - _null_ ));
......
......@@ -5,17 +5,17 @@
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.27 2005/01/01 05:43:08 momjian Exp $
* $PostgreSQL: pgsql/src/include/pgstat.h,v 1.28 2005/05/09 11:31:33 neilc Exp $
* ----------
*/
#ifndef PGSTAT_H
#define PGSTAT_H
#include "libpq/pqcomm.h"
#include "utils/hsearch.h"
#include "utils/nabstime.h"
#include "utils/rel.h"
/* ----------
* The types of backend/postmaster -> collector messages
* ----------
......@@ -54,6 +54,7 @@ typedef struct PgStat_MsgHdr
int m_procpid;
Oid m_databaseid;
AclId m_userid;
SockAddr m_clientaddr;
} PgStat_MsgHdr;
/* ----------
......@@ -231,8 +232,11 @@ typedef struct PgStat_StatBeEntry
Oid databaseid;
Oid userid;
int procpid;
AbsoluteTime start_sec;
int start_usec;
AbsoluteTime activity_start_sec;
int activity_start_usec;
SockAddr clientaddr;
char activity[PGSTAT_ACTIVITY_SIZE];
} PgStat_StatBeEntry;
......
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