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