#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
                              # %%='%'

Andrew Dunstan
This commit is contained in:
Bruce Momjian 2004-03-09 04:43:07 +00:00
parent af96aa9ab1
commit 2d3fe86bc4
9 changed files with 274 additions and 15 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.245 2004/03/07 01:02:55 neilc Exp $
$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.246 2004/03/09 04:43:06 momjian Exp $
-->
<Chapter Id="runtime">
@ -1972,6 +1972,98 @@ SET ENABLE_SEQSCAN TO OFF;
</listitem>
</varlistentry>
<varlistentry>
<term><varname>log_line_prefix</varname> (<type>string</type>)</term>
<listitem>
<para>
This is a <literal>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. <application>Syslog</> produces its own
timestamp and process ID information, so you probably do not want to
use those escapes if you are using <application>syslog</>.
<informaltable>
<tgroup cols="3">
<thead>
<row>
<entry>Escape</entry>
<entry>Effect</entry>
<entry>Session only</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>%u</literal></entry>
<entry>User Name</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%d</literal></entry>
<entry>Database Name</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%r</literal></entry>
<entry>Remote Hostname or IP address, and Remote Port</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%p</literal></entry>
<entry>Process ID</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>%t</literal></entry>
<entry>Timestamp</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>%i</literal></entry>
<entry>Command Tag. This is the command which generated the log
line.</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%c</literal></entry>
<entry>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.</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%l</literal></entry>
<entry>Number of the log line for each process,
starting at 1</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>%s</literal></entry>
<entry>Session Start Timestamp</entry>
<entry>Yes</entry>
</row>
<row>
<entry><literal>%x</literal></entry>
<entry>Does not produce any output, but tells non-session
processes to stop at this point in the string. Ignored by
session backends.</entry>
<entry>No</entry>
</row>
<row>
<entry><literal>%%</literal></entry>
<entry>literal <literal>%</></entry>
<entry>No</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>log_pid</varname> (<type>boolean</type>)</term>
<listitem>

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.370 2004/03/05 01:11:04 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.371 2004/03/09 04:43:06 momjian Exp $
*
* NOTES
*
@ -2437,6 +2437,7 @@ BackendInit(Port *port)
/* 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,7 +2490,7 @@ BackendInit(Port *port)
/* modify remote_host for use in ps status */
char tmphost[NI_MAXHOST];
snprintf(tmphost, sizeof(tmphost), "%s:%s", remote_host, remote_port);
snprintf(tmphost, sizeof(tmphost), "%s(%s)", remote_host, remote_port);
StrNCpy(remote_host, tmphost, sizeof(remote_host));
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.393 2004/02/21 06:29:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.394 2004/03/09 04:43:07 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -3198,7 +3198,7 @@ ShowUsage(const char *title)
static void
log_disconnections(int code, Datum arg)
{
Port * port = MyProcPort;
Port *port = MyProcPort;
struct timeval end;
int hours, minutes, seconds;

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.126 2003/11/29 19:52:01 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.127 2004/03/09 04:43:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -72,6 +72,7 @@ PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE;
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,7 +147,7 @@ static const char *error_severity(int elevel);
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,6 +1023,138 @@ write_syslog(int level, const char *line)
}
#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,7 +1166,8 @@ send_message_to_server_log(ErrorData *edata)
initStringInfo(&buf);
appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
appendStringInfo(&buf, "%s%s: ",
log_line_prefix(), error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
@ -1066,18 +1200,21 @@ send_message_to_server_log(ErrorData *edata)
{
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,11 +1223,13 @@ send_message_to_server_log(ErrorData *edata)
{
/* assume no newlines in funcname or filename... */
if (edata->funcname && edata->filename)
appendStringInfo(&buf, gettext("LOCATION: %s, %s:%d\n"),
appendStringInfo(&buf, gettext("%sLOCATION: %s, %s:%d\n"),
log_line_prefix(),
edata->funcname, edata->filename,
edata->lineno);
else if (edata->filename)
appendStringInfo(&buf, gettext("LOCATION: %s:%d\n"),
appendStringInfo(&buf, gettext("%sLOCATION: %s:%d\n"),
log_line_prefix(),
edata->filename, edata->lineno);
}
}
@ -1100,6 +1239,7 @@ send_message_to_server_log(ErrorData *edata)
*/
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');

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.188 2004/02/23 20:45:59 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.189 2004/03/09 04:43:07 momjian Exp $
*
*--------------------------------------------------------------------
*/
@ -1495,6 +1495,16 @@ static struct config_string ConfigureNamesString[] =
"panic", assign_min_error_statement, NULL
},
{
{"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."),

View File

@ -185,6 +185,14 @@
#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

View File

@ -5,7 +5,7 @@
* to contain some useful information. Mechanism differs wildly across
* platforms.
*
* $PostgreSQL: pgsql/src/backend/utils/misc/ps_status.c,v 1.17 2004/02/22 21:26:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/ps_status.c,v 1.18 2004/03/09 04:43:07 momjian Exp $
*
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
* various details abducted from various places
@ -26,6 +26,7 @@
#include <crt_externs.h>
#endif
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "utils/ps_status.h"
@ -276,11 +277,16 @@ init_ps_display(const char *username, const char *dbname,
void
set_ps_display(const char *activity)
{
#ifndef PS_USE_NONE
/* 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 */
if (!ps_buffer)

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.41 2004/02/21 06:29:58 tgl Exp $
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.42 2004/03/09 04:43:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -50,6 +50,7 @@ typedef struct Port
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 */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.64 2003/11/29 22:41:15 pgsql Exp $
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.65 2004/03/09 04:43:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -171,6 +171,7 @@ typedef enum
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;