Add virtual transaction IDs to CSVLOG output, so that messages coming from

the same transaction can be identified even when no regular XID was assigned.
This seems essential after addition of the lazy-XID patch.  Also some
minor code cleanup in write_csvlog().
This commit is contained in:
Tom Lane 2007-09-27 18:15:36 +00:00
parent a62a359ba2
commit 77c166ba6c
2 changed files with 25 additions and 34 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.148 2007/09/26 22:36:30 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.149 2007/09/27 18:15:36 tgl Exp $ -->
<chapter Id="runtime-config"> <chapter Id="runtime-config">
<title>Server Configuration</title> <title>Server Configuration</title>
@ -3123,8 +3123,8 @@ SELECT * FROM parent WHERE key = 2400;
This option emits log lines in comma-separated-value format, This option emits log lines in comma-separated-value format,
with these columns: timestamp with milliseconds, username, database with these columns: timestamp with milliseconds, username, database
name, session id, host:port number, process id, per-process line name, session id, host:port number, process id, per-process line
number, command tag, session start time, transaction id, error number, command tag, session start time, virtual transaction id,
severity, SQL state code, statement/error message. regular transaction id, error severity, SQL state code, error message.
Here is a sample table definition for storing CSV-format log output: Here is a sample table definition for storing CSV-format log output:
</para> </para>
@ -3132,23 +3132,23 @@ SELECT * FROM parent WHERE key = 2400;
CREATE TABLE postgres_log CREATE TABLE postgres_log
( (
log_time timestamp with time zone, log_time timestamp with time zone,
username text, user_name text,
database_name text, database_name text,
sessionid text, session_id text,
connection_from text, connection_from text,
process_id integer, process_id integer,
process_line_num bigint, process_line_num bigint,
command_tag text, command_tag text,
session_start_time timestamp with time zone, session_start_time timestamp with time zone,
virtual_transaction_id text,
transaction_id bigint, transaction_id bigint,
error_severity text, error_severity text,
sql_state_code text, sql_state_code text,
statement text, message text,
PRIMARY KEY (sessionid, process_line_num) PRIMARY KEY (session_id, process_line_num)
); );
</programlisting> </programlisting>
<para> <para>
To import a log file into this table, use the <command>COPY FROM</> To import a log file into this table, use the <command>COPY FROM</>
command: command:

View File

@ -42,7 +42,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.196 2007/09/05 18:10:48 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.197 2007/09/27 18:15:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -1636,10 +1636,9 @@ appendCSVLiteral(StringInfo buf, const char* data)
/* /*
* Constructs the error message, depending on the Errordata it gets, * Constructs the error message, depending on the Errordata it gets,
* in CSV (comma seperated values) format. The COPY command * in CSV (comma separated values) format. The COPY command
* can then be used to load the messages into a table. * can then be used to load the messages into a table.
*/ */
static void static void
write_csvlog(ErrorData *edata) write_csvlog(ErrorData *edata)
{ {
@ -1672,8 +1671,8 @@ write_csvlog(ErrorData *edata)
* The format of the log output in CSV format: * The format of the log output in CSV format:
* timestamp with milliseconds, username, databasename, session id, * timestamp with milliseconds, username, databasename, session id,
* host and port number, process id, process line number, command tag, * host and port number, process id, process line number, command tag,
* session start time, transaction id, error severity, sql state code, * session start time, virtual transaction id, regular transaction id,
* statement or error message. * error severity, sql state code, error message.
*/ */
/* timestamp_with_milliseconds */ /* timestamp_with_milliseconds */
@ -1737,29 +1736,25 @@ write_csvlog(ErrorData *edata)
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* session id */ /* session id */
appendStringInfo(&buf, "%lx.%x", appendStringInfo(&buf, "%lx.%x", (long) MyStartTime, MyProcPid);
(long) MyStartTime, MyProcPid);
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* Remote host and port */ /* Remote host and port (is it safe to not quote this?) */
if (MyProcPort && MyProcPort->remote_host) if (MyProcPort && MyProcPort->remote_host)
{ {
appendStringInfo(&buf, "%s", MyProcPort->remote_host); appendStringInfo(&buf, "%s", MyProcPort->remote_host);
if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
appendStringInfo(&buf, ":%s", MyProcPort->remote_port); appendStringInfo(&buf, ":%s", MyProcPort->remote_port);
} }
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* Process id */ /* Process id */
if (MyProcPid != 0) if (MyProcPid != 0)
appendStringInfo(&buf, "%d", MyProcPid); appendStringInfo(&buf, "%d", MyProcPid);
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* Line number */ /* Line number */
appendStringInfo(&buf, "%ld", log_line_number); appendStringInfo(&buf, "%ld", log_line_number);
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* PS display */ /* PS display */
@ -1773,16 +1768,13 @@ write_csvlog(ErrorData *edata)
appendCSVLiteral(&buf, msgbuf.data); appendCSVLiteral(&buf, msgbuf.data);
resetStringInfo(&msgbuf); resetStringInfo(&msgbuf);
} }
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* session start timestamp */ /* session start timestamp */
if (formatted_start_time[0] == '\0') if (formatted_start_time[0] == '\0')
{ {
pg_time_t stamp_time = (pg_time_t) MyStartTime; pg_time_t stamp_time = (pg_time_t) MyStartTime;
pg_tz *tz; pg_tz *tz = log_timezone ? log_timezone : gmt_timezone;
tz = log_timezone ? log_timezone : gmt_timezone;
pg_strftime(formatted_start_time, FORMATTED_TS_LEN, pg_strftime(formatted_start_time, FORMATTED_TS_LEN,
"%Y-%m-%d %H:%M:%S %Z", "%Y-%m-%d %H:%M:%S %Z",
@ -1791,22 +1783,21 @@ write_csvlog(ErrorData *edata)
appendStringInfoString(&buf, formatted_start_time); appendStringInfoString(&buf, formatted_start_time);
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* Virtual transaction id */
/* keep VXID format in sync with lockfuncs.c */
if (MyProc != NULL)
appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid);
appendStringInfoChar(&buf, ',');
/* Transaction id */ /* Transaction id */
appendStringInfo(&buf, "%u", GetTopTransactionIdIfAny()); appendStringInfo(&buf, "%u", GetTopTransactionIdIfAny());
appendStringInfoChar(&buf, ','); appendStringInfoChar(&buf, ',');
/* Error severity */ /* Error severity */
if (error_severity(edata->elevel) != NULL) appendStringInfo(&buf, "%s,", error_severity(edata->elevel));
appendStringInfo(&buf, "%s,", error_severity(edata->elevel));
else
appendStringInfoString(&buf, ",");
/* SQL state code */ /* SQL state code */
if (Log_error_verbosity >= PGERROR_VERBOSE) appendStringInfo(&buf, "%s,", unpack_sql_state(edata->sqlerrcode));
appendStringInfo(&buf, "%s",
unpack_sql_state(edata->sqlerrcode));
appendStringInfoChar(&buf, ',');
/* Error message and cursor position if any */ /* Error message and cursor position if any */
get_csv_error_message(&buf, edata); get_csv_error_message(&buf, edata);
@ -1830,7 +1821,7 @@ write_csvlog(ErrorData *edata)
static void static void
get_csv_error_message(StringInfo buf, ErrorData *edata) get_csv_error_message(StringInfo buf, ErrorData *edata)
{ {
char *msg = edata->message ? edata-> message : _("missing error text"); char *msg = edata->message ? edata->message : _("missing error text");
char c; char c;
appendStringInfoCharMacro(buf, '"'); appendStringInfoCharMacro(buf, '"');