]> granicus.if.org Git - postgresql/commitdiff
Add:
authorBruce Momjian <bruce@momjian.us>
Tue, 9 Mar 2004 04:43:07 +0000 (04:43 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 9 Mar 2004 04:43:07 +0000 (04:43 +0000)
#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

doc/src/sgml/runtime.sgml
src/backend/postmaster/postmaster.c
src/backend/tcop/postgres.c
src/backend/utils/error/elog.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/backend/utils/misc/ps_status.c
src/include/libpq/libpq-be.h
src/include/utils/elog.h

index 5c67f70863e40942f519793a70a7822593ab6c6d..335a404f070e0e3b04a661b8b42a3c41149a0e2d 100644 (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>
index 3e35bf39399db330f9feb2b346f1503314254c99..9b4abc16eb15095db55101775012119321e3b96a 100644 (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));
        }
 
index abb682686dc378818ab9f013188def0e5977f6bc..ef59e78fbddfc4c5f445158f935735919e156bf4 100644 (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;
 
index 22fcde31ed799b90d5550e3bb68058004372f8ca..d516d2d72ecc68417ab0d9e00f54dd86a7dcbfff 100644 (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');
index 85931e3ca83c1e8c2601817cf5f923f2e2ec45fc..e8a28aaa44829bf68637734238d59b974adbcba1 100644 (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."),
index 3d58e9783f5f58675853652930ee9e861e3edb3e..8830f822bcd336b6d1908a833dfb301f12a87ab2 100644 (file)
 #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 fcd236d0012646c324ca9e65903903a786e68e02..770882cc8efcb7f290abea974091dd295a59aec1 100644 (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)
index 9c6a474d7f84710a24e85ae6d9e9467db443d2ae..a077913a113286b246239c45c28cebc0eb130aad 100644 (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 */
 
index 5b626fab0c8ec720e6f051d4c13416952f2593e6..4a7629e90d7986dce4f85bc561f626b2d9370bdb 100644 (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;