pg_stat_activity_state_query.patch
application/octet-stream
Filename: pg_stat_activity_state_query.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/catalog/system_views.sql | 2 | 1 |
| src/backend/postmaster/autovacuum.c | 1 | 1 |
| src/backend/postmaster/pgstat.c | 11 | 6 |
| src/backend/tcop/postgres.c | 9 | 8 |
| src/backend/utils/adt/pgstatfuncs.c | 63 | 33 |
| src/include/catalog/pg_proc.h | 1 | 1 |
| src/include/c.h | 5 | 0 |
| src/include/pgstat.h | 4 | 1 |
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 2253ca8..ca34aa8 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -531,7 +531,8 @@ CREATE VIEW pg_stat_activity AS
S.xact_start,
S.query_start,
S.waiting,
- S.current_query
+ S.state,
+ S.query
FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U
WHERE S.datid = D.oid AND
S.usesysid = U.oid;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 3b71232..c2d8080 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2751,7 +2751,7 @@ autovac_report_activity(autovac_table *tab)
/* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp();
- pgstat_report_activity(activity);
+ pgstat_report_activity(STATE_RUNNING,activity);
}
/*
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 24582e3..86b2762 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -2416,6 +2416,7 @@ pgstat_bestart(void)
beentry->st_clientaddr = clientaddr;
beentry->st_clienthostname[0] = '\0';
beentry->st_waiting = false;
+ beentry->st_state=-1;
beentry->st_appname[0] = '\0';
beentry->st_activity[0] = '\0';
/* Also make sure the last byte in each string area is always 0 */
@@ -2479,7 +2480,7 @@ pgstat_beshutdown_hook(int code, Datum arg)
* ----------
*/
void
-pgstat_report_activity(const char *cmd_str)
+pgstat_report_activity(int state, const char *cmd_str)
{
volatile PgBackendStatus *beentry = MyBEEntry;
TimestampTz start_timestamp;
@@ -2496,9 +2497,6 @@ pgstat_report_activity(const char *cmd_str)
*/
start_timestamp = GetCurrentStatementStartTimestamp();
- len = strlen(cmd_str);
- len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
-
/*
* Update my status entry, following the protocol of bumping
* st_changecount before and after. We use a volatile pointer here to
@@ -2507,8 +2505,15 @@ pgstat_report_activity(const char *cmd_str)
beentry->st_changecount++;
beentry->st_activity_start_timestamp = start_timestamp;
- memcpy((char *) beentry->st_activity, cmd_str, len);
- beentry->st_activity[len] = '\0';
+ beentry->st_state = state;
+
+ if ( cmd_str != NULL )
+ {
+ len = strlen(cmd_str);
+ len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
+ memcpy((char *) beentry->st_activity, cmd_str, len);
+ beentry->st_activity[len] = '\0';
+ }
beentry->st_changecount++;
Assert((beentry->st_changecount & 1) == 0);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 976a832..4c1ce60 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -809,7 +809,7 @@ exec_simple_query(const char *query_string)
*/
debug_query_string = query_string;
- pgstat_report_activity(query_string);
+ pgstat_report_activity(STATE_RUNNING,query_string);
TRACE_POSTGRESQL_QUERY_START(query_string);
@@ -1128,7 +1128,7 @@ exec_parse_message(const char *query_string, /* string to execute */
*/
debug_query_string = query_string;
- pgstat_report_activity(query_string);
+ pgstat_report_activity(STATE_RUNNING,query_string);
set_ps_display("PARSE", false);
@@ -1423,7 +1423,7 @@ exec_bind_message(StringInfo input_message)
*/
debug_query_string = psrc->query_string;
- pgstat_report_activity(psrc->query_string);
+ pgstat_report_activity(STATE_RUNNING,psrc->query_string);
set_ps_display("BIND", false);
@@ -1826,7 +1826,7 @@ exec_execute_message(const char *portal_name, long max_rows)
*/
debug_query_string = sourceText;
- pgstat_report_activity(sourceText);
+ pgstat_report_activity(STATE_RUNNING,sourceText);
set_ps_display(portal->commandTag, false);
@@ -3789,12 +3789,12 @@ PostgresMain(int argc, char *argv[], const char *username)
if (IsAbortedTransactionBlockState())
{
set_ps_display("idle in transaction (aborted)", false);
- pgstat_report_activity("<IDLE> in transaction (aborted)");
+ pgstat_report_activity(STATE_IDLEINTRANSACTION_ABRT,NULL);
}
else if (IsTransactionOrTransactionBlock())
{
set_ps_display("idle in transaction", false);
- pgstat_report_activity("<IDLE> in transaction");
+ pgstat_report_activity(STATE_IDLEINTRANSACTION,NULL);
}
else
{
@@ -3802,7 +3802,7 @@ PostgresMain(int argc, char *argv[], const char *username)
pgstat_report_stat(false);
set_ps_display("idle", false);
- pgstat_report_activity("<IDLE>");
+ pgstat_report_activity(STATE_IDLE,NULL);
}
ReadyForQuery(whereToSendOutput);
@@ -3922,7 +3922,8 @@ PostgresMain(int argc, char *argv[], const char *username)
SetCurrentStatementStartTimestamp();
/* Report query to various monitoring facilities. */
- pgstat_report_activity("<FASTPATH> function call");
+// pgstat_report_activity("<FASTPATH> function call");
+ pgstat_report_activity(STATE_FASTPATH,NULL);
set_ps_display("<FASTPATH>", false);
/* start an xact for this function invocation */
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 7792b33..9f04b52 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -507,7 +507,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
- tupdesc = CreateTemplateTupleDesc(12, false);
+ tupdesc = CreateTemplateTupleDesc(13, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid",
OIDOID, -1, 0);
/* This should have been called 'pid'; can't change it. 2011-06-11 */
@@ -517,21 +517,23 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "application_name",
TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 5, "current_query",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 5, "state",
TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 6, "waiting",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 6, "query",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 7, "waiting",
BOOLOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 7, "act_start",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 8, "act_start",
TIMESTAMPTZOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 8, "query_start",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 9, "query_start",
TIMESTAMPTZOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 9, "backend_start",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 10, "backend_start",
TIMESTAMPTZOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_addr",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_addr",
INETOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 11, "client_hostname",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_hostname",
TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 12, "client_port",
+ TupleDescInitEntry(tupdesc, (AttrNumber) 13, "client_port",
INT4OID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
@@ -584,8 +586,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (funcctx->call_cntr < funcctx->max_calls)
{
/* for each row */
- Datum values[12];
- bool nulls[12];
+ Datum values[13];
+ bool nulls[13];
HeapTuple tuple;
PgBackendStatus *beentry;
SockAddr zero_clientaddr;
@@ -610,8 +612,8 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
for (i = 0; i < sizeof(nulls) / sizeof(nulls[0]); i++)
nulls[i] = true;
- nulls[4] = false;
- values[4] = CStringGetTextDatum("<backend information not available>");
+ nulls[5] = false;
+ values[5] = CStringGetTextDatum("<backend information not available>");
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
@@ -629,40 +631,67 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
/* Values only available to same user or superuser */
if (superuser() || beentry->st_userid == GetUserId())
{
+ if ( beentry->st_state == -1)
+ {
+ nulls[4] = true;
+ }
+ else
+ {
+ switch(beentry->st_state)
+ {
+ case STATE_IDLE:
+ values[4] = CStringGetTextDatum("<IDLE>");
+ break;
+ case STATE_RUNNING:
+ values[4] = CStringGetTextDatum("<RUNNING>");
+ break;
+ case STATE_IDLEINTRANSACTION:
+ values[4] = CStringGetTextDatum("<IDLE> in transaction");
+ break;
+ case STATE_FASTPATH:
+ values[4] = CStringGetTextDatum("<FASTPATH> function call");
+ break;
+ case STATE_IDLEINTRANSACTION_ABRT:
+ values[4] = CStringGetTextDatum("<IDLE> in transaction (aborted)");
+ break;
+ }
+ }
if (*(beentry->st_activity) == '\0')
{
- values[4] = CStringGetTextDatum("<command string not enabled>");
+
+ values[5] = CStringGetTextDatum("<command string not enabled>");
}
else
{
- values[4] = CStringGetTextDatum(beentry->st_activity);
+
+ values[5] = CStringGetTextDatum(beentry->st_activity);
}
- values[5] = BoolGetDatum(beentry->st_waiting);
+ values[6] = BoolGetDatum(beentry->st_waiting);
if (beentry->st_xact_start_timestamp != 0)
- values[6] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
+ values[7] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
else
- nulls[6] = true;
+ nulls[7] = true;
if (beentry->st_activity_start_timestamp != 0)
- values[7] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
+ values[8] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
else
- nulls[7] = true;
+ nulls[8] = true;
if (beentry->st_proc_start_timestamp != 0)
- values[8] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
+ values[9] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
else
- nulls[8] = true;
+ nulls[9] = true;
/* A zeroed client addr means we don't know */
memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
sizeof(zero_clientaddr) == 0))
{
- nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
+ nulls[12] = true;
}
else
{
@@ -686,19 +715,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
if (ret == 0)
{
clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
- values[9] = DirectFunctionCall1(inet_in,
+ values[10] = DirectFunctionCall1(inet_in,
CStringGetDatum(remote_host));
if (beentry->st_clienthostname)
- values[10] = CStringGetTextDatum(beentry->st_clienthostname);
+ values[11] = CStringGetTextDatum(beentry->st_clienthostname);
else
- nulls[10] = true;
- values[11] = Int32GetDatum(atoi(remote_port));
+ nulls[11] = true;
+ values[12] = Int32GetDatum(atoi(remote_port));
}
else
{
- nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
+ nulls[12] = true;
}
}
else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
@@ -709,30 +738,31 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
* connections we have no permissions to view, or with
* errors.
*/
- nulls[9] = true;
nulls[10] = true;
- values[11] = DatumGetInt32(-1);
+ nulls[11] = true;
+ values[12] = DatumGetInt32(-1);
}
else
{
/* Unknown address type, should never happen */
- nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
+ nulls[12] = true;
}
}
}
else
{
/* No permissions to view data about this session */
- values[4] = CStringGetTextDatum("<insufficient privilege>");
- nulls[5] = true;
+ values[5] = CStringGetTextDatum("<insufficient privilege>");
+ nulls[4] = true;
nulls[6] = true;
nulls[7] = true;
nulls[8] = true;
nulls[9] = true;
nulls[10] = true;
nulls[11] = true;
+ nulls[12] = true;
}
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
diff --git a/src/include/c.h b/src/include/c.h
index 0391860..9d7c450 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -708,6 +708,11 @@ typedef NameData *Name;
#define STATUS_EOF (-2)
#define STATUS_FOUND (1)
#define STATUS_WAITING (2)
+#define STATE_IDLE (0)
+#define STATE_RUNNING (1)
+#define STATE_IDLEINTRANSACTION (2)
+#define STATE_FASTPATH (3)
+#define STATE_IDLEINTRANSACTION_ABRT (4)
/* gettext domain name mangling */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 64b7a6a..e576436 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2548,7 +2548,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 t t s 0 0 23 "" _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 t s 1 0 2249 "23" "{23,26,23,26,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _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 t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,869,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,client_addr,client_hostname,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ ));
DESCR("statistics: information about currently active backends");
DATA(insert OID = 3099 ( pg_stat_get_wal_senders PGNSP PGUID 12 1 10 0 0 f f f f t s 0 0 2249 "" "{23,25,25,25,25,25,23,25}" "{o,o,o,o,o,o,o,o}" "{procpid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
DESCR("statistics: information about currently active replication");
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 7b2bd4e..e784087 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -632,6 +632,9 @@ typedef struct PgBackendStatus
/* Is backend currently waiting on an lmgr lock? */
bool st_waiting;
+ /* current state integer */
+ int st_state;
+
/* application name; MUST be null-terminated */
char *st_appname;
@@ -715,7 +718,7 @@ extern void pgstat_report_recovery_conflict(int reason);
extern void pgstat_initialize(void);
extern void pgstat_bestart(void);
-extern void pgstat_report_activity(const char *cmd_str);
+extern void pgstat_report_activity(int state, const char *cmd_str);
extern void pgstat_report_appname(const char *appname);
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
extern void pgstat_report_waiting(bool waiting);