Re: logging enhancements, minor code cleanup (retry) - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: logging enhancements, minor code cleanup (retry) |
Date | |
Msg-id | 200308170448.h7H4mxu11174@candle.pha.pa.us Whole thread Raw |
In response to | logging enhancements, minor code cleanup (retry) (Andrew Dunstan <andrew@dunslane.net>) |
List | pgsql-patches |
This has been saved for the 7.5 release: http:/momjian.postgresql.org/cgi-bin/pgpatches2 --------------------------------------------------------------------------- Andrew Dunstan wrote: > > revised patch attached, including docco. I think this attends to all the > comments I received. > > cheers > > andrew > > > 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 ---- > > > <varlistentry> > + <term><varname>LOG_SESSION_END</varname> (<type>boolean</type>)</term> > + <listitem> > + <para> > + 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 <filename>postgresql.conf</filename> > + configuration file. > + </para> > + </listitem> > + </varlistentry> > + > + > + <varlistentry> > <term><varname>LOG_DURATION</varname> (<type>boolean</type>)</term> > <listitem> > <para> > *************** > *** 1825,1830 **** > --- 1839,1876 ---- > the process ID. > </para> > </listitem> > + </varlistentry> > + > + <varlistentry> > + <term><varname>LOG_LINE_FORMAT</varname> (<type>string</type>)</term> > + <listitem> > + <para> > + 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: > + <literal>'%U'</literal> is replace with the username, > + <literal>'%D'</literal> is replaced by the database name, > + and <literal>'%%'</literal> is replaced by <literal>'%'</literal>. > + All other characters are copied literally to the log. For example, > + <programlisting> > + log_line_format = '<%U%%%D> ' > + </programlisting> > + will produce output like this: > + <programlisting> > + <myuser%mydb> LOG: query: create table foo(blah text); > + </programlisting> > + </para> > + <para> > + If <varname>LOG_PID</varname> or <varname>LOG_TIMESTAMP</varname> > + are turned on the output from <varname>LOG_LINE_FORMAT</varname> > + will follow those items but precede any other output on the line. > + </para> > + <para> > + This option can only be set at server start or in the > + <filename>postgresql.conf</filename> configuration file. > + </para> > + > + </listitem> > </varlistentry> > > <varlistentry> > 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; > > ---------------------------(end of broadcast)--------------------------- > TIP 9: the planner will ignore your desire to choose an index scan if your > joining column's datatypes do not match -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
pgsql-patches by date: