diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-03-26 22:02:22 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-03-26 22:02:22 -0400 |
commit | fc70a4b0df38bda6a13941f1581f25fbb643c7f3 (patch) | |
tree | 87ee4eec5f4bc96bacad8e8c5313abc5f9c3f367 /src/backend/postmaster/pgstat.c | |
parent | 2f0903ea196503fc8af373a9de46b1e01a23508c (diff) | |
download | postgresql-fc70a4b0df38bda6a13941f1581f25fbb643c7f3.tar.gz postgresql-fc70a4b0df38bda6a13941f1581f25fbb643c7f3.zip |
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
Diffstat (limited to 'src/backend/postmaster/pgstat.c')
-rw-r--r-- | src/backend/postmaster/pgstat.c | 194 |
1 files changed, 169 insertions, 25 deletions
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index b704788eb5a..869afd4c4a5 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -50,6 +50,7 @@ #include "postmaster/autovacuum.h" #include "postmaster/fork_process.h" #include "postmaster/postmaster.h" +#include "replication/walsender.h" #include "storage/backendid.h" #include "storage/dsm.h" #include "storage/fd.h" @@ -103,6 +104,18 @@ /* ---------- + * 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 * ---------- */ @@ -212,7 +225,11 @@ typedef struct TwoPhasePgStatRecord */ static MemoryContext pgStatLocalContext = NULL; static HTAB *pgStatDBHash = NULL; + +/* Status for backends including auxiliary */ static LocalPgBackendStatus *localBackendStatusTable = NULL; + +/* Total number of backends including auxiliary */ static int localNumBackends = 0; /* @@ -2505,20 +2522,20 @@ BackendStatusShmemSize(void) Size size; /* BackendStatusArray: */ - size = mul_size(sizeof(PgBackendStatus), MaxBackends); + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); /* BackendAppnameBuffer: */ size = add_size(size, - mul_size(NAMEDATALEN, MaxBackends)); + mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendClientHostnameBuffer: */ size = add_size(size, - mul_size(NAMEDATALEN, MaxBackends)); + mul_size(NAMEDATALEN, NumBackendStatSlots)); /* BackendActivityBuffer: */ size = add_size(size, - mul_size(pgstat_track_activity_query_size, MaxBackends)); + mul_size(pgstat_track_activity_query_size, NumBackendStatSlots)); #ifdef USE_SSL /* BackendSslStatusBuffer: */ size = add_size(size, - mul_size(sizeof(PgBackendSSLStatus), MaxBackends)); + mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots)); #endif return size; } @@ -2536,7 +2553,7 @@ CreateSharedBackendStatus(void) char *buffer; /* Create or attach to the shared array */ - size = mul_size(sizeof(PgBackendStatus), MaxBackends); + size = mul_size(sizeof(PgBackendStatus), NumBackendStatSlots); BackendStatusArray = (PgBackendStatus *) ShmemInitStruct("Backend Status Array", size, &found); @@ -2559,7 +2576,7 @@ CreateSharedBackendStatus(void) /* Initialize st_appname pointers. */ buffer = BackendAppnameBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_appname = buffer; buffer += NAMEDATALEN; @@ -2577,7 +2594,7 @@ CreateSharedBackendStatus(void) /* Initialize st_clienthostname pointers. */ buffer = BackendClientHostnameBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_clienthostname = buffer; buffer += NAMEDATALEN; @@ -2586,7 +2603,7 @@ CreateSharedBackendStatus(void) /* Create or attach to the shared activity buffer */ BackendActivityBufferSize = mul_size(pgstat_track_activity_query_size, - MaxBackends); + NumBackendStatSlots); BackendActivityBuffer = (char *) ShmemInitStruct("Backend Activity Buffer", BackendActivityBufferSize, @@ -2598,7 +2615,7 @@ CreateSharedBackendStatus(void) /* Initialize st_activity pointers. */ buffer = BackendActivityBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_activity = buffer; buffer += pgstat_track_activity_query_size; @@ -2607,7 +2624,7 @@ CreateSharedBackendStatus(void) #ifdef USE_SSL /* Create or attach to the shared SSL status buffer */ - size = mul_size(sizeof(PgBackendSSLStatus), MaxBackends); + size = mul_size(sizeof(PgBackendSSLStatus), NumBackendStatSlots); BackendSslStatusBuffer = (PgBackendSSLStatus *) ShmemInitStruct("Backend SSL Status Buffer", size, &found); @@ -2619,7 +2636,7 @@ CreateSharedBackendStatus(void) /* Initialize st_sslstatus pointers. */ ptr = BackendSslStatusBuffer; - for (i = 0; i < MaxBackends; i++) + for (i = 0; i < NumBackendStatSlots; i++) { BackendStatusArray[i].st_sslstatus = ptr; ptr++; @@ -2633,7 +2650,8 @@ CreateSharedBackendStatus(void) * pgstat_initialize() - * * 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 * exit hook must run after the last transaction exit). * NOTE: MyDatabaseId isn't set yet; so the shutdown hook has to be careful. @@ -2643,8 +2661,26 @@ void pgstat_initialize(void) { /* Initialize MyBEEntry */ - Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); - MyBEEntry = &BackendStatusArray[MyBackendId - 1]; + if (MyBackendId != InvalidBackendId) + { + Assert(MyBackendId >= 1 && MyBackendId <= MaxBackends); + 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 */ on_shmem_exit(pgstat_beshutdown_hook, 0); @@ -2655,15 +2691,16 @@ pgstat_initialize(void) * * Initialize this backend's entry in the PgBackendStatus array. * 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 pgstat_bestart(void) { TimestampTz proc_start_timestamp; - Oid userid; SockAddr clientaddr; volatile PgBackendStatus *beentry; @@ -2678,7 +2715,6 @@ pgstat_bestart(void) proc_start_timestamp = MyProcPort->SessionStartTime; else proc_start_timestamp = GetCurrentTimestamp(); - userid = GetSessionUserId(); /* * We may not have a MyProcPort (eg, if this is the autovacuum process). @@ -2697,6 +2733,66 @@ pgstat_bestart(void) * cute. */ 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 { pgstat_increment_changecount_before(beentry); @@ -2708,7 +2804,15 @@ pgstat_bestart(void) beentry->st_state_start_timestamp = 0; beentry->st_xact_start_timestamp = 0; 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; if (MyProcPort && MyProcPort->remote_hostname) strlcpy(beentry->st_clienthostname, MyProcPort->remote_hostname, @@ -3046,24 +3150,24 @@ pgstat_read_current_status(void) localtable = (LocalPgBackendStatus *) MemoryContextAlloc(pgStatLocalContext, - sizeof(LocalPgBackendStatus) * MaxBackends); + sizeof(LocalPgBackendStatus) * NumBackendStatSlots); localappname = (char *) MemoryContextAlloc(pgStatLocalContext, - NAMEDATALEN * MaxBackends); + NAMEDATALEN * NumBackendStatSlots); localactivity = (char *) MemoryContextAlloc(pgStatLocalContext, - pgstat_track_activity_query_size * MaxBackends); + pgstat_track_activity_query_size * NumBackendStatSlots); #ifdef USE_SSL localsslstatus = (PgBackendSSLStatus *) MemoryContextAlloc(pgStatLocalContext, - sizeof(PgBackendSSLStatus) * MaxBackends); + sizeof(PgBackendSSLStatus) * NumBackendStatSlots); #endif localNumBackends = 0; beentry = BackendStatusArray; 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 @@ -3829,7 +3933,47 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen) 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 * ------------------------------------------------------------ |