Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.199
diff -c -w -r1.199 runtime.sgml
*** doc/src/sgml/runtime.sgml 10 Aug 2003 01:20:34 -0000 1.199
--- doc/src/sgml/runtime.sgml 13 Aug 2003 20:59:13 -0000
***************
*** 1801,1806 ****
--- 1801,1820 ----
+ LOG_SESSION_END (boolean)
+
+
+ This outputs a line to the server logs similar to LOG_CONNECTIONS
+ but at the end of a session, and including the duration of the
+ session.This is off by default. This option can only be set at
+ server start or in the postgresql.conf
+ configuration file.
+
+
+
+
+
+
LOG_DURATION (boolean)
***************
*** 1825,1830 ****
--- 1839,1876 ----
the process ID.
+
+
+
+ LOG_LINE_FORMAT (string)
+
+
+ Prefixes each message in the server log file or syslog with extra
+ information as specidied in the string. The default is an empty
+ string. The following sequences in the string are translated:
+ '%U' is replace with the username,
+ '%D' is replaced by the database name,
+ and '%%' is replaced by '%'.
+ All other characters are copied literally to the log. For example,
+
+ log_line_format = '<%U%%%D> '
+
+ will produce output like this:
+
+ <myuser%mydb> LOG: query: create table foo(blah text);
+
+
+
+ If LOG_PID or LOG_TIMESTAMP
+ are turned on the output from LOG_LINE_FORMAT
+ will follow those items but precede any other output on the line.
+
+
+ This option can only be set at server start or in the
+ postgresql.conf configuration file.
+
+
+
Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/commands/vacuum.c,v
retrieving revision 1.259
diff -c -w -r1.259 vacuum.c
*** src/backend/commands/vacuum.c 4 Aug 2003 02:39:58 -0000 1.259
--- src/backend/commands/vacuum.c 13 Aug 2003 20:59:14 -0000
***************
*** 3109,3118 ****
void
vac_init_rusage(VacRUsage *ru0)
{
- struct timezone tz;
-
getrusage(RUSAGE_SELF, &ru0->ru);
! gettimeofday(&ru0->tv, &tz);
}
/*
--- 3109,3116 ----
void
vac_init_rusage(VacRUsage *ru0)
{
getrusage(RUSAGE_SELF, &ru0->ru);
! gettimeofday(&ru0->tv, NULL);
}
/*
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.341
diff -c -w -r1.341 postmaster.c
*** src/backend/postmaster/postmaster.c 12 Aug 2003 18:23:20 -0000 1.341
--- src/backend/postmaster/postmaster.c 13 Aug 2003 20:59:15 -0000
***************
*** 1000,1009 ****
int nSockets;
struct timeval now,
later;
- struct timezone tz;
int i;
! gettimeofday(&now, &tz);
nSockets = initMasks(&readmask);
--- 1000,1008 ----
int nSockets;
struct timeval now,
later;
int i;
! gettimeofday(&now, NULL);
nSockets = initMasks(&readmask);
***************
*** 1085,1091 ****
*/
while (random_seed == 0)
{
! gettimeofday(&later, &tz);
/*
* We are not sure how much precision is in tv_usec, so we
--- 1084,1090 ----
*/
while (random_seed == 0)
{
! gettimeofday(&later, NULL);
/*
* We are not sure how much precision is in tv_usec, so we
***************
*** 2320,2326 ****
int i;
int status;
struct timeval now;
- struct timezone tz;
char remote_host[NI_MAXHOST];
char remote_port[NI_MAXSERV];
--- 2319,2324 ----
***************
*** 2342,2350 ****
/* Close the postmaster's other sockets */
ClosePostmasterPorts(true);
- /* Save port etc. for ps status */
- MyProcPort = port;
-
/* Reset MyProcPid to new backend's pid */
MyProcPid = getpid();
--- 2340,2345 ----
***************
*** 2416,2421 ****
--- 2411,2423 ----
elog(FATAL, "could not set timer for authorization timeout");
/*
+ * Save port etc. for ps status
+ * do this after we log connections or auth failures so that we don't use
+ * the format line before the details are filled in
+ */
+ MyProcPort = port;
+
+ /*
* Receive the startup packet (which might turn out to be a cancel
* request packet).
*/
***************
*** 2456,2462 ****
* start a new random sequence in the random() library function.
*/
random_seed = 0;
! gettimeofday(&now, &tz);
srandom((unsigned int) now.tv_usec);
/* ----------------
--- 2458,2464 ----
* start a new random sequence in the random() library function.
*/
random_seed = 0;
! gettimeofday(&now, NULL);
srandom((unsigned int) now.tv_usec);
/* ----------------
***************
*** 2539,2544 ****
--- 2541,2554 ----
MemoryContextSwitchTo(TopMemoryContext);
MemoryContextDelete(PostmasterContext);
PostmasterContext = NULL;
+
+ /*
+ * set up remaining members of port stucture while in the
+ * TopMemoryContext
+ */
+ port->remote_host = pstrdup(remote_host);
+ port->remote_port = pstrdup(remote_port);
+ gettimeofday(&(port->session_start),NULL);
/*
* Debug: print arguments being passed to backend
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.359
diff -c -w -r1.359 postgres.c
*** src/backend/tcop/postgres.c 12 Aug 2003 18:52:38 -0000 1.359
--- src/backend/tcop/postgres.c 13 Aug 2003 20:59:15 -0000
***************
*** 85,90 ****
--- 85,93 ----
bool Warn_restart_ready = false;
bool InError = false;
+ /* flag for logging end of session */
+ bool Log_session_end = false;
+
/*
* Flags for expensive function optimization -- JMH 3/9/92
*/
***************
*** 150,155 ****
--- 153,159 ----
static void finish_xact_command(void);
static void SigHupHandler(SIGNAL_ARGS);
static void FloatExceptionHandler(SIGNAL_ARGS);
+ static void log_session_end(void);
/* ----------------------------------------------------------------
***************
*** 2426,2432 ****
--- 2430,2439 ----
* other output options.
*/
if (debug_flag >= 1)
+ {
SetConfigOption("log_connections", "true", debug_context, gucsource);
+ SetConfigOption("log_session_end", "true", debug_context, gucsource);
+ }
if (debug_flag >= 2)
SetConfigOption("log_statement", "true", debug_context, gucsource);
if (debug_flag >= 3)
***************
*** 2455,2460 ****
--- 2462,2472 ----
gucopts = lnext(gucopts);
SetConfigOption(name, value, PGC_BACKEND, PGC_S_CLIENT);
}
+ /*
+ * set up handler to log session end.
+ */
+ if (IsUnderPostmaster && Log_session_end)
+ on_proc_exit(log_session_end,0);
}
/*
***************
*** 3195,3198 ****
--- 3207,3269 ----
errdetail("%s", str.data)));
pfree(str.data);
+ }
+
+
+ /*
+ * on_proc_exit handler to log end of session
+ */
+ static void
+ log_session_end(void)
+ {
+ Port * port = MyProcPort;
+ struct timeval end;
+ int hours, minutes, seconds;
+
+ char session_time[20];
+ char uname[6+NAMEDATALEN];
+ char dbname[10+NAMEDATALEN];
+ char remote_host[7 + NI_MAXHOST];
+ char remote_port[7 + NI_MAXSERV];
+
+ snprintf(uname, sizeof(uname)," user=%s",port->user_name);
+ snprintf(dbname, sizeof(dbname)," database=%s",port->database_name);
+ snprintf(remote_host,sizeof(remote_host)," host=%s",
+ port->remote_host);
+ /* prevent redundant or empty reporting of port */
+ if (!LogSourcePort && strlen(port->remote_port))
+ snprintf(remote_port,sizeof(remote_port)," port=%s",port->remote_port);
+ else
+ remote_port[0] = '\0';
+
+
+ gettimeofday(&end,NULL);
+
+ if (end.tv_usec < port->session_start.tv_usec)
+ {
+ end.tv_sec--;
+ end.tv_usec += 1000000;
+ }
+ end.tv_sec -= port->session_start.tv_sec;
+ end.tv_usec -= port->session_start.tv_usec;
+
+ hours = end.tv_sec / 3600;
+ end.tv_sec %= 3600;
+ minutes = end.tv_sec / 60;
+ seconds = end.tv_sec % 60;
+
+ /* if time has gone backwards for some reason say so, or print time */
+
+ if (end.tv_sec < 0)
+ snprintf(session_time,sizeof(session_time),"negative!");
+ else
+ /* for stricter accuracy here we could round - this is close enough */
+ snprintf(session_time, sizeof(session_time),"%d:%02d:%02d.%02ld",
+ hours, minutes, seconds, end.tv_usec/10000);
+
+ ereport(
+ LOG,
+ (errmsg("session end: duration: %s%s%s%s%s",
+ session_time,uname,dbname,remote_host,remote_port)));
+
}
Index: src/backend/utils/adt/nabstime.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/nabstime.c,v
retrieving revision 1.113
diff -c -w -r1.113 nabstime.c
*** src/backend/utils/adt/nabstime.c 4 Aug 2003 02:40:05 -0000 1.113
--- src/backend/utils/adt/nabstime.c 13 Aug 2003 20:59:16 -0000
***************
*** 1745,1757 ****
timeofday(PG_FUNCTION_ARGS)
{
struct timeval tp;
- struct timezone tpz;
char templ[100];
char buf[100];
text *result;
int len;
! gettimeofday(&tp, &tpz);
strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
localtime((time_t *) &tp.tv_sec));
snprintf(buf, sizeof(buf), templ, tp.tv_usec);
--- 1745,1756 ----
timeofday(PG_FUNCTION_ARGS)
{
struct timeval tp;
char templ[100];
char buf[100];
text *result;
int len;
! gettimeofday(&tp, NULL);
strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z",
localtime((time_t *) &tp.tv_sec));
snprintf(buf, sizeof(buf), templ, tp.tv_usec);
Index: src/backend/utils/error/elog.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v
retrieving revision 1.119
diff -c -w -r1.119 elog.c
*** src/backend/utils/error/elog.c 8 Aug 2003 21:42:11 -0000 1.119
--- src/backend/utils/error/elog.c 13 Aug 2003 20:59:16 -0000
***************
*** 72,77 ****
--- 72,78 ----
bool Log_timestamp = false; /* show timestamps in stderr
* output */
bool Log_pid = false; /* show PIDs in stderr output */
+ char *Log_line_format_str = ""; /* format for extra log line info */
#ifdef HAVE_SYSLOG
/*
***************
*** 145,150 ****
--- 146,152 ----
static const char *error_severity(int elevel);
static const char *print_timestamp(void);
static const char *print_pid(void);
+ static const char *log_line_extra(void);
/*
***************
*** 1019,1024 ****
--- 1021,1099 ----
}
#endif /* HAVE_SYSLOG */
+ /*
+ * Formatted extra info for log if option is set and we have data,
+ * or empty string otherwise.
+ */
+ static const char *
+ log_line_extra(void)
+ {
+ /* space for option string + 2 identifiers */
+ /* Note: if more identifiers are built in this will have to increase */
+ static char *result = NULL;
+ int format_len = strlen(Log_line_format_str);
+ int result_len = 2*NAMEDATALEN + format_len +3 ;
+ if (result == NULL)
+ result = malloc(result_len);
+ result[0] = '\0';
+
+ if (format_len > 0 && MyProcPort)
+ {
+ int i,j;
+ char * dbname = MyProcPort->database_name;
+ char * username = MyProcPort->user_name;
+ if (dbname == NULL)
+ dbname="";
+ if (username == NULL)
+ username = "";
+
+ /*
+ * invariant through each iteration of this loop:
+ * . j is the index of the trailing null on result
+ * . result_len - j is the number of chars we have room for
+ * including the trailing null
+ * . there is room to write at least one more non-null char plus the
+ * trailing null
+ */
+ for (i = 0, j=0; i < format_len && j < result_len-1; i++)
+ {
+ if(Log_line_format_str[i] != '%')
+ {
+ /* literal char, just copy */
+ result[j]=Log_line_format_str[i];
+ j++;
+ result[j] = '\0';
+ continue;
+ }
+ else if (i == format_len - 1)
+ {
+ /* format error - skip it */
+ continue;
+ }
+ /* go to char after '%', take action accordingly */
+ i++;
+ switch (Log_line_format_str[i])
+ {
+ case 'U':
+ j += snprintf(result+j,result_len-j,"%s",username);
+ break;
+ case 'D':
+ j += snprintf(result+j,result_len-j,"%s",dbname);
+ break;
+ case '%':
+ result[j] = '%';
+ j++;
+ result[j] = '\0';
+ break;
+ default:
+ /* format error - skip it */
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
/*
* Write error report to server's log
***************
*** 1028,1036 ****
{
StringInfoData buf;
initStringInfo(&buf);
! appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
--- 1103,1115 ----
{
StringInfoData buf;
+ const char *extra_info = log_line_extra();
+
initStringInfo(&buf);
! appendStringInfo(&buf, "%s%s: ",
! extra_info,
! error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
***************
*** 1062,1080 ****
if (Log_error_verbosity >= PGERROR_DEFAULT)
{
if (edata->detail)
! appendStringInfo(&buf, gettext("DETAIL: %s\n"), edata->detail);
if (edata->hint)
! appendStringInfo(&buf, gettext("HINT: %s\n"), edata->hint);
if (edata->context)
! appendStringInfo(&buf, gettext("CONTEXT: %s\n"), edata->context);
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
if (edata->funcname && edata->filename)
! appendStringInfo(&buf, gettext("LOCATION: %s, %s:%d\n"),
edata->funcname, edata->filename,
edata->lineno);
else if (edata->filename)
! appendStringInfo(&buf, gettext("LOCATION: %s:%d\n"),
edata->filename, edata->lineno);
}
}
--- 1141,1167 ----
if (Log_error_verbosity >= PGERROR_DEFAULT)
{
if (edata->detail)
! appendStringInfo(&buf, gettext("%sDETAIL: %s\n"),
! extra_info,
! edata->detail);
if (edata->hint)
! appendStringInfo(&buf, gettext("%sHINT: %s\n"),
! extra_info,
! edata->hint);
if (edata->context)
! appendStringInfo(&buf, gettext("%sCONTEXT: %s\n"),
! extra_info,
! edata->context);
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
if (edata->funcname && edata->filename)
! appendStringInfo(&buf, gettext("%sLOCATION: %s, %s:%d\n"),
! extra_info,
edata->funcname, edata->filename,
edata->lineno);
else if (edata->filename)
! appendStringInfo(&buf, gettext("%sLOCATION: %s:%d\n"),
! extra_info,
edata->filename, edata->lineno);
}
}
***************
*** 1086,1092 ****
* improve?
*/
if (edata->elevel >= log_min_error_statement && debug_query_string != NULL)
! appendStringInfo(&buf, gettext("STATEMENT: %s\n"),
debug_query_string);
--- 1173,1180 ----
* improve?
*/
if (edata->elevel >= log_min_error_statement && debug_query_string != NULL)
! appendStringInfo(&buf, gettext("%sSTATEMENT: %s\n"),
! extra_info,
debug_query_string);
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.149
diff -c -w -r1.149 guc.c
*** src/backend/utils/misc/guc.c 11 Aug 2003 23:04:49 -0000 1.149
--- src/backend/utils/misc/guc.c 13 Aug 2003 20:59:17 -0000
***************
*** 66,71 ****
--- 66,72 ----
/* XXX these should appear in other modules' header files */
extern bool Log_connections;
+ extern bool Log_session_end;
extern int PreAuthDelay;
extern int AuthenticationTimeout;
extern int CheckPointTimeout;
***************
*** 488,493 ****
--- 489,502 ----
false, NULL, NULL
},
{
+ {"log_session_end", PGC_BACKEND, LOGGING_WHAT,
+ gettext_noop("Logs end of a session, including duration"),
+ NULL
+ },
+ &Log_session_end,
+ false, NULL, NULL
+ },
+ {
{"log_timestamp", PGC_SIGHUP, LOGGING_WHAT,
gettext_noop("Prefixes server log messages with a time stamp"),
NULL
***************
*** 1334,1339 ****
--- 1343,1357 ----
},
&log_min_error_statement_str,
"panic", assign_min_error_statement, NULL
+ },
+
+ {
+ {"log_line_format", PGC_SIGHUP, LOGGING_WHAT,
+ gettext_noop("Controls extra information on each log line"),
+ gettext_noop("if blank no extra info is logged")
+ },
+ &Log_line_format_str,
+ "", NULL, NULL
},
{
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.87
diff -c -w -r1.87 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample 29 Jul 2003 00:03:18 -0000 1.87
--- src/backend/utils/misc/postgresql.conf.sample 13 Aug 2003 20:59:17 -0000
***************
*** 171,178 ****
--- 171,180 ----
#debug_print_plan = false
#debug_pretty_print = false
#log_connections = false
+ #log_session_end = false
#log_duration = false
#log_pid = false
+ #log_line_format = '' # e.g. '<%U%%%D> ' - %U=username %D=databasename %%=%
#log_statement = false
#log_timestamp = false
#log_hostname = false
Index: src/include/libpq/libpq-be.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/libpq/libpq-be.h,v
retrieving revision 1.37
diff -c -w -r1.37 libpq-be.h
*** src/include/libpq/libpq-be.h 4 Aug 2003 02:40:13 -0000 1.37
--- src/include/libpq/libpq-be.h 13 Aug 2003 20:59:17 -0000
***************
*** 42,47 ****
--- 42,50 ----
ProtocolVersion proto; /* FE/BE protocol version */
SockAddr laddr; /* local addr (postmaster) */
SockAddr raddr; /* remote addr (client) */
+ char *remote_host; /* name (or ip addr) of remote host */
+ char *remote_port; /* text rep of remote port */
+ struct timeval session_start; /* for session duration logging */
/*
* Information that needs to be saved from the startup packet and
Index: src/include/utils/elog.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v
retrieving revision 1.63
diff -c -w -r1.63 elog.h
*** src/include/utils/elog.h 8 Aug 2003 21:42:55 -0000 1.63
--- src/include/utils/elog.h 13 Aug 2003 20:59:17 -0000
***************
*** 171,176 ****
--- 171,177 ----
extern PGErrorVerbosity Log_error_verbosity;
extern bool Log_timestamp;
extern bool Log_pid;
+ extern char *Log_line_format_str;
#ifdef HAVE_SYSLOG
extern int Use_syslog;