mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Move any code specific to log_destination=csvlog to its own file
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
This commit is contained in:
parent
ac7c80758a
commit
bed6ed3de9
@ -14,6 +14,7 @@ include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = \
|
||||
assert.o \
|
||||
csvlog.o \
|
||||
elog.o
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk
|
||||
|
264
src/backend/utils/error/csvlog.c
Normal file
264
src/backend/utils/error/csvlog.c
Normal file
@ -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);
|
||||
}
|
@ -2792,237 +2792,6 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, '"');
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpack MAKE_SQLSTATE code. Note that this returns a pointer to a
|
||||
* static buffer.
|
||||
|
Loading…
Reference in New Issue
Block a user