]> granicus.if.org Git - postgresql/commitdiff
Show more processes in pg_stat_activity.
authorRobert Haas <rhaas@postgresql.org>
Mon, 27 Mar 2017 02:02:22 +0000 (22:02 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 27 Mar 2017 02:02:22 +0000 (22:02 -0400)
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

14 files changed:
doc/src/sgml/monitoring.sgml
src/backend/bootstrap/bootstrap.c
src/backend/catalog/system_views.sql
src/backend/postmaster/pgstat.c
src/backend/postmaster/startup.c
src/backend/replication/walsender.c
src/backend/storage/lmgr/proc.c
src/backend/utils/adt/pgstatfuncs.c
src/backend/utils/init/postinit.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/pgstat.h
src/include/storage/proc.h
src/test/regress/expected/rules.out

index e930731b1628e102731bd43ea9213981bd18a2eb..9856968997e84f2f7d8caf421e87e227b9670599 100644 (file)
@@ -620,8 +620,8 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
     <row>
      <entry><structfield>backend_start</></entry>
      <entry><type>timestamp with time zone</></entry>
-     <entry>Time when this process was started, i.e., when the
-      client connected to the server
+     <entry>Time when this process was started.  For client backends,
+      this is the time the client connected to the server.
      </entry>
     </row>
     <row>
@@ -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">.
      </entry>
     </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>
    </tgroup>
   </table>
index 6cfce4f8ddb0f897e1b211f9f95e2525cc55a282..d8efdb5ed3d1a98dc6b714a4030b517747ab3d40 100644 (file)
@@ -387,6 +387,10 @@ AuxiliaryProcessMain(int argc, char *argv[])
                /* finish setting up bufmgr.c */
                InitBufferPoolBackend();
 
+               /* Initialize backend status information */
+               pgstat_initialize();
+               pgstat_bestart();
+
                /* register a before-shutdown callback for LWLock cleanup */
                before_shmem_exit(ShutdownAuxiliaryProcess, 0);
        }
index d8b762ee3fb62dece6cf3e746ef3dc2ce5894e62..d357c8b8fdbeadbe90a1cdc48500730140af77e0 100644 (file)
@@ -716,7 +716,8 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
-            S.query
+            S.query,
+            S.backend_type
     FROM pg_stat_get_activity(NULL) AS S
         LEFT JOIN pg_database AS D ON (S.datid = D.oid)
         LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
index b704788eb5a1b85f172c6daf88b65fb04f5578d8..869afd4c4a5703d0df70542acf24f9d82f8fc9f4 100644 (file)
@@ -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"
 #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
  * ----------
@@ -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
  * ------------------------------------------------------------
index b172b5e5d787a0c2a4a2e476229b2da1f81817e5..b62325247500b227fbfa3cca75da8bb7b987ff7f 100644 (file)
@@ -25,6 +25,7 @@
 #include "access/xlog.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "postmaster/startup.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
index 040ad7b7371ebd9f38db921ce384afdc60b9c543..cfc3fba1b7ddd686ca400815dc8cdb41aff3e4ed 100644 (file)
@@ -2011,8 +2011,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
        last_reply_timestamp = GetCurrentTimestamp();
        waiting_for_ping_response = false;
 
-       /* Report to pgstat that this process is a WAL sender */
-       pgstat_report_activity(STATE_RUNNING, "walsender");
+       /* Report to pgstat that this process is running */
+       pgstat_report_activity(STATE_RUNNING, NULL);
 
        /*
         * Loop until we reach the end of this timeline or the client requests to
index 8f467bef504b66b45ca5790da234687df0798e96..3e716b1c6c7280038b457a5b355e96e61c7982b6 100644 (file)
@@ -941,6 +941,33 @@ AuxiliaryProcKill(int code, Datum arg)
        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
index a987d0d62143a629491b3878d6389fdc220f5e6b..dd2b924d0af355babeeb2844e71c56372e34e7e9 100644 (file)
@@ -20,6 +20,7 @@
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "postmaster/postmaster.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
 #include "utils/acl.h"
@@ -538,7 +539,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
 Datum
 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                     curr_backend;
        int                     pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -582,8 +583,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                LocalPgBackendStatus *local_beentry;
                PgBackendStatus *beentry;
                PGPROC     *proc;
-               const char *wait_event_type;
-               const char *wait_event;
+               const char *wait_event_type = NULL;
+               const char *wait_event = NULL;
 
                MemSet(values, 0, sizeof(values));
                MemSet(nulls, 0, sizeof(nulls));
@@ -615,9 +616,18 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                        continue;
 
                /* Values available to all callers */
-               values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+               if (beentry->st_databaseid != InvalidOid)
+                       values[0] = ObjectIdGetDatum(beentry->st_databaseid);
+               else
+                       nulls[0] = true;
+
                values[1] = Int32GetDatum(beentry->st_procpid);
-               values[2] = ObjectIdGetDatum(beentry->st_userid);
+
+               if (beentry->st_userid != InvalidOid)
+                       values[2] = ObjectIdGetDatum(beentry->st_userid);
+               else
+                       nulls[2] = true;
+
                if (beentry->st_appname)
                        values[3] = CStringGetTextDatum(beentry->st_appname);
                else
@@ -635,17 +645,17 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 
                if (beentry->st_ssl)
                {
-                       values[17] = BoolGetDatum(true);        /* ssl */
-                       values[18] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
-                       values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
-                       values[20] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
-                       values[21] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
-                       values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
+                       values[18] = BoolGetDatum(true);        /* ssl */
+                       values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
+                       values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
+                       values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
+                       values[22] = BoolGetDatum(beentry->st_sslstatus->ssl_compression);
+                       values[23] = CStringGetTextDatum(beentry->st_sslstatus->ssl_clientdn);
                }
                else
                {
-                       values[17] = BoolGetDatum(false);       /* ssl */
-                       nulls[18] = nulls[19] = nulls[20] = nulls[21] = nulls[22] = true;
+                       values[18] = BoolGetDatum(false);       /* ssl */
+                       nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = true;
                }
 
                /* Values only available to role member */
@@ -690,10 +700,24 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                                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)
@@ -793,6 +817,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                                        nulls[14] = true;
                                }
                        }
+                       /* Add backend type */
+                       values[17] =
+                               CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
                }
                else
                {
@@ -808,6 +835,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
                        nulls[12] = true;
                        nulls[13] = true;
                        nulls[14] = true;
+                       nulls[17] = true;
                }
 
                tuplestore_putvalues(tupstore, tupdesc, values, nulls);
index 9f938f2d2707a1af74a64739e14bc8ef6e05c170..b8b4a06350c50858c66a41f6d70b46e74303c0a4 100644 (file)
@@ -665,7 +665,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 
        /* The autovacuum launcher is done here */
        if (IsAutoVacuumLauncherProcess())
+       {
+               /* report this backend in the PgBackendStatus array */
+               pgstat_bestart();
+
                return;
+       }
 
        /*
         * 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,
                 * transaction we started before returning.
                 */
                if (!bootstrap)
+               {
+                       pgstat_bestart();
                        CommitTransactionCommand();
+               }
                return;
        }
 
index b8fa18ae2ea024842202fb5bf278d1daf40350ab..fc374d79c8b6f2345525dca038523f18f91fa533 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201703242
+#define CATALOG_VERSION_NO     201703261
 
 #endif
index ee67459c32efb2bff87600e171a33f7666724702..79f9b9012e2bdbd173c40f5299f12a4f5fc662a8 100644 (file)
@@ -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");
 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");
-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");
 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");
index 201562521f7743ff92eae0016e80b3243d572da9..e29397f25b83202b7e1a037d6b9371e913512fa3 100644 (file)
@@ -695,6 +695,25 @@ typedef struct 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
  * ----------
@@ -927,6 +946,9 @@ typedef struct PgBackendSSLStatus
  * showing its current activity.  (The structs are allocated according to
  * BackendId, but that is not critical.)  Note that the collector process
  * has no involvement in, or even access to, these structs.
+ *
+ * Each auxiliary process also maintains a PgBackendStatus struct in shared
+ * memory.
  * ----------
  */
 typedef struct PgBackendStatus
@@ -951,6 +973,9 @@ typedef struct PgBackendStatus
        /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
        int                     st_procpid;
 
+       /* Type of backends */
+       BackendType st_backendType;
+
        /* Times when current backend, transaction, and activity started */
        TimestampTz st_proc_start_timestamp;
        TimestampTz st_xact_start_timestamp;
@@ -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_crashed_backend_activity(int pid, char *buffer,
                                                                        int buflen);
+extern const char *pgstat_get_backend_desc(BackendType backendType);
 
 extern void pgstat_progress_start_command(ProgressCommandType cmdtype,
                                                          Oid relid);
index 1b345faa2dcbba9bf62711baff878bfb722f0e98..1a125d83f4083904e5d69d21415736b8d46a8275 100644 (file)
@@ -272,7 +272,6 @@ extern PGPROC *PreparedXactProcs;
  */
 #define NUM_AUXILIARY_PROCS            4
 
-
 /* configurable options */
 extern int     DeadlockTimeout;
 extern int     StatementTimeout;
@@ -309,6 +308,8 @@ extern void LockErrorCleanup(void);
 extern void ProcWaitForSignal(uint32 wait_event_info);
 extern void ProcSendSignal(int pid);
 
+extern PGPROC *AuxiliaryPidGetProc(int pid);
+
 extern void BecomeLockGroupLeader(void);
 extern bool BecomeLockGroupMember(PGPROC *leader, int pid);
 
index e8f8726c5377c2b26df131cc9f35204672e248d6..71121c8663464ddef09100b884df5dbb6f889b1b 100644 (file)
@@ -1727,8 +1727,9 @@ pg_stat_activity| SELECT s.datid,
     s.state,
     s.backend_xid,
     s.backend_xmin,
-    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.query,
+    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_authid u ON ((s.usesysid = u.oid)));
 pg_stat_all_indexes| SELECT c.oid AS relid,
@@ -1859,7 +1860,7 @@ pg_stat_replication| SELECT s.pid,
     w.replay_lag,
     w.sync_priority,
     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)))
      LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
 pg_stat_ssl| SELECT s.pid,
@@ -1869,7 +1870,7 @@ pg_stat_ssl| SELECT s.pid,
     s.sslbits AS bits,
     s.sslcompression AS compression,
     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,
     su.subname,
     st.pid,