commit 37c032f813c9e20ea64ac05f67e42461a0a3502e Author: Dave Page Date: Tue Oct 13 15:34:43 2009 +0100 Initial cut of server aupport for 'application name' diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 98e9685..6d11a14 100644 *** a/src/backend/catalog/system_views.sql --- b/src/backend/catalog/system_views.sql *************** CREATE VIEW pg_stat_activity AS *** 339,345 **** S.query_start, S.backend_start, S.client_addr, ! S.client_port FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U WHERE S.datid = D.oid AND S.usesysid = U.oid; --- 339,346 ---- S.query_start, S.backend_start, S.client_addr, ! S.client_port, ! S.application_name 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/pgstat.c b/src/backend/postmaster/pgstat.c index 1a818ef..519cef4 100644 *** a/src/backend/postmaster/pgstat.c --- b/src/backend/postmaster/pgstat.c *************** pgstat_fetch_global(void) *** 2074,2079 **** --- 2074,2080 ---- static PgBackendStatus *BackendStatusArray = NULL; static PgBackendStatus *MyBEEntry = NULL; static char *BackendActivityBuffer = NULL; + static char *BackendAppnameBuffer = NULL; /* *************** BackendStatusShmemSize(void) *** 2090,2096 **** } /* ! * Initialize the shared status array and activity string buffer during * postmaster startup. */ void --- 2091,2097 ---- } /* ! * Initialize the shared status array and activity/appname string buffers during * postmaster startup. */ void *************** CreateSharedBackendStatus(void) *** 2099,2105 **** Size size; bool found; int i; ! char *buffer; /* Create or attach to the shared array */ size = mul_size(sizeof(PgBackendStatus), MaxBackends); --- 2100,2106 ---- Size size; bool found; int i; ! char *activitybuffer, *appnamebuffer; /* Create or attach to the shared array */ size = mul_size(sizeof(PgBackendStatus), MaxBackends); *************** CreateSharedBackendStatus(void) *** 2124,2134 **** MemSet(BackendActivityBuffer, 0, size); /* Initialize st_activity pointers. */ ! buffer = BackendActivityBuffer; for (i = 0; i < MaxBackends; i++) { ! BackendStatusArray[i].st_activity = buffer; ! buffer += pgstat_track_activity_query_size; } } } --- 2125,2153 ---- MemSet(BackendActivityBuffer, 0, size); /* Initialize st_activity pointers. */ ! activitybuffer = BackendActivityBuffer; for (i = 0; i < MaxBackends; i++) { ! BackendStatusArray[i].st_activity = activitybuffer; ! activitybuffer += pgstat_track_activity_query_size; ! } ! } ! ! /* Create or attach to the shared appname buffer */ ! size = mul_size(NAMEDATALEN, MaxBackends); ! BackendAppnameBuffer = (char *) ! ShmemInitStruct("Backend Application Name Buffer", size, &found); ! ! if (!found) ! { ! MemSet(BackendAppnameBuffer, 0, size); ! ! /* Initialize st_activity pointers. */ ! appnamebuffer = BackendAppnameBuffer; ! for (i = 0; i < MaxBackends; i++) ! { ! BackendStatusArray[i].st_appname = appnamebuffer; ! appnamebuffer += NAMEDATALEN; } } } *************** pgstat_bestart(void) *** 2169,2175 **** TimestampTz proc_start_timestamp; Oid userid; SockAddr clientaddr; ! volatile PgBackendStatus *beentry; /* * To minimize the time spent modifying the PgBackendStatus entry, fetch --- 2188,2194 ---- TimestampTz proc_start_timestamp; Oid userid; SockAddr clientaddr; ! volatile PgBackendStatus *beentry; /* * To minimize the time spent modifying the PgBackendStatus entry, fetch *************** pgstat_bestart(void) *** 2214,2221 **** --- 2233,2242 ---- beentry->st_userid = userid; beentry->st_clientaddr = clientaddr; beentry->st_waiting = false; + beentry->st_appname[0] = '\0'; beentry->st_activity[0] = '\0'; /* Also make sure the last byte in the string area is always 0 */ + beentry->st_appname[NAMEDATALEN - 1] = '\0'; beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0'; beentry->st_changecount++; *************** pgstat_report_activity(const char *cmd_s *** 2271,2277 **** { volatile PgBackendStatus *beentry = MyBEEntry; TimestampTz start_timestamp; ! int len; TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str); --- 2292,2298 ---- { volatile PgBackendStatus *beentry = MyBEEntry; TimestampTz start_timestamp; ! int activity_len, appname_len; TRACE_POSTGRESQL_STATEMENT_STATUS(cmd_str); *************** pgstat_report_activity(const char *cmd_s *** 2284,2291 **** */ 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 --- 2305,2315 ---- */ start_timestamp = GetCurrentStatementStartTimestamp(); ! activity_len = strlen(cmd_str); ! activity_len = pg_mbcliplen(cmd_str, activity_len, pgstat_track_activity_query_size - 1); ! ! appname_len = strlen(application_name); ! appname_len = pg_mbcliplen(application_name, appname_len, NAMEDATALEN - 1); /* * Update my status entry, following the protocol of bumping *************** pgstat_report_activity(const char *cmd_s *** 2295,2302 **** 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_changecount++; Assert((beentry->st_changecount & 1) == 0); --- 2319,2328 ---- beentry->st_changecount++; beentry->st_activity_start_timestamp = start_timestamp; ! memcpy((char *) beentry->st_appname, application_name, appname_len); ! beentry->st_appname[appname_len] = '\0'; ! memcpy((char *) beentry->st_activity, cmd_str, activity_len); ! beentry->st_activity[activity_len] = '\0'; beentry->st_changecount++; Assert((beentry->st_changecount & 1) == 0); *************** pgstat_read_current_status(void) *** 2364,2370 **** volatile PgBackendStatus *beentry; PgBackendStatus *localtable; PgBackendStatus *localentry; ! char *localactivity; int i; Assert(!pgStatRunningInCollector); --- 2390,2396 ---- volatile PgBackendStatus *beentry; PgBackendStatus *localtable; PgBackendStatus *localentry; ! char *localactivity, *localappname; int i; Assert(!pgStatRunningInCollector); *************** pgstat_read_current_status(void) *** 2379,2384 **** --- 2405,2413 ---- localactivity = (char *) MemoryContextAlloc(pgStatLocalContext, pgstat_track_activity_query_size * MaxBackends); + localappname = (char *) + MemoryContextAlloc(pgStatLocalContext, + NAMEDATALEN * MaxBackends); localNumBackends = 0; beentry = BackendStatusArray; *************** pgstat_read_current_status(void) *** 2405,2410 **** --- 2434,2441 ---- * strcpy is safe even if the string is modified concurrently, * because there's always a \0 at the end of the buffer. */ + strcpy(localappname, (char *) beentry->st_appname); + localentry->st_appname = localappname; strcpy(localactivity, (char *) beentry->st_activity); localentry->st_activity = localactivity; } *************** pgstat_read_current_status(void) *** 2423,2428 **** --- 2454,2460 ---- { localentry++; localactivity += pgstat_track_activity_query_size; + localappname += NAMEDATALEN; localNumBackends++; } } diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 39bb558..03243a4 100644 *** a/src/backend/utils/adt/pgstatfuncs.c --- b/src/backend/utils/adt/pgstatfuncs.c *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 416,422 **** oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); ! tupdesc = CreateTemplateTupleDesc(10, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0); --- 416,422 ---- oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); ! tupdesc = CreateTemplateTupleDesc(11, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "datid", OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "procpid", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "usesysid", OIDOID, -1, 0); *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 427,432 **** --- 427,433 ---- TupleDescInitEntry(tupdesc, (AttrNumber) 8, "backend_start", TIMESTAMPTZOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 9, "client_addr", INETOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 10, "client_port", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "application_name", TEXTOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 478,485 **** if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ ! Datum values[10]; ! bool nulls[10]; HeapTuple tuple; PgBackendStatus *beentry; SockAddr zero_clientaddr; --- 479,486 ---- if (funcctx->call_cntr < funcctx->max_calls) { /* for each row */ ! Datum values[11]; ! bool nulls[11]; HeapTuple tuple; PgBackendStatus *beentry; SockAddr zero_clientaddr; *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 598,604 **** --- 599,613 ---- nulls[8] = true; nulls[9] = true; } + } + + /* application name */ + if (beentry->st_appname) + values[10] = CStringGetTextDatum(beentry->st_appname); + else + nulls[10] = true; + } else { *************** pg_stat_get_activity(PG_FUNCTION_ARGS) *** 610,615 **** --- 619,625 ---- nulls[7] = true; nulls[8] = true; nulls[9] = true; + nulls[10] = true; } tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 9e25da1..2c3e51a 100644 *** a/src/backend/utils/error/elog.c --- b/src/backend/utils/error/elog.c *************** *** 68,73 **** --- 68,74 ---- #include "storage/ipc.h" #include "storage/proc.h" #include "tcop/tcopprot.h" + #include "utils/guc.h" #include "utils/memutils.h" #include "utils/ps_status.h" *************** log_line_prefix(StringInfo buf, ErrorDat *** 1723,1728 **** --- 1724,1739 ---- /* process the option */ switch (Log_line_prefix[i]) { + case 'a': + if (application_name) + { + const char *appname = application_name; + + if (appname == NULL || *appname == '\0') + appname = _("[unknown]"); + appendStringInfo(buf, "%s", appname); + } + break; case 'u': if (MyProcPort) { *************** write_csvlog(ErrorData *edata) *** 2028,2033 **** --- 2039,2049 ---- appendCSVLiteral(&buf, msgbuf.data); pfree(msgbuf.data); } + + /* application name */ + if (application_name) + appendCSVLiteral(&buf, application_name); + appendStringInfoCharMacro(&buf, ','); appendStringInfoChar(&buf, '\n'); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 1f63e06..d04e1e4 100644 *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** char *pgstat_temp_directory; *** 387,392 **** --- 387,394 ---- char *default_do_language; + char *application_name; + int tcp_keepalives_idle; int tcp_keepalives_interval; int tcp_keepalives_count; *************** static struct config_string ConfigureNam *** 2550,2555 **** --- 2552,2566 ---- "plpgsql", NULL, NULL }, + { + {"application_name", PGC_USERSET, LOGGING, + gettext_noop("Sets the application name to be reported in statistics and logs."), + NULL + }, + &application_name, + "", NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index d6cf7e2..d0024c3 100644 *** a/src/backend/utils/misc/postgresql.conf.sample --- b/src/backend/utils/misc/postgresql.conf.sample *************** *** 334,339 **** --- 334,340 ---- #log_duration = off #log_hostname = off #log_line_prefix = '' # special values: + # %a = application name # %u = user name # %d = database name # %r = remote host and port diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 429e5d9..a4739f4 100644 *** a/src/bin/psql/startup.c --- b/src/bin/psql/startup.c *************** main(int argc, char *argv[]) *** 199,206 **** } PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); ! SyncVariables(); if (options.action == ACT_LIST_DB) { --- 199,210 ---- } PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); ! SyncVariables(); + + /* Set the application name */ + if (pset.sversion >= 80500) + SendQuery("SET application_name = 'psql';"); if (options.action == ACT_LIST_DB) { *************** main(int argc, char *argv[]) *** 209,215 **** PQfinish(pset.db); exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } ! if (options.logfilename) { pset.logfile = fopen(options.logfilename, "a"); --- 213,219 ---- PQfinish(pset.db); exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } ! if (options.logfilename) { pset.logfile = fopen(options.logfilename, "a"); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 90111e9..9d5da3d 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DATA(insert OID = 2784 ( pg_stat_get_la *** 2999,3005 **** DESCR("statistics: last auto analyze time for a table"); DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 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 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,16,1184,1184,1184,869,23}" "{i,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port}" _null_ pg_stat_get_activity _null_ _null_ _null_ )); DESCR("statistics: information about currently active backends"); DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ )); DESCR("statistics: current backend PID"); --- 2999,3005 ---- DESCR("statistics: last auto analyze time for a table"); DATA(insert OID = 1936 ( pg_stat_get_backend_idset PGNSP PGUID 12 1 100 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 f f f f t s 1 0 2249 "23" "{23,26,23,26,25,16,1184,1184,1184,869,23,25}" "{i,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,procpid,usesysid,current_query,waiting,xact_start,query_start,backend_start,client_addr,client_port,application_name}" _null_ pg_stat_get_activity _null_ _null_ _null_ )); DESCR("statistics: information about currently active backends"); DATA(insert OID = 2026 ( pg_backend_pid PGNSP PGUID 12 1 0 0 f f f t f s 0 0 23 "" _null_ _null_ _null_ _null_ pg_backend_pid _null_ _null_ _null_ )); DESCR("statistics: current backend PID"); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 91ad364..455517b 100644 *** a/src/include/pgstat.h --- b/src/include/pgstat.h *************** typedef struct PgBackendStatus *** 564,571 **** --- 564,575 ---- /* Is backend currently waiting on an lmgr lock? */ bool st_waiting; + /* application name */ + char *st_appname; + /* current command string; MUST be null-terminated */ char *st_activity; + } PgBackendStatus; /* diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 289c6c0..1d06a3b 100644 *** a/src/include/utils/guc.h --- b/src/include/utils/guc.h *************** extern char *HbaFileName; *** 179,184 **** --- 179,186 ---- extern char *IdentFileName; extern char *external_pid_file; + extern char *application_name; + extern char *default_do_language; extern int tcp_keepalives_idle;