Commit fc70a4b0 authored by Robert Haas's avatar Robert Haas

Show more processes in pg_stat_activity.

Previously, auxiliary processes and background workers not connected
to a database (such as the logical replication launcher) weren't
shown.  Include them, so that we can see the associated wait state
information.  Add a new column to identify the processes type, so that
people can filter them out easily using SQL if they wish.

Before this patch was written, there was discussion about whether we
should expose this information in a separate view, so as to avoid
contaminating pg_stat_activity with things people might not want to
see.  But putting everything in pg_stat_activity was a more popular
choice, so that's what the patch does.

Kuntal Ghosh, reviewed by Amit Langote and Michael Paquier.  Some
revisions and bug fixes by me.

Discussion: http://postgr.es/m/CA+TgmoYES5nhkEGw9nZXU8_FhA8XEm8NTm3-SO+3ML1B81Hkww@mail.gmail.com
parent 2f0903ea
...@@ -620,8 +620,8 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser ...@@ -620,8 +620,8 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<row> <row>
<entry><structfield>backend_start</></entry> <entry><structfield>backend_start</></entry>
<entry><type>timestamp with time zone</></entry> <entry><type>timestamp with time zone</></entry>
<entry>Time when this process was started, i.e., when the <entry>Time when this process was started. For client backends,
client connected to the server this is the time the client connected to the server.
</entry> </entry>
</row> </row>
<row> <row>
...@@ -797,6 +797,17 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser ...@@ -797,6 +797,17 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<xref linkend="guc-track-activity-query-size">. <xref linkend="guc-track-activity-query-size">.
</entry> </entry>
</row> </row>
<row>
<entry><structfield>backend_type</structfield></entry>
<entry><type>text</type></entry>
<entry>Type of current backend. Possible types are
<literal>autovacuum launcher</>, <literal>autovacuum worker</>,
<literal>background worker</>, <literal>background writer</>,
<literal>client backend</>, <literal>checkpointer</>,
<literal>startup</>, <literal>walreceiver</>,
<literal>walsender</> and <literal>walwriter</>.
</entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
......
...@@ -387,6 +387,10 @@ AuxiliaryProcessMain(int argc, char *argv[]) ...@@ -387,6 +387,10 @@ AuxiliaryProcessMain(int argc, char *argv[])
/* finish setting up bufmgr.c */ /* finish setting up bufmgr.c */
InitBufferPoolBackend(); InitBufferPoolBackend();
/* Initialize backend status information */
pgstat_initialize();
pgstat_bestart();
/* register a before-shutdown callback for LWLock cleanup */ /* register a before-shutdown callback for LWLock cleanup */
before_shmem_exit(ShutdownAuxiliaryProcess, 0); before_shmem_exit(ShutdownAuxiliaryProcess, 0);
} }
......
...@@ -716,7 +716,8 @@ CREATE VIEW pg_stat_activity AS ...@@ -716,7 +716,8 @@ CREATE VIEW pg_stat_activity AS
S.state, S.state,
S.backend_xid, S.backend_xid,
s.backend_xmin, s.backend_xmin,
S.query S.query,
S.backend_type
FROM pg_stat_get_activity(NULL) AS S FROM pg_stat_get_activity(NULL) AS S
LEFT JOIN pg_database AS D ON (S.datid = D.oid) LEFT JOIN pg_database AS D ON (S.datid = D.oid)
LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid); LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include "postmaster/autovacuum.h" #include "postmaster/autovacuum.h"
#include "postmaster/fork_process.h" #include "postmaster/fork_process.h"
#include "postmaster/postmaster.h" #include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/backendid.h" #include "storage/backendid.h"
#include "storage/dsm.h" #include "storage/dsm.h"
#include "storage/fd.h" #include "storage/fd.h"
...@@ -102,6 +103,18 @@ ...@@ -102,6 +103,18 @@
#define PGSTAT_FUNCTION_HASH_SIZE 512 #define PGSTAT_FUNCTION_HASH_SIZE 512
/* ----------
* Total number of backends including auxiliary
*
* We reserve a slot for each possible BackendId, plus one for each
* possible auxiliary process type. (This scheme assumes there is not
* more than one of any auxiliary process type at a time.) MaxBackends
* includes autovacuum workers and background workers as well.
* ----------
*/
#define NumBackendStatSlots (MaxBackends + NUM_AUXPROCTYPES)
/* ---------- /* ----------
* GUC parameters * GUC parameters
* ---------- * ----------
...@@ -212,7 +225,11 @@ typedef struct TwoPhasePgStatRecord ...@@ -212,7 +225,11 @@ typedef struct TwoPhasePgStatRecord
*/ */
static MemoryContext pgStatLocalContext = NULL; static MemoryContext pgStatLocalContext = NULL;
static HTAB *pgStatDBHash = NULL; static HTAB *pgStatDBHash = NULL;
/* Status for backends including auxiliary */
static LocalPgBackendStatus *localBackendStatusTable = NULL; static LocalPgBackendStatus *localBackendStatusTable = NULL;
/* Total number of backends including auxiliary */
static int localNumBackends = 0; static int localNumBackends = 0;
/* /*
...@@ -2505,20 +2522,20 @@ BackendStatusShmemSize(void) ...@@ -2505,20 +2522,20 @@ BackendStatusShmemSize(void)
Size size; Size size;
/* BackendStatusArray: */ /* BackendStatusArray: */
size = mul_size(sizeof(PgBackendStatus), MaxBackends); size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
/* BackendAppnameBuffer: */ /* BackendAppnameBuffer: */
size = add_size(size, size = add_size(size,
mul_size(NAMEDATALEN, MaxBackends)); mul_size(NAMEDATALEN, NumBackendStatSlots));
/* BackendClientHostnameBuffer: */ /* BackendClientHostnameBuffer: */
size = add_size(size, size = add_size(size,
mul_size(NAMEDATALEN, MaxBackends)); mul_size(NAMEDATALEN, NumBackendStatSlots));
/* BackendActivityBuffer: */ /* BackendActivityBuffer: */
size = add_size(size, size = add_size(size,
mul_size(pgstat_track_activity_query_size, MaxBackends)); mul_size(pgstat_track_activity_query_size, NumBackendStatSlots));
#ifdef USE_SSL #ifdef USE_SSL
/* BackendSslStatusBuffer: */ /* BackendSslStatusBuffer: */
size = add_size(size, size = add_size(size,
mul_size(sizeof(PgBackendSSLStatus), MaxBackends)); mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots));
#endif #endif
return size; return size;
} }
...@@ -2536,7 +2553,7 @@ CreateSharedBackendStatus(void) ...@@ -2536,7 +2553,7 @@ CreateSharedBackendStatus(void)
char *buffer; char *buffer;
/* Create or attach to the shared array */ /* Create or attach to the shared array */
size = mul_size(sizeof(PgBackendStatus), MaxBackends); size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots);
BackendStatusArray = (PgBackendStatus *) BackendStatusArray = (PgBackendStatus *)
ShmemInitStruct("Backend Status Array", size, &found); ShmemInitStruct("Backend Status Array", size, &found);
...@@ -2559,7 +2576,7 @@ CreateSharedBackendStatus(void) ...@@ -2559,7 +2576,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_appname pointers. */ /* Initialize st_appname pointers. */
buffer = BackendAppnameBuffer; buffer = BackendAppnameBuffer;
for (i = 0; i < MaxBackends; i++) for (i = 0; i < NumBackendStatSlots; i++)
{ {
BackendStatusArray[i].st_appname = buffer; BackendStatusArray[i].st_appname = buffer;
buffer += NAMEDATALEN; buffer += NAMEDATALEN;
...@@ -2577,7 +2594,7 @@ CreateSharedBackendStatus(void) ...@@ -2577,7 +2594,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_clienthostname pointers. */ /* Initialize st_clienthostname pointers. */
buffer = BackendClientHostnameBuffer; buffer = BackendClientHostnameBuffer;
for (i = 0; i < MaxBackends; i++) for (i = 0; i < NumBackendStatSlots; i++)
{ {
BackendStatusArray[i].st_clienthostname = buffer; BackendStatusArray[i].st_clienthostname = buffer;
buffer += NAMEDATALEN; buffer += NAMEDATALEN;
...@@ -2586,7 +2603,7 @@ CreateSharedBackendStatus(void) ...@@ -2586,7 +2603,7 @@ CreateSharedBackendStatus(void)
/* Create or attach to the shared activity buffer */ /* Create or attach to the shared activity buffer */
BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size, BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size,
MaxBackends); NumBackendStatSlots);
BackendActivityBuffer = (char *) BackendActivityBuffer = (char *)
ShmemInitStruct("Backend Activity Buffer", ShmemInitStruct("Backend Activity Buffer",
BackendActivityBufferSize, BackendActivityBufferSize,
...@@ -2598,7 +2615,7 @@ CreateSharedBackendStatus(void) ...@@ -2598,7 +2615,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_activity pointers. */ /* Initialize st_activity pointers. */
buffer = BackendActivityBuffer; buffer = BackendActivityBuffer;
for (i = 0; i < MaxBackends; i++) for (i = 0; i < NumBackendStatSlots; i++)
{ {
BackendStatusArray[i].st_activity = buffer; BackendStatusArray[i].st_activity = buffer;
buffer += pgstat_track_activity_query_size; buffer += pgstat_track_activity_query_size;
...@@ -2607,7 +2624,7 @@ CreateSharedBackendStatus(void) ...@@ -2607,7 +2624,7 @@ CreateSharedBackendStatus(void)
#ifdef USE_SSL #ifdef USE_SSL
/* Create or attach to the shared SSL status buffer */ /* Create or attach to the shared SSL status buffer */
size = mul_size(sizeof(PgBackendSSLStatus), MaxBackends); size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots);
BackendSslStatusBuffer = (PgBackendSSLStatus *) BackendSslStatusBuffer = (PgBackendSSLStatus *)
ShmemInitStruct("Backend SSL Status Buffer", size, &found); ShmemInitStruct("Backend SSL Status Buffer", size, &found);
...@@ -2619,7 +2636,7 @@ CreateSharedBackendStatus(void) ...@@ -2619,7 +2636,7 @@ CreateSharedBackendStatus(void)
/* Initialize st_sslstatus pointers. */ /* Initialize st_sslstatus pointers. */
ptr = BackendSslStatusBuffer; ptr = BackendSslStatusBuffer;
for (i = 0; i < MaxBackends; i++) for (i = 0; i < NumBackendStatSlots; i++)
{ {
BackendStatusArray[i].st_sslstatus = ptr; BackendStatusArray[i].st_sslstatus = ptr;
ptr++; ptr++;
...@@ -2633,7 +2650,8 @@ CreateSharedBackendStatus(void) ...@@ -2633,7 +2650,8 @@ CreateSharedBackendStatus(void)
* pgstat_initialize() - * pgstat_initialize() -
* *
* Initialize pgstats state, and set up our on-proc-exit hook. * Initialize pgstats state, and set up our on-proc-exit hook.
* Called from InitPostgres. MyBackendId must be set, * Called from InitPostgres and AuxiliaryProcessMain. For auxiliary process,
* MyBackendId is invalid. Otherwise, MyBackendId must be set,
* but we must not have started any transaction yet (since the * but we must not have started any transaction yet (since the
* exit hook must run after the last transaction exit). * exit hook must run after the last transaction exit).
* NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful. * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful.
...@@ -2643,8 +2661,26 @@ void ...@@ -2643,8 +2661,26 @@ void
pgstat_initialize(void) pgstat_initialize(void)
{ {
/* Initialize MyBEEntry */ /* Initialize MyBEEntry */
if (MyBackendId != InvalidBackendId)
{
Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends);
MyBEEntry = &BackendStatusArray[MyBackendId - 1]; MyBEEntry = &BackendStatusArray[MyBackendId - 1];
}
else
{
/* Must be an auxiliary process */
Assert(MyAuxProcType != NotAnAuxProcess);
/*
* Assign the MyBEEntry for an auxiliary process. Since it doesn't
* have a BackendId, the slot is statically allocated based on the
* auxiliary process type (MyAuxProcType). Backends use slots indexed
* in the range from 1 to MaxBackends (inclusive), so we use
* MaxBackends + AuxBackendType + 1 as the index of the slot for an
* auxiliary process.
*/
MyBEEntry = &BackendStatusArray[MaxBackends + MyAuxProcType];
}
/* Set up a process-exit hook to clean up */ /* Set up a process-exit hook to clean up */
on_shmem_exit(pgstat_beshutdown_hook, 0); on_shmem_exit(pgstat_beshutdown_hook, 0);
...@@ -2655,15 +2691,16 @@ pgstat_initialize(void) ...@@ -2655,15 +2691,16 @@ pgstat_initialize(void)
* *
* Initialize this backend's entry in the PgBackendStatus array. * Initialize this backend's entry in the PgBackendStatus array.
* Called from InitPostgres. * Called from InitPostgres.
* MyDatabaseId, session userid, and application_name must be set *
* (hence, this cannot be combined with pgstat_initialize). * Apart from auxiliary processes, MyBackendId, MyDatabaseId,
* session userid, and application_name must be set for a
* backend (hence, this cannot be combined with pgstat_initialize).
* ---------- * ----------
*/ */
void void
pgstat_bestart(void) pgstat_bestart(void)
{ {
TimestampTz proc_start_timestamp; TimestampTz proc_start_timestamp;
Oid userid;
SockAddr clientaddr; SockAddr clientaddr;
volatile PgBackendStatus *beentry; volatile PgBackendStatus *beentry;
...@@ -2678,7 +2715,6 @@ pgstat_bestart(void) ...@@ -2678,7 +2715,6 @@ pgstat_bestart(void)
proc_start_timestamp = MyProcPort->SessionStartTime; proc_start_timestamp = MyProcPort->SessionStartTime;
else else
proc_start_timestamp = GetCurrentTimestamp(); proc_start_timestamp = GetCurrentTimestamp();
userid = GetSessionUserId();
/* /*
* We may not have a MyProcPort (eg, if this is the autovacuum process). * We may not have a MyProcPort (eg, if this is the autovacuum process).
...@@ -2697,6 +2733,66 @@ pgstat_bestart(void) ...@@ -2697,6 +2733,66 @@ pgstat_bestart(void)
* cute. * cute.
*/ */
beentry = MyBEEntry; beentry = MyBEEntry;
/* pgstats state must be initialized from pgstat_initialize() */
Assert(beentry != NULL);
if (MyBackendId != InvalidBackendId)
{
if (IsAutoVacuumLauncherProcess())
{
/* Autovacuum Launcher */
beentry->st_backendType = B_AUTOVAC_LAUNCHER;
}
else if (IsAutoVacuumWorkerProcess())
{
/* Autovacuum Worker */
beentry->st_backendType = B_AUTOVAC_WORKER;
}
else if (am_walsender)
{
/* Wal sender */
beentry->st_backendType = B_WAL_SENDER;
}
else if (IsBackgroundWorker)
{
/* bgworker */
beentry->st_backendType = B_BG_WORKER;
}
else
{
/* client-backend */
beentry->st_backendType = B_BACKEND;
}
}
else
{
/* Must be an auxiliary process */
Assert(MyAuxProcType != NotAnAuxProcess);
switch (MyAuxProcType)
{
case StartupProcess:
beentry->st_backendType = B_STARTUP;
break;
case BgWriterProcess:
beentry->st_backendType = B_BG_WRITER;
break;
case CheckpointerProcess:
beentry->st_backendType = B_CHECKPOINTER;
break;
case WalWriterProcess:
beentry->st_backendType = B_WAL_WRITER;
break;
case WalReceiverProcess:
beentry->st_backendType = B_WAL_RECEIVER;
break;
default:
elog(FATAL, "unrecognized process type: %d",
(int) MyAuxProcType);
proc_exit(1);
}
}
do do
{ {
pgstat_increment_changecount_before(beentry); pgstat_increment_changecount_before(beentry);
...@@ -2708,7 +2804,15 @@ pgstat_bestart(void) ...@@ -2708,7 +2804,15 @@ pgstat_bestart(void)
beentry->st_state_start_timestamp = 0; beentry->st_state_start_timestamp = 0;
beentry->st_xact_start_timestamp = 0; beentry->st_xact_start_timestamp = 0;
beentry->st_databaseid = MyDatabaseId; beentry->st_databaseid = MyDatabaseId;
beentry->st_userid = userid;
/* We have userid for client-backends, wal-sender and bgworker processes */
if (beentry->st_backendType == B_BACKEND
|| beentry->st_backendType == B_WAL_SENDER
|| beentry->st_backendType == B_BG_WORKER)
beentry->st_userid = GetSessionUserId();
else
beentry->st_userid = InvalidOid;
beentry->st_clientaddr = clientaddr; beentry->st_clientaddr = clientaddr;
if (MyProcPort && MyProcPort->remote_hostname) if (MyProcPort && MyProcPort->remote_hostname)
strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname,
...@@ -3046,24 +3150,24 @@ pgstat_read_current_status(void) ...@@ -3046,24 +3150,24 @@ pgstat_read_current_status(void)
localtable = (LocalPgBackendStatus *) localtable = (LocalPgBackendStatus *)
MemoryContextAlloc(pgStatLocalContext, MemoryContextAlloc(pgStatLocalContext,
sizeof(LocalPgBackendStatus) * MaxBackends); sizeof(LocalPgBackendStatus) * NumBackendStatSlots);
localappname = (char *) localappname = (char *)
MemoryContextAlloc(pgStatLocalContext, MemoryContextAlloc(pgStatLocalContext,
NAMEDATALEN * MaxBackends); NAMEDATALEN * NumBackendStatSlots);
localactivity = (char *) localactivity = (char *)
MemoryContextAlloc(pgStatLocalContext, MemoryContextAlloc(pgStatLocalContext,
pgstat_track_activity_query_size * MaxBackends); pgstat_track_activity_query_size * NumBackendStatSlots);
#ifdef USE_SSL #ifdef USE_SSL
localsslstatus = (PgBackendSSLStatus *) localsslstatus = (PgBackendSSLStatus *)
MemoryContextAlloc(pgStatLocalContext, MemoryContextAlloc(pgStatLocalContext,
sizeof(PgBackendSSLStatus) * MaxBackends); sizeof(PgBackendSSLStatus) * NumBackendStatSlots);
#endif #endif
localNumBackends = 0; localNumBackends = 0;
beentry = BackendStatusArray; beentry = BackendStatusArray;
localentry = localtable; localentry = localtable;
for (i = 1; i <= MaxBackends; i++) for (i = 1; i <= NumBackendStatSlots; i++)
{ {
/* /*
* Follow the protocol of retrying if st_changecount changes while we * Follow the protocol of retrying if st_changecount changes while we
...@@ -3829,7 +3933,47 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen) ...@@ -3829,7 +3933,47 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
return NULL; return NULL;
} }
const char *
pgstat_get_backend_desc(BackendType backendType)
{
const char *backendDesc = "unknown process type";
switch (backendType)
{
case B_AUTOVAC_LAUNCHER:
backendDesc = "autovacuum launcher";
break;
case B_AUTOVAC_WORKER:
backendDesc = "autovacuum worker";
break;
case B_BACKEND:
backendDesc = "client backend";
break;
case B_BG_WORKER:
backendDesc = "background worker";
break;
case B_BG_WRITER:
backendDesc = "background writer";
break;
case B_CHECKPOINTER:
backendDesc = "checkpointer";
break;
case B_STARTUP:
backendDesc = "startup";
break;
case B_WAL_RECEIVER:
backendDesc = "walreceiver";
break;
case B_WAL_SENDER:
backendDesc = "walsender";
break;
case B_WAL_WRITER:
backendDesc = "walwriter";
break;
}
return backendDesc;
}
/* ------------------------------------------------------------ /* ------------------------------------------------------------
* Local support functions follow * Local support functions follow
* ------------------------------------------------------------ * ------------------------------------------------------------
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "access/xlog.h" #include "access/xlog.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/startup.h" #include "postmaster/startup.h"
#include "storage/ipc.h" #include "storage/ipc.h"
#include "storage/latch.h" #include "storage/latch.h"
......
...@@ -2011,8 +2011,8 @@ WalSndLoop(WalSndSendDataCallback send_data) ...@@ -2011,8 +2011,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
last_reply_timestamp = GetCurrentTimestamp(); last_reply_timestamp = GetCurrentTimestamp();
waiting_for_ping_response = false; waiting_for_ping_response = false;
/* Report to pgstat that this process is a WAL sender */ /* Report to pgstat that this process is running */
pgstat_report_activity(STATE_RUNNING, "walsender"); pgstat_report_activity(STATE_RUNNING, NULL);
/* /*
* Loop until we reach the end of this timeline or the client requests to * Loop until we reach the end of this timeline or the client requests to
......
...@@ -941,6 +941,33 @@ AuxiliaryProcKill(int code, Datum arg) ...@@ -941,6 +941,33 @@ AuxiliaryProcKill(int code, Datum arg)
SpinLockRelease(ProcStructLock); SpinLockRelease(ProcStructLock);
} }
/*
* AuxiliaryPidGetProc -- get PGPROC for an auxiliary process
* given its PID
*
* Returns NULL if not found.
*/
PGPROC *
AuxiliaryPidGetProc(int pid)
{
PGPROC *result = NULL;
int index;
if (pid == 0) /* never match dummy PGPROCs */
return NULL;
for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
{
PGPROC *proc = &AuxiliaryProcs[index];
if (proc->pid == pid)
{
result = proc;
break;
}
}
return result;
}
/* /*
* ProcQueue package: routines for putting processes to sleep * ProcQueue package: routines for putting processes to sleep
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "funcapi.h" #include "funcapi.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "pgstat.h" #include "pgstat.h"
#include "postmaster/postmaster.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/procarray.h" #include "storage/procarray.h"
#include "utils/acl.h" #include "utils/acl.h"
...@@ -538,7 +539,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS) ...@@ -538,7 +539,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
Datum Datum
pg_stat_get_activity(PG_FUNCTION_ARGS) pg_stat_get_activity(PG_FUNCTION_ARGS)
{ {
#define PG_STAT_GET_ACTIVITY_COLS 23 #define PG_STAT_GET_ACTIVITY_COLS 24
int num_backends = pgstat_fetch_stat_numbackends(); int num_backends = pgstat_fetch_stat_numbackends();
int curr_backend; int curr_backend;
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0); int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
...@@ -582,8 +583,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -582,8 +583,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
LocalPgBackendStatus *local_beentry; LocalPgBackendStatus *local_beentry;
PgBackendStatus *beentry; PgBackendStatus *beentry;
PGPROC *proc; PGPROC *proc;
const char *wait_event_type; const char *wait_event_type = NULL;
const char *wait_event; const char *wait_event = NULL;
MemSet(values, 0, sizeof(values)); MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls)); MemSet(nulls, 0, sizeof(nulls));
...@@ -615,9 +616,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -615,9 +616,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
continue; continue;
/* Values available to all callers */ /* Values available to all callers */
if (beentry->st_databaseid != InvalidOid)
values[0] = ObjectIdGetDatum(beentry->st_databaseid); values[0] = ObjectIdGetDatum(beentry->st_databaseid);
else
nulls[0] = true;
values[1] = Int32GetDatum(beentry->st_procpid); values[1] = Int32GetDatum(beentry->st_procpid);
if (beentry->st_userid != InvalidOid)
values[2] = ObjectIdGetDatum(beentry->st_userid); values[2] = ObjectIdGetDatum(beentry->st_userid);
else
nulls[2] = true;
if (beentry->st_appname) if (beentry->st_appname)
values[3] = CStringGetTextDatum(beentry->st_appname); values[3] = CStringGetTextDatum(beentry->st_appname);
else else
...@@ -635,17 +645,17 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -635,17 +645,17 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (beentry->st_ssl) if (beentry->st_ssl)
{ {
values[17] = BoolGetDatum(true); /* ssl */ values[18] = BoolGetDatum(true); /* ssl */
values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version); values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher); values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
values[20] = Int32GetDatum(beentry->st_sslstatus->ssl_bits); values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
values[21] = BoolGetDatum(beentry->st_sslstatus->ssl_compression); values[22] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn); values[23] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
} }
else else
{ {
values[17] = BoolGetDatum(false); /* ssl */ values[18] = BoolGetDatum(false); /* ssl */
nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true; nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = true;
} }
/* Values only available to role member */ /* Values only available to role member */
...@@ -690,10 +700,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -690,10 +700,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
wait_event = pgstat_get_wait_event(raw_wait_event); wait_event = pgstat_get_wait_event(raw_wait_event);
} }
else else if (beentry->st_backendType != B_BACKEND)
{ {
wait_event_type = NULL; /*
wait_event = NULL; * For an auxiliary process, retrieve process info from
* AuxiliaryProcs stored in shared-memory.
*/
proc = AuxiliaryPidGetProc(beentry->st_procpid);
if (proc != NULL)
{
uint32 raw_wait_event;
raw_wait_event =
UINT32_ACCESS_ONCE(proc->wait_event_info);
wait_event_type =
pgstat_get_wait_event_type(raw_wait_event);
wait_event = pgstat_get_wait_event(raw_wait_event);
}
} }
if (wait_event_type) if (wait_event_type)
...@@ -793,6 +817,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -793,6 +817,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[14] = true; nulls[14] = true;
} }
} }
/* Add backend type */
values[17] =
CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
} }
else else
{ {
...@@ -808,6 +835,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS) ...@@ -808,6 +835,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
nulls[12] = true; nulls[12] = true;
nulls[13] = true; nulls[13] = true;
nulls[14] = true; nulls[14] = true;
nulls[17] = true;
} }
tuplestore_putvalues(tupstore, tupdesc, values, nulls); tuplestore_putvalues(tupstore, tupdesc, values, nulls);
......
...@@ -665,7 +665,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, ...@@ -665,7 +665,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
/* The autovacuum launcher is done here */ /* The autovacuum launcher is done here */
if (IsAutoVacuumLauncherProcess()) if (IsAutoVacuumLauncherProcess())
{
/* report this backend in the PgBackendStatus array */
pgstat_bestart();
return; return;
}
/* /*
* Start a new transaction here before first access to db, and get a * Start a new transaction here before first access to db, and get a
...@@ -874,7 +879,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, ...@@ -874,7 +879,10 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
* transaction we started before returning. * transaction we started before returning.
*/ */
if (!bootstrap) if (!bootstrap)
{
pgstat_bestart();
CommitTransactionCommand(); CommitTransactionCommand();
}
return; return;
} }
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201703242 #define CATALOG_VERSION_NO 201703261
#endif #endif
...@@ -2811,7 +2811,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f ...@@ -2811,7 +2811,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 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 0 f f f f t t s r 0 0 23 "" _null_ _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 0 f f f f t t s r 0 0 23 "" _null_ _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 0 f f f f f t s r 1 0 2249 "23" "{23,26,23,26,25,25,25,25,25,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ )); DATA(insert OID = 2022 ( pg_stat_get_activity PGNSP PGUID 12 1 100 0 0 f f f f f t s r 1 0 2249 "23" "{23,26,23,26,25,25,25,25,25,1184,1184,1184,1184,869,25,23,28,28,25,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _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 = 3318 ( pg_stat_get_progress_info PGNSP PGUID 12 1 100 0 0 f f f f t t s r 1 0 2249 "25" "{25,23,26,26,20,20,20,20,20,20,20,20,20,20}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10}" _null_ _null_ pg_stat_get_progress_info _null_ _null_ _null_ )); DATA(insert OID = 3318 ( pg_stat_get_progress_info PGNSP PGUID 12 1 100 0 0 f f f f t t s r 1 0 2249 "25" "{25,23,26,26,20,20,20,20,20,20,20,20,20,20}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{cmdtype,pid,datid,relid,param1,param2,param3,param4,param5,param6,param7,param8,param9,param10}" _null_ _null_ pg_stat_get_progress_info _null_ _null_ _null_ ));
DESCR("statistics: information about progress of backends running maintenance command"); DESCR("statistics: information about progress of backends running maintenance command");
......
...@@ -695,6 +695,25 @@ typedef struct PgStat_GlobalStats ...@@ -695,6 +695,25 @@ typedef struct PgStat_GlobalStats
} PgStat_GlobalStats; } PgStat_GlobalStats;
/* ----------
* Backend types
* ----------
*/
typedef enum BackendType
{
B_AUTOVAC_LAUNCHER,
B_AUTOVAC_WORKER,
B_BACKEND,
B_BG_WORKER,
B_BG_WRITER,
B_CHECKPOINTER,
B_STARTUP,
B_WAL_RECEIVER,
B_WAL_SENDER,
B_WAL_WRITER
} BackendType;
/* ---------- /* ----------
* Backend states * Backend states
* ---------- * ----------
...@@ -927,6 +946,9 @@ typedef struct PgBackendSSLStatus ...@@ -927,6 +946,9 @@ typedef struct PgBackendSSLStatus
* showing its current activity. (The structs are allocated according to * showing its current activity. (The structs are allocated according to
* BackendId, but that is not critical.) Note that the collector process * BackendId, but that is not critical.) Note that the collector process
* has no involvement in, or even access to, these structs. * has no involvement in, or even access to, these structs.
*
* Each auxiliary process also maintains a PgBackendStatus struct in shared
* memory.
* ---------- * ----------
*/ */
typedef struct PgBackendStatus typedef struct PgBackendStatus
...@@ -951,6 +973,9 @@ typedef struct PgBackendStatus ...@@ -951,6 +973,9 @@ typedef struct PgBackendStatus
/* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */ /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
int st_procpid; int st_procpid;
/* Type of backends */
BackendType st_backendType;
/* Times when current backend, transaction, and activity started */ /* Times when current backend, transaction, and activity started */
TimestampTz st_proc_start_timestamp; TimestampTz st_proc_start_timestamp;
TimestampTz st_xact_start_timestamp; TimestampTz st_xact_start_timestamp;
...@@ -1149,6 +1174,7 @@ extern const char *pgstat_get_wait_event_type(uint32 wait_event_info); ...@@ -1149,6 +1174,7 @@ extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser); extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer, extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
int buflen); int buflen);
extern const char *pgstat_get_backend_desc(BackendType backendType);
extern void pgstat_progress_start_command(ProgressCommandType cmdtype, extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
Oid relid); Oid relid);
......
...@@ -272,7 +272,6 @@ extern PGPROC *PreparedXactProcs; ...@@ -272,7 +272,6 @@ extern PGPROC *PreparedXactProcs;
*/ */
#define NUM_AUXILIARY_PROCS 4 #define NUM_AUXILIARY_PROCS 4
/* configurable options */ /* configurable options */
extern int DeadlockTimeout; extern int DeadlockTimeout;
extern int StatementTimeout; extern int StatementTimeout;
...@@ -309,6 +308,8 @@ extern void LockErrorCleanup(void); ...@@ -309,6 +308,8 @@ extern void LockErrorCleanup(void);
extern void ProcWaitForSignal(uint32 wait_event_info); extern void ProcWaitForSignal(uint32 wait_event_info);
extern void ProcSendSignal(int pid); extern void ProcSendSignal(int pid);
extern PGPROC *AuxiliaryPidGetProc(int pid);
extern void BecomeLockGroupLeader(void); extern void BecomeLockGroupLeader(void);
extern bool BecomeLockGroupMember(PGPROC *leader, int pid); extern bool BecomeLockGroupMember(PGPROC *leader, int pid);
......
...@@ -1727,8 +1727,9 @@ pg_stat_activity| SELECT s.datid, ...@@ -1727,8 +1727,9 @@ pg_stat_activity| SELECT s.datid,
s.state, s.state,
s.backend_xid, s.backend_xid,
s.backend_xmin, s.backend_xmin,
s.query s.query,
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) s.backend_type
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn)
LEFT JOIN pg_database d ON ((s.datid = d.oid))) LEFT JOIN pg_database d ON ((s.datid = d.oid)))
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
pg_stat_all_indexes| SELECT c.oid AS relid, pg_stat_all_indexes| SELECT c.oid AS relid,
...@@ -1859,7 +1860,7 @@ pg_stat_replication| SELECT s.pid, ...@@ -1859,7 +1860,7 @@ pg_stat_replication| SELECT s.pid,
w.replay_lag, w.replay_lag,
w.sync_priority, w.sync_priority,
w.sync_state w.sync_state
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn) FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn)
JOIN pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, write_lag, flush_lag, replay_lag, sync_priority, sync_state) ON ((s.pid = w.pid))) JOIN pg_stat_get_wal_senders() w(pid, state, sent_location, write_location, flush_location, replay_location, write_lag, flush_lag, replay_lag, sync_priority, sync_state) ON ((s.pid = w.pid)))
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid))); LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
pg_stat_ssl| SELECT s.pid, pg_stat_ssl| SELECT s.pid,
...@@ -1869,7 +1870,7 @@ pg_stat_ssl| SELECT s.pid, ...@@ -1869,7 +1870,7 @@ pg_stat_ssl| SELECT s.pid,
s.sslbits AS bits, s.sslbits AS bits,
s.sslcompression AS compression, s.sslcompression AS compression,
s.sslclientdn AS clientdn s.sslclientdn AS clientdn
FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn); FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, sslcompression, sslclientdn);
pg_stat_subscription| SELECT su.oid AS subid, pg_stat_subscription| SELECT su.oid AS subid,
su.subname, su.subname,
st.pid, st.pid,
......
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