Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.245
diff -c -c -r1.245 runtime.sgml
*** doc/src/sgml/runtime.sgml 7 Mar 2004 01:02:55 -0000 1.245
--- doc/src/sgml/runtime.sgml 9 Mar 2004 04:33:24 -0000
***************
*** 1973,1978 ****
--- 1973,2070 ----
+ log_line_prefix (string)
+
+
+ This is a printf>-style string that is output at the
+ beginning of each log line. The default is an empty string.
+ Each recognized escape is replaced as outlined
+ below - anything else that looks like an escape is ignored. Other
+ characters are copied straight to the log line. Some escapes are
+ only recognised by session processes, and do not apply to
+ processes without controlling sessions. Syslog> produces its own
+ timestamp and process ID information, so you probably do not want to
+ use those escapes if you are using syslog>.
+
+
+
+
+ Escape
+ Effect
+ Session only
+
+
+
+
+ %u
+ User Name
+ Yes
+
+
+ %d
+ Database Name
+ Yes
+
+
+ %r
+ Remote Hostname or IP address, and Remote Port
+ Yes
+
+
+ %p
+ Process ID
+ No
+
+
+ %t
+ Timestamp
+ No
+
+
+ %i
+ Command Tag. This is the command which generated the log
+ line.
+ Yes
+
+
+ %c
+ Session ID. A unique identifier for each session.
+ It is 2 4-byte hexadecimal numbers separated by a dot. The numbers
+ are the Session Start Time and the Process ID, so this can also
+ be used as a space saving way of printing these items.
+ Yes
+
+
+ %l
+ Number of the log line for each process,
+ starting at 1
+ No
+
+
+ %s
+ Session Start Timestamp
+ Yes
+
+
+ %x
+ Does not produce any output, but tells non-session
+ processes to stop at this point in the string. Ignored by
+ session backends.
+ No
+
+
+ %%
+ literal %>
+ No
+
+
+
+
+
+
+
+
+
log_pid (boolean)
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.370
diff -c -c -r1.370 postmaster.c
*** src/backend/postmaster/postmaster.c 5 Mar 2004 01:11:04 -0000 1.370
--- src/backend/postmaster/postmaster.c 9 Mar 2004 04:33:28 -0000
***************
*** 2437,2442 ****
--- 2437,2443 ----
/* set these to empty in case they are needed before we set them up */
port->remote_host = "";
port->remote_port = "";
+ port->commandTag = "";
/* Save port etc. for ps status */
MyProcPort = port;
***************
*** 2489,2495 ****
/* modify remote_host for use in ps status */
char tmphost[NI_MAXHOST];
! snprintf(tmphost, sizeof(tmphost), "%s:%s", remote_host, remote_port);
StrNCpy(remote_host, tmphost, sizeof(remote_host));
}
--- 2490,2496 ----
/* modify remote_host for use in ps status */
char tmphost[NI_MAXHOST];
! snprintf(tmphost, sizeof(tmphost), "%s(%s)", remote_host, remote_port);
StrNCpy(remote_host, tmphost, sizeof(remote_host));
}
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.393
diff -c -c -r1.393 postgres.c
*** src/backend/tcop/postgres.c 21 Feb 2004 06:29:58 -0000 1.393
--- src/backend/tcop/postgres.c 9 Mar 2004 04:33:30 -0000
***************
*** 3198,3204 ****
static void
log_disconnections(int code, Datum arg)
{
! Port * port = MyProcPort;
struct timeval end;
int hours, minutes, seconds;
--- 3198,3204 ----
static void
log_disconnections(int code, Datum arg)
{
! Port *port = MyProcPort;
struct timeval end;
int hours, minutes, seconds;
Index: src/backend/utils/error/elog.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/error/elog.c,v
retrieving revision 1.126
diff -c -c -r1.126 elog.c
*** src/backend/utils/error/elog.c 29 Nov 2003 19:52:01 -0000 1.126
--- src/backend/utils/error/elog.c 9 Mar 2004 04:33:31 -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_prefix = ""; /* format for extra log line info */
#ifdef HAVE_SYSLOG
/*
***************
*** 146,152 ****
static const char *print_timestamp(void);
static const char *print_pid(void);
static void append_with_tabs(StringInfo buf, const char *str);
!
/*
* errstart --- begin an error-reporting cycle
--- 147,153 ----
static const char *print_timestamp(void);
static const char *print_pid(void);
static void append_with_tabs(StringInfo buf, const char *str);
! static const char *log_line_prefix(void);
/*
* errstart --- begin an error-reporting cycle
***************
*** 1022,1027 ****
--- 1023,1160 ----
}
#endif /* HAVE_SYSLOG */
+ /*
+ * Format tag info for log lines
+ */
+ static const char *
+ log_line_prefix(void)
+ {
+
+ /* static accumulator for line numbers */
+ static int log_line_number = 0;
+
+ /* space for option string + one of each option, plus some room to spare */
+ /* Note: if more identifiers are built in this will have to increase */
+ static char *result = NULL;
+ int format_len = strlen(Log_line_prefix);
+ int result_len = 2*NAMEDATALEN + format_len +120 ;
+
+ if (result == NULL)
+ result = malloc(result_len);
+ result[0] = '\0';
+
+ if (format_len > 0)
+ {
+ int i,j;
+ char * dbname = NULL;
+ char * username = NULL;
+ time_t stamp_time;
+ log_line_number++;
+ if (MyProcPort != NULL)
+ {
+ dbname = MyProcPort->database_name;
+ username = MyProcPort->user_name;
+ if (dbname == NULL || *dbname == '\0')
+ dbname = gettext("[unknown]");
+ if (username == NULL || *username == '\0')
+ username = gettext("[unknown]");
+ }
+
+ /*
+ * 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_prefix[i] != '%')
+ {
+ /* literal char, just copy */
+ result[j]=Log_line_prefix[i];
+ j++;
+ result[j] = '\0';
+ continue;
+ }
+ else if (i == format_len - 1)
+ {
+ /* format error - skip it */
+ continue;
+ }
+
+ /* go to char after '%' */
+ i++;
+
+ /* in postmaster and friends, skip non-applicable options,
+ * stop if %x is seen
+ */
+ if (MyProcPort == NULL)
+ {
+ if (Log_line_prefix[i] == 'x')
+ break;
+ if (strchr("udcsir",Log_line_prefix[i]) != NULL)
+ continue;
+ }
+
+ /* process the option */
+ switch (Log_line_prefix[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 'c':
+ j += snprintf(result+j,result_len-j,"%lx.%lx",
+ (long)(MyProcPort->session_start.tv_sec),
+ (long)MyProcPid);
+ break;
+ case 'p':
+ j += snprintf(result+j,result_len-j,"%ld",(long)MyProcPid);
+ break;
+ case 'l':
+ j += snprintf(result+j,result_len-j,"%d",log_line_number);
+ break;
+ case 't':
+ stamp_time = time(NULL);
+ j += strftime(result+j, result_len-j, "%Y-%m-%d %H:%M:%S",
+ localtime(&stamp_time));
+ break;
+ case 's':
+ j += strftime(result+j, result_len-j, "%Y-%m-%d %H:%M:%S",
+ localtime(&(MyProcPort->session_start.tv_sec)));
+ break;
+ case 'i':
+ j += snprintf(result+j,result_len-j,"%s",
+ MyProcPort->commandTag);
+ break;
+ case 'r':
+ j += snprintf(result+j,result_len-j,"%s",
+ MyProcPort->remote_host);
+ if (!LogSourcePort && strlen(MyProcPort->remote_port))
+ j += snprintf(result+j,result_len-j,"(%s)",
+ MyProcPort->remote_port);
+ break;
+ case 'x':
+ /* non-postmaster case - just ignore */
+ break;
+ case '%':
+ result[j] = '%';
+ j++;
+ result[j] = '\0';
+ break;
+ default:
+ /* format error - skip it */
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
/*
* Write error report to server's log
***************
*** 1033,1039 ****
initStringInfo(&buf);
! appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
--- 1166,1173 ----
initStringInfo(&buf);
! appendStringInfo(&buf, "%s%s: ",
! log_line_prefix(), error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
***************
*** 1066,1083 ****
--- 1200,1220 ----
{
if (edata->detail)
{
+ appendStringInfoString(&buf, log_line_prefix() );
appendStringInfoString(&buf, gettext("DETAIL: "));
append_with_tabs(&buf, edata->detail);
appendStringInfoChar(&buf, '\n');
}
if (edata->hint)
{
+ appendStringInfoString(&buf, log_line_prefix() );
appendStringInfoString(&buf, gettext("HINT: "));
append_with_tabs(&buf, edata->hint);
appendStringInfoChar(&buf, '\n');
}
if (edata->context)
{
+ appendStringInfoString(&buf, log_line_prefix() );
appendStringInfoString(&buf, gettext("CONTEXT: "));
append_with_tabs(&buf, edata->context);
appendStringInfoChar(&buf, '\n');
***************
*** 1086,1096 ****
{
/* assume no newlines in funcname or filename... */
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);
}
}
--- 1223,1235 ----
{
/* assume no newlines in funcname or filename... */
if (edata->funcname && edata->filename)
! appendStringInfo(&buf, gettext("%sLOCATION: %s, %s:%d\n"),
! log_line_prefix(),
edata->funcname, edata->filename,
edata->lineno);
else if (edata->filename)
! appendStringInfo(&buf, gettext("%sLOCATION: %s:%d\n"),
! log_line_prefix(),
edata->filename, edata->lineno);
}
}
***************
*** 1100,1105 ****
--- 1239,1245 ----
*/
if (edata->elevel >= log_min_error_statement && debug_query_string != NULL)
{
+ appendStringInfoString(&buf, log_line_prefix() );
appendStringInfoString(&buf, gettext("STATEMENT: "));
append_with_tabs(&buf, debug_query_string);
appendStringInfoChar(&buf, '\n');
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.188
diff -c -c -r1.188 guc.c
*** src/backend/utils/misc/guc.c 23 Feb 2004 20:45:59 -0000 1.188
--- src/backend/utils/misc/guc.c 9 Mar 2004 04:33:35 -0000
***************
*** 1496,1501 ****
--- 1496,1511 ----
},
{
+ {"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
+ gettext_noop("Controls information prefixed to each log line"),
+ gettext_noop("if blank no prefix is used")
+ },
+ &Log_line_prefix,
+ "", NULL, NULL
+ },
+
+
+ {
{"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the display format for date and time values."),
gettext_noop("Also controls interpretation of ambiguous "
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.106
diff -c -c -r1.106 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample 17 Feb 2004 03:54:57 -0000 1.106
--- src/backend/utils/misc/postgresql.conf.sample 9 Mar 2004 04:33:35 -0000
***************
*** 185,190 ****
--- 185,198 ----
#log_disconnections = false
#log_duration = false
#log_pid = false
+ #log_line_prefix = '' # e.g. '<%u%%%d> '
+ # %u=user name %d=database name
+ # %r=remote host and port
+ # %p=PID %t=timestamp %i=command tag
+ # %c=session id %l=session line number
+ # %s=session start timestamp
+ # %x=stop here in non-session processes
+ # %%='%'
#log_statement = false
#log_timestamp = false
#log_hostname = false
Index: src/backend/utils/misc/ps_status.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/ps_status.c,v
retrieving revision 1.17
diff -c -c -r1.17 ps_status.c
*** src/backend/utils/misc/ps_status.c 22 Feb 2004 21:26:55 -0000 1.17
--- src/backend/utils/misc/ps_status.c 9 Mar 2004 04:33:35 -0000
***************
*** 26,31 ****
--- 26,32 ----
#include
#endif
+ #include "libpq/libpq.h"
#include "miscadmin.h"
#include "utils/ps_status.h"
***************
*** 276,285 ****
void
set_ps_display(const char *activity)
{
- #ifndef PS_USE_NONE
/* no ps display for stand-alone backend */
if (!IsUnderPostmaster)
return;
#ifdef PS_USE_CLOBBER_ARGV
/* If ps_buffer is a pointer, it might still be null */
--- 277,291 ----
void
set_ps_display(const char *activity)
{
/* no ps display for stand-alone backend */
if (!IsUnderPostmaster)
return;
+
+ /* save it for logging context */
+ if (MyProcPort)
+ MyProcPort->commandTag = (char *) activity;
+
+ #ifndef PS_USE_NONE
#ifdef PS_USE_CLOBBER_ARGV
/* If ps_buffer is a pointer, it might still be null */
Index: src/include/libpq/libpq-be.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/libpq/libpq-be.h,v
retrieving revision 1.41
diff -c -c -r1.41 libpq-be.h
*** src/include/libpq/libpq-be.h 21 Feb 2004 06:29:58 -0000 1.41
--- src/include/libpq/libpq-be.h 9 Mar 2004 04:33:36 -0000
***************
*** 50,55 ****
--- 50,56 ----
SockAddr raddr; /* remote addr (client) */
char *remote_host; /* name (or ip addr) of remote host */
char *remote_port; /* text rep of remote port */
+ char *commandTag; /* command tag for display in log lines */
struct timeval session_start; /* for session duration logging */
CAC_state canAcceptConnections; /* postmaster connection status */
Index: src/include/utils/elog.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/elog.h,v
retrieving revision 1.64
diff -c -c -r1.64 elog.h
*** src/include/utils/elog.h 29 Nov 2003 22:41:15 -0000 1.64
--- src/include/utils/elog.h 9 Mar 2004 04:33:36 -0000
***************
*** 171,176 ****
--- 171,177 ----
extern PGErrorVerbosity Log_error_verbosity;
extern bool Log_timestamp;
extern bool Log_pid;
+ extern char *Log_line_prefix;
#ifdef HAVE_SYSLOG
extern int Use_syslog;