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
<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>
......
......@@ -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);
}
......
......@@ -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);
......
This diff is collapsed.
......@@ -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"
......
......@@ -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
......
......@@ -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
......
......@@ -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 */
if (beentry->st_databaseid != InvalidOid)
values[0] = ObjectIdGetDatum(beentry->st_databaseid);
else
nulls[0] = true;
values[1] = Int32GetDatum(beentry->st_procpid);
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);
......
......@@ -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;
}
......
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201703242
#define CATALOG_VERSION_NO 201703261
#endif
......@@ -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");
......
......@@ -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);
......
......@@ -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);
......
......@@ -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,
......
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