mirror of https://github.com/postgres/postgres
The recent refactoring done in ac7c807
makes this move possible and
simple, as this just moves some code around. This reduces the size of
elog.c by 7%.
Author: Michael Paquier, Sehrope Sarkuni
Reviewed-by: Nathan Bossart
Discussion: https://postgr.es/m/CAH7T-aqswBM6JWe4pDehi1uOiufqe06DJWaU5=X7dDLyqUExHg@mail.gmail.com
simply moves the routines related to csvlog into their own file
pull/76/head
parent
ac7c80758a
commit
bed6ed3de9
@ -0,0 +1,264 @@ |
|||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* |
||||||
|
* csvlog.c |
||||||
|
* CSV logging |
||||||
|
* |
||||||
|
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group |
||||||
|
* Portions Copyright (c) 1994, Regents of the University of Californi |
||||||
|
* |
||||||
|
* |
||||||
|
* IDENTIFICATION |
||||||
|
* src/backend/utils/error/csvlog.c |
||||||
|
* |
||||||
|
*------------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "postgres.h" |
||||||
|
|
||||||
|
#include "access/xact.h" |
||||||
|
#include "libpq/libpq.h" |
||||||
|
#include "lib/stringinfo.h" |
||||||
|
#include "miscadmin.h" |
||||||
|
#include "postmaster/bgworker.h" |
||||||
|
#include "postmaster/syslogger.h" |
||||||
|
#include "storage/lock.h" |
||||||
|
#include "storage/proc.h" |
||||||
|
#include "tcop/tcopprot.h" |
||||||
|
#include "utils/backend_status.h" |
||||||
|
#include "utils/elog.h" |
||||||
|
#include "utils/guc.h" |
||||||
|
#include "utils/ps_status.h" |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* append a CSV'd version of a string to a StringInfo |
||||||
|
* We use the PostgreSQL defaults for CSV, i.e. quote = escape = '"' |
||||||
|
* If it's NULL, append nothing. |
||||||
|
*/ |
||||||
|
static inline void |
||||||
|
appendCSVLiteral(StringInfo buf, const char *data) |
||||||
|
{ |
||||||
|
const char *p = data; |
||||||
|
char c; |
||||||
|
|
||||||
|
/* avoid confusing an empty string with NULL */ |
||||||
|
if (p == NULL) |
||||||
|
return; |
||||||
|
|
||||||
|
appendStringInfoCharMacro(buf, '"'); |
||||||
|
while ((c = *p++) != '\0') |
||||||
|
{ |
||||||
|
if (c == '"') |
||||||
|
appendStringInfoCharMacro(buf, '"'); |
||||||
|
appendStringInfoCharMacro(buf, c); |
||||||
|
} |
||||||
|
appendStringInfoCharMacro(buf, '"'); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* write_csvlog -- Generate and write CSV log entry |
||||||
|
* |
||||||
|
* Constructs the error message, depending on the Errordata it gets, in a CSV |
||||||
|
* format which is described in doc/src/sgml/config.sgml. |
||||||
|
*/ |
||||||
|
void |
||||||
|
write_csvlog(ErrorData *edata) |
||||||
|
{ |
||||||
|
StringInfoData buf; |
||||||
|
bool print_stmt = false; |
||||||
|
|
||||||
|
/* static counter for line numbers */ |
||||||
|
static long log_line_number = 0; |
||||||
|
|
||||||
|
/* has counter been reset in current process? */ |
||||||
|
static int log_my_pid = 0; |
||||||
|
|
||||||
|
/*
|
||||||
|
* 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; |
||||||
|
reset_formatted_start_time(); |
||||||
|
} |
||||||
|
log_line_number++; |
||||||
|
|
||||||
|
initStringInfo(&buf); |
||||||
|
|
||||||
|
/* timestamp with milliseconds */ |
||||||
|
appendStringInfoString(&buf, get_formatted_log_time()); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* username */ |
||||||
|
if (MyProcPort) |
||||||
|
appendCSVLiteral(&buf, MyProcPort->user_name); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* database name */ |
||||||
|
if (MyProcPort) |
||||||
|
appendCSVLiteral(&buf, MyProcPort->database_name); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Process id */ |
||||||
|
if (MyProcPid != 0) |
||||||
|
appendStringInfo(&buf, "%d", MyProcPid); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Remote host and port */ |
||||||
|
if (MyProcPort && MyProcPort->remote_host) |
||||||
|
{ |
||||||
|
appendStringInfoChar(&buf, '"'); |
||||||
|
appendStringInfoString(&buf, MyProcPort->remote_host); |
||||||
|
if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0') |
||||||
|
{ |
||||||
|
appendStringInfoChar(&buf, ':'); |
||||||
|
appendStringInfoString(&buf, MyProcPort->remote_port); |
||||||
|
} |
||||||
|
appendStringInfoChar(&buf, '"'); |
||||||
|
} |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* session id */ |
||||||
|
appendStringInfo(&buf, "%lx.%x", (long) MyStartTime, MyProcPid); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Line number */ |
||||||
|
appendStringInfo(&buf, "%ld", log_line_number); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* PS display */ |
||||||
|
if (MyProcPort) |
||||||
|
{ |
||||||
|
StringInfoData msgbuf; |
||||||
|
const char *psdisp; |
||||||
|
int displen; |
||||||
|
|
||||||
|
initStringInfo(&msgbuf); |
||||||
|
|
||||||
|
psdisp = get_ps_display(&displen); |
||||||
|
appendBinaryStringInfo(&msgbuf, psdisp, displen); |
||||||
|
appendCSVLiteral(&buf, msgbuf.data); |
||||||
|
|
||||||
|
pfree(msgbuf.data); |
||||||
|
} |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* session start timestamp */ |
||||||
|
appendStringInfoString(&buf, get_formatted_start_time()); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Virtual transaction id */ |
||||||
|
/* keep VXID format in sync with lockfuncs.c */ |
||||||
|
if (MyProc != NULL && MyProc->backendId != InvalidBackendId) |
||||||
|
appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Transaction id */ |
||||||
|
appendStringInfo(&buf, "%u", GetTopTransactionIdIfAny()); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* Error severity */ |
||||||
|
appendStringInfoString(&buf, _(error_severity(edata->elevel))); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* SQL state code */ |
||||||
|
appendStringInfoString(&buf, unpack_sql_state(edata->sqlerrcode)); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* errmessage */ |
||||||
|
appendCSVLiteral(&buf, edata->message); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* errdetail or errdetail_log */ |
||||||
|
if (edata->detail_log) |
||||||
|
appendCSVLiteral(&buf, edata->detail_log); |
||||||
|
else |
||||||
|
appendCSVLiteral(&buf, edata->detail); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* errhint */ |
||||||
|
appendCSVLiteral(&buf, edata->hint); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* internal query */ |
||||||
|
appendCSVLiteral(&buf, edata->internalquery); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* if printed internal query, print internal pos too */ |
||||||
|
if (edata->internalpos > 0 && edata->internalquery != NULL) |
||||||
|
appendStringInfo(&buf, "%d", edata->internalpos); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* errcontext */ |
||||||
|
if (!edata->hide_ctx) |
||||||
|
appendCSVLiteral(&buf, edata->context); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* user query --- only reported if not disabled by the caller */ |
||||||
|
print_stmt = check_log_of_query(edata); |
||||||
|
if (print_stmt) |
||||||
|
appendCSVLiteral(&buf, debug_query_string); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
if (print_stmt && edata->cursorpos > 0) |
||||||
|
appendStringInfo(&buf, "%d", edata->cursorpos); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* file error location */ |
||||||
|
if (Log_error_verbosity >= PGERROR_VERBOSE) |
||||||
|
{ |
||||||
|
StringInfoData msgbuf; |
||||||
|
|
||||||
|
initStringInfo(&msgbuf); |
||||||
|
|
||||||
|
if (edata->funcname && edata->filename) |
||||||
|
appendStringInfo(&msgbuf, "%s, %s:%d", |
||||||
|
edata->funcname, edata->filename, |
||||||
|
edata->lineno); |
||||||
|
else if (edata->filename) |
||||||
|
appendStringInfo(&msgbuf, "%s:%d", |
||||||
|
edata->filename, edata->lineno); |
||||||
|
appendCSVLiteral(&buf, msgbuf.data); |
||||||
|
pfree(msgbuf.data); |
||||||
|
} |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* application name */ |
||||||
|
if (application_name) |
||||||
|
appendCSVLiteral(&buf, application_name); |
||||||
|
|
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* backend type */ |
||||||
|
appendCSVLiteral(&buf, get_backend_type_for_log()); |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* leader PID */ |
||||||
|
if (MyProc) |
||||||
|
{ |
||||||
|
PGPROC *leader = MyProc->lockGroupLeader; |
||||||
|
|
||||||
|
/*
|
||||||
|
* Show the leader only for active parallel workers. This leaves out |
||||||
|
* the leader of a parallel group. |
||||||
|
*/ |
||||||
|
if (leader && leader->pid != MyProcPid) |
||||||
|
appendStringInfo(&buf, "%d", leader->pid); |
||||||
|
} |
||||||
|
appendStringInfoChar(&buf, ','); |
||||||
|
|
||||||
|
/* query id */ |
||||||
|
appendStringInfo(&buf, "%lld", (long long) pgstat_get_my_query_id()); |
||||||
|
|
||||||
|
appendStringInfoChar(&buf, '\n'); |
||||||
|
|
||||||
|
/* If in the syslogger process, try to write messages direct to file */ |
||||||
|
if (MyBackendType == B_LOGGER) |
||||||
|
write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_CSVLOG); |
||||||
|
else |
||||||
|
write_pipe_chunks(buf.data, buf.len, LOG_DESTINATION_CSVLOG); |
||||||
|
|
||||||
|
pfree(buf.data); |
||||||
|
} |
Loading…
Reference in new issue