*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.128 2004/03/15 15:56:23 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.129 2004/03/19 02:23:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* GUC parameters */
PGErrorVerbosity Log_error_verbosity = PGERROR_VERBOSE;
-char *Log_line_prefix = ""; /* format for extra log line info */
+char *Log_line_prefix = NULL; /* format for extra log line info */
#ifdef HAVE_SYSLOG
/*
} while (0)
+static void log_line_prefix(StringInfo buf);
static void send_message_to_server_log(ErrorData *edata);
static void send_message_to_frontend(ErrorData *edata);
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
static const char *useful_strerror(int errnum);
static const char *error_severity(int elevel);
static void append_with_tabs(StringInfo buf, const char *str);
-static const char *log_line_prefix(void);
+
/*
* errstart --- begin an error-reporting cycle
#endif /* HAVE_SYSLOG */
/*
- * Format tag info for log lines
+ * Format tag info for log lines; append to the provided buffer.
*/
-static const char *
-log_line_prefix(void)
+static void
+log_line_prefix(StringInfo buf)
{
+ /* static counter for line numbers */
+ static long log_line_number = 0;
+ /* has counter been reset in current process? */
+ static int log_my_pid = 0;
+
+ int format_len;
+ int i;
+
+ /*
+ * This is one of the few places where we'd rather not inherit a
+ * static variable's value from the postmaster. But since we will,
+ * reset it when MyProcPid changes.
+ */
+ if (log_my_pid != MyProcPid)
+ {
+ log_line_number = 0;
+ log_my_pid = MyProcPid;
+ }
+ log_line_number++;
- /* 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 (Log_line_prefix == NULL)
+ return; /* in case guc hasn't run yet */
- if (result == NULL)
- result = malloc(result_len);
- result[0] = '\0';
+ format_len = strlen(Log_line_prefix);
- if (format_len > 0)
+ for (i = 0; i < format_len; i++)
{
- int i,j;
- char * dbname = NULL;
- char * username = NULL;
- time_t stamp_time;
- log_line_number++;
- if (MyProcPort != NULL)
+ if (Log_line_prefix[i] != '%')
{
- dbname = MyProcPort->database_name;
- username = MyProcPort->user_name;
- if (dbname == NULL || *dbname == '\0')
- dbname = gettext("[unknown]");
- if (username == NULL || *username == '\0')
- username = gettext("[unknown]");
+ /* literal char, just copy */
+ appendStringInfoChar(buf, Log_line_prefix[i]);
+ continue;
+ }
+ /* go to char after '%' */
+ i++;
+ if (i >= format_len)
+ {
+ /* format error - ignore it */
+ break;
}
- /*
- * 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++)
+ /* process the option */
+ switch (Log_line_prefix[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;
- }
+ case 'u':
+ if (MyProcPort)
+ {
+ const char *username = MyProcPort->user_name;
- /* go to char after '%' */
- i++;
+ if (username == NULL || *username == '\0')
+ username = gettext("[unknown]");
+ appendStringInfo(buf, "%s", username);
+ }
+ break;
+ case 'd':
+ if (MyProcPort)
+ {
+ const char *dbname = MyProcPort->database_name;
- /* 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;
- }
+ if (dbname == NULL || *dbname == '\0')
+ dbname = gettext("[unknown]");
+ appendStringInfo(buf, "%s", dbname);
+ }
+ break;
+ case 'c':
+ if (MyProcPort)
+ {
+ appendStringInfo(buf, "%lx.%lx",
+ (long)(MyProcPort->session_start.tv_sec),
+ (long)MyProcPid);
+ }
+ break;
+ case 'p':
+ appendStringInfo(buf, "%ld", (long)MyProcPid);
+ break;
+ case 'l':
+ appendStringInfo(buf, "%ld", log_line_number);
+ break;
+ case 't':
+ {
+ time_t stamp_time = time(NULL);
+ char strfbuf[32];
- /* 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",
+ strftime(strfbuf, sizeof(strfbuf), "%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);
+ appendStringInfoString(buf, strfbuf);
+ }
+ break;
+ case 's':
+ if (MyProcPort)
+ {
+ time_t stamp_time = MyProcPort->session_start.tv_sec;
+ char strfbuf[32];
+
+ strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S",
+ localtime(&stamp_time));
+ appendStringInfoString(buf, strfbuf);
+ }
+ break;
+ case 'i':
+ if (MyProcPort)
+ {
+ appendStringInfo(buf, "%s", MyProcPort->commandTag);
+ }
+ break;
+ case 'r':
+ if (MyProcPort)
+ {
+ appendStringInfo(buf, "%s", MyProcPort->remote_host);
if (strlen(MyProcPort->remote_port) > 0)
- 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;
- }
+ appendStringInfo(buf, "(%s)",
+ MyProcPort->remote_port);
+ }
+ break;
+ case 'x':
+ /* in postmaster and friends, stop if %x is seen */
+ /* in a backend, just ignore */
+ if (MyProcPort == NULL)
+ i = format_len;
+ break;
+ case '%':
+ appendStringInfoChar(buf, '%');
+ break;
+ default:
+ /* format error - ignore it */
+ break;
}
}
- return result;
}
initStringInfo(&buf);
- appendStringInfo(&buf, "%s%s: ",
- log_line_prefix(), error_severity(edata->elevel));
+ log_line_prefix(&buf);
+ appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
if (Log_error_verbosity >= PGERROR_VERBOSE)
{
{
if (edata->detail)
{
- appendStringInfoString(&buf, log_line_prefix() );
+ log_line_prefix(&buf);
appendStringInfoString(&buf, gettext("DETAIL: "));
append_with_tabs(&buf, edata->detail);
appendStringInfoChar(&buf, '\n');
}
if (edata->hint)
{
- appendStringInfoString(&buf, log_line_prefix() );
+ log_line_prefix(&buf);
appendStringInfoString(&buf, gettext("HINT: "));
append_with_tabs(&buf, edata->hint);
appendStringInfoChar(&buf, '\n');
}
if (edata->context)
{
- appendStringInfoString(&buf, log_line_prefix() );
+ log_line_prefix(&buf);
appendStringInfoString(&buf, gettext("CONTEXT: "));
append_with_tabs(&buf, edata->context);
appendStringInfoChar(&buf, '\n');
{
/* assume no newlines in funcname or filename... */
if (edata->funcname && edata->filename)
- appendStringInfo(&buf, gettext("%sLOCATION: %s, %s:%d\n"),
- log_line_prefix(),
+ {
+ log_line_prefix(&buf);
+ appendStringInfo(&buf, gettext("LOCATION: %s, %s:%d\n"),
edata->funcname, edata->filename,
edata->lineno);
+ }
else if (edata->filename)
- appendStringInfo(&buf, gettext("%sLOCATION: %s:%d\n"),
- log_line_prefix(),
+ {
+ log_line_prefix(&buf);
+ appendStringInfo(&buf, gettext("LOCATION: %s:%d\n"),
edata->filename, edata->lineno);
+ }
}
}
*/
if (edata->elevel >= log_min_error_statement && debug_query_string != NULL)
{
- appendStringInfoString(&buf, log_line_prefix() );
+ log_line_prefix(&buf);
appendStringInfoString(&buf, gettext("STATEMENT: "));
append_with_tabs(&buf, debug_query_string);
appendStringInfoChar(&buf, '\n');
/* Write to stderr, if enabled */
if (Use_syslog <= 1 || whereToSendOutput == Debug)
{
- /*
- * Timestamp and PID are only used for stderr output --- we assume
- * the syslog daemon will supply them for us in the other case.
- */
- fprintf(stderr, "%s",buf.data);
+ fprintf(stderr, "%s", buf.data);
}
pfree(buf.data);