PostgreSQL Source Code  git master
csvlog.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * csvlog.c
4  * CSV logging
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/error/csvlog.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include "access/xact.h"
19 #include "lib/stringinfo.h"
20 #include "libpq/libpq-be.h"
21 #include "miscadmin.h"
22 #include "postmaster/syslogger.h"
23 #include "storage/lock.h"
24 #include "storage/proc.h"
25 #include "tcop/tcopprot.h"
26 #include "utils/backend_status.h"
27 #include "utils/guc.h"
28 #include "utils/ps_status.h"
29 
30 
31 /*
32  * append a CSV'd version of a string to a StringInfo
33  * We use the PostgreSQL defaults for CSV, i.e. quote = escape = '"'
34  * If it's NULL, append nothing.
35  */
36 static inline void
38 {
39  const char *p = data;
40  char c;
41 
42  /* avoid confusing an empty string with NULL */
43  if (p == NULL)
44  return;
45 
47  while ((c = *p++) != '\0')
48  {
49  if (c == '"')
52  }
54 }
55 
56 /*
57  * write_csvlog -- Generate and write CSV log entry
58  *
59  * Constructs the error message, depending on the Errordata it gets, in a CSV
60  * format which is described in doc/src/sgml/config.sgml.
61  */
62 void
64 {
66  bool print_stmt = false;
67 
68  /* static counter for line numbers */
69  static long log_line_number = 0;
70 
71  /* has counter been reset in current process? */
72  static int log_my_pid = 0;
73 
74  /*
75  * This is one of the few places where we'd rather not inherit a static
76  * variable's value from the postmaster. But since we will, reset it when
77  * MyProcPid changes.
78  */
79  if (log_my_pid != MyProcPid)
80  {
81  log_line_number = 0;
82  log_my_pid = MyProcPid;
84  }
85  log_line_number++;
86 
88 
89  /* timestamp with milliseconds */
92 
93  /* username */
94  if (MyProcPort)
97 
98  /* database name */
99  if (MyProcPort)
101  appendStringInfoChar(&buf, ',');
102 
103  /* Process id */
104  if (MyProcPid != 0)
105  appendStringInfo(&buf, "%d", MyProcPid);
106  appendStringInfoChar(&buf, ',');
107 
108  /* Remote host and port */
110  {
111  appendStringInfoChar(&buf, '"');
113  if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
114  {
115  appendStringInfoChar(&buf, ':');
117  }
118  appendStringInfoChar(&buf, '"');
119  }
120  appendStringInfoChar(&buf, ',');
121 
122  /* session id */
123  appendStringInfo(&buf, "%lx.%x", (long) MyStartTime, MyProcPid);
124  appendStringInfoChar(&buf, ',');
125 
126  /* Line number */
127  appendStringInfo(&buf, "%ld", log_line_number);
128  appendStringInfoChar(&buf, ',');
129 
130  /* PS display */
131  if (MyProcPort)
132  {
133  StringInfoData msgbuf;
134  const char *psdisp;
135  int displen;
136 
137  initStringInfo(&msgbuf);
138 
139  psdisp = get_ps_display(&displen);
140  appendBinaryStringInfo(&msgbuf, psdisp, displen);
141  appendCSVLiteral(&buf, msgbuf.data);
142 
143  pfree(msgbuf.data);
144  }
145  appendStringInfoChar(&buf, ',');
146 
147  /* session start timestamp */
149  appendStringInfoChar(&buf, ',');
150 
151  /* Virtual transaction id */
152  /* keep VXID format in sync with lockfuncs.c */
153  if (MyProc != NULL && MyProc->vxid.procNumber != INVALID_PROC_NUMBER)
155  appendStringInfoChar(&buf, ',');
156 
157  /* Transaction id */
159  appendStringInfoChar(&buf, ',');
160 
161  /* Error severity */
163  appendStringInfoChar(&buf, ',');
164 
165  /* SQL state code */
167  appendStringInfoChar(&buf, ',');
168 
169  /* errmessage */
170  appendCSVLiteral(&buf, edata->message);
171  appendStringInfoChar(&buf, ',');
172 
173  /* errdetail or errdetail_log */
174  if (edata->detail_log)
175  appendCSVLiteral(&buf, edata->detail_log);
176  else
177  appendCSVLiteral(&buf, edata->detail);
178  appendStringInfoChar(&buf, ',');
179 
180  /* errhint */
181  appendCSVLiteral(&buf, edata->hint);
182  appendStringInfoChar(&buf, ',');
183 
184  /* internal query */
186  appendStringInfoChar(&buf, ',');
187 
188  /* if printed internal query, print internal pos too */
189  if (edata->internalpos > 0 && edata->internalquery != NULL)
190  appendStringInfo(&buf, "%d", edata->internalpos);
191  appendStringInfoChar(&buf, ',');
192 
193  /* errcontext */
194  if (!edata->hide_ctx)
195  appendCSVLiteral(&buf, edata->context);
196  appendStringInfoChar(&buf, ',');
197 
198  /* user query --- only reported if not disabled by the caller */
199  print_stmt = check_log_of_query(edata);
200  if (print_stmt)
202  appendStringInfoChar(&buf, ',');
203  if (print_stmt && edata->cursorpos > 0)
204  appendStringInfo(&buf, "%d", edata->cursorpos);
205  appendStringInfoChar(&buf, ',');
206 
207  /* file error location */
209  {
210  StringInfoData msgbuf;
211 
212  initStringInfo(&msgbuf);
213 
214  if (edata->funcname && edata->filename)
215  appendStringInfo(&msgbuf, "%s, %s:%d",
216  edata->funcname, edata->filename,
217  edata->lineno);
218  else if (edata->filename)
219  appendStringInfo(&msgbuf, "%s:%d",
220  edata->filename, edata->lineno);
221  appendCSVLiteral(&buf, msgbuf.data);
222  pfree(msgbuf.data);
223  }
224  appendStringInfoChar(&buf, ',');
225 
226  /* application name */
227  if (application_name)
229 
230  appendStringInfoChar(&buf, ',');
231 
232  /* backend type */
234  appendStringInfoChar(&buf, ',');
235 
236  /* leader PID */
237  if (MyProc)
238  {
239  PGPROC *leader = MyProc->lockGroupLeader;
240 
241  /*
242  * Show the leader only for active parallel workers. This leaves out
243  * the leader of a parallel group.
244  */
245  if (leader && leader->pid != MyProcPid)
246  appendStringInfo(&buf, "%d", leader->pid);
247  }
248  appendStringInfoChar(&buf, ',');
249 
250  /* query id */
251  appendStringInfo(&buf, "%lld", (long long) pgstat_get_my_query_id());
252 
253  appendStringInfoChar(&buf, '\n');
254 
255  /* If in the syslogger process, try to write messages direct to file */
256  if (MyBackendType == B_LOGGER)
258  else
260 
261  pfree(buf.data);
262 }
uint64 pgstat_get_my_query_id(void)
static void appendCSVLiteral(StringInfo buf, const char *data)
Definition: csvlog.c:37
void write_csvlog(ErrorData *edata)
Definition: csvlog.c:63
bool check_log_of_query(ErrorData *edata)
Definition: elog.c:2697
char * get_formatted_log_time(void)
Definition: elog.c:2623
int Log_error_verbosity
Definition: elog.c:110
const char * error_severity(int elevel)
Definition: elog.c:3636
const char * get_backend_type_for_log(void)
Definition: elog.c:2720
void write_pipe_chunks(char *data, int len, int dest)
Definition: elog.c:3395
char * unpack_sql_state(int sql_state)
Definition: elog.c:3135
char * get_formatted_start_time(void)
Definition: elog.c:2673
#define _(x)
Definition: elog.c:90
void reset_formatted_start_time(void)
Definition: elog.c:2661
@ PGERROR_VERBOSE
Definition: elog.h:481
#define LOG_DESTINATION_CSVLOG
Definition: elog.h:495
int MyProcPid
Definition: globals.c:45
struct Port * MyProcPort
Definition: globals.c:49
pg_time_t MyStartTime
Definition: globals.c:46
char * application_name
Definition: guc_tables.c:546
void pfree(void *pointer)
Definition: mcxt.c:1520
@ B_LOGGER
Definition: miscadmin.h:367
BackendType MyBackendType
Definition: miscinit.c:63
const void * data
static char * buf
Definition: pg_test_fsync.c:73
const char * debug_query_string
Definition: postgres.c:87
char * c
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
const char * get_ps_display(int *displen)
Definition: ps_status.c:530
PGPROC * MyProc
Definition: proc.c:66
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
int internalpos
Definition: elog.h:452
char * context
Definition: elog.h:443
char * internalquery
Definition: elog.h:453
int sqlerrcode
Definition: elog.h:438
const char * filename
Definition: elog.h:433
int elevel
Definition: elog.h:428
char * detail
Definition: elog.h:440
const char * funcname
Definition: elog.h:435
char * message
Definition: elog.h:439
char * detail_log
Definition: elog.h:441
int lineno
Definition: elog.h:434
char * hint
Definition: elog.h:442
bool hide_ctx
Definition: elog.h:432
int cursorpos
Definition: elog.h:451
Definition: proc.h:157
LocalTransactionId lxid
Definition: proc.h:196
ProcNumber procNumber
Definition: proc.h:191
int pid
Definition: proc.h:178
PGPROC * lockGroupLeader
Definition: proc.h:300
struct PGPROC::@117 vxid
char * user_name
Definition: libpq-be.h:152
char * remote_port
Definition: libpq-be.h:144
char * database_name
Definition: libpq-be.h:151
char * remote_host
Definition: libpq-be.h:139
void write_syslogger_file(const char *buffer, int count, int destination)
Definition: syslogger.c:1094
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:438