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-2023, 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 "libpq/libpq.h"
20 #include "lib/stringinfo.h"
21 #include "miscadmin.h"
22 #include "postmaster/bgworker.h"
23 #include "postmaster/syslogger.h"
24 #include "storage/lock.h"
25 #include "storage/proc.h"
26 #include "tcop/tcopprot.h"
27 #include "utils/backend_status.h"
28 #include "utils/elog.h"
29 #include "utils/guc.h"
30 #include "utils/ps_status.h"
31 
32 
33 /*
34  * append a CSV'd version of a string to a StringInfo
35  * We use the PostgreSQL defaults for CSV, i.e. quote = escape = '"'
36  * If it's NULL, append nothing.
37  */
38 static inline void
40 {
41  const char *p = data;
42  char c;
43 
44  /* avoid confusing an empty string with NULL */
45  if (p == NULL)
46  return;
47 
49  while ((c = *p++) != '\0')
50  {
51  if (c == '"')
54  }
56 }
57 
58 /*
59  * write_csvlog -- Generate and write CSV log entry
60  *
61  * Constructs the error message, depending on the Errordata it gets, in a CSV
62  * format which is described in doc/src/sgml/config.sgml.
63  */
64 void
66 {
68  bool print_stmt = false;
69 
70  /* static counter for line numbers */
71  static long log_line_number = 0;
72 
73  /* has counter been reset in current process? */
74  static int log_my_pid = 0;
75 
76  /*
77  * This is one of the few places where we'd rather not inherit a static
78  * variable's value from the postmaster. But since we will, reset it when
79  * MyProcPid changes.
80  */
81  if (log_my_pid != MyProcPid)
82  {
83  log_line_number = 0;
84  log_my_pid = MyProcPid;
86  }
87  log_line_number++;
88 
90 
91  /* timestamp with milliseconds */
94 
95  /* username */
96  if (MyProcPort)
99 
100  /* database name */
101  if (MyProcPort)
103  appendStringInfoChar(&buf, ',');
104 
105  /* Process id */
106  if (MyProcPid != 0)
107  appendStringInfo(&buf, "%d", MyProcPid);
108  appendStringInfoChar(&buf, ',');
109 
110  /* Remote host and port */
112  {
113  appendStringInfoChar(&buf, '"');
115  if (MyProcPort->remote_port && MyProcPort->remote_port[0] != '\0')
116  {
117  appendStringInfoChar(&buf, ':');
119  }
120  appendStringInfoChar(&buf, '"');
121  }
122  appendStringInfoChar(&buf, ',');
123 
124  /* session id */
125  appendStringInfo(&buf, "%lx.%x", (long) MyStartTime, MyProcPid);
126  appendStringInfoChar(&buf, ',');
127 
128  /* Line number */
129  appendStringInfo(&buf, "%ld", log_line_number);
130  appendStringInfoChar(&buf, ',');
131 
132  /* PS display */
133  if (MyProcPort)
134  {
135  StringInfoData msgbuf;
136  const char *psdisp;
137  int displen;
138 
139  initStringInfo(&msgbuf);
140 
141  psdisp = get_ps_display(&displen);
142  appendBinaryStringInfo(&msgbuf, psdisp, displen);
143  appendCSVLiteral(&buf, msgbuf.data);
144 
145  pfree(msgbuf.data);
146  }
147  appendStringInfoChar(&buf, ',');
148 
149  /* session start timestamp */
151  appendStringInfoChar(&buf, ',');
152 
153  /* Virtual transaction id */
154  /* keep VXID format in sync with lockfuncs.c */
155  if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
157  appendStringInfoChar(&buf, ',');
158 
159  /* Transaction id */
161  appendStringInfoChar(&buf, ',');
162 
163  /* Error severity */
165  appendStringInfoChar(&buf, ',');
166 
167  /* SQL state code */
169  appendStringInfoChar(&buf, ',');
170 
171  /* errmessage */
172  appendCSVLiteral(&buf, edata->message);
173  appendStringInfoChar(&buf, ',');
174 
175  /* errdetail or errdetail_log */
176  if (edata->detail_log)
177  appendCSVLiteral(&buf, edata->detail_log);
178  else
179  appendCSVLiteral(&buf, edata->detail);
180  appendStringInfoChar(&buf, ',');
181 
182  /* errhint */
183  appendCSVLiteral(&buf, edata->hint);
184  appendStringInfoChar(&buf, ',');
185 
186  /* internal query */
188  appendStringInfoChar(&buf, ',');
189 
190  /* if printed internal query, print internal pos too */
191  if (edata->internalpos > 0 && edata->internalquery != NULL)
192  appendStringInfo(&buf, "%d", edata->internalpos);
193  appendStringInfoChar(&buf, ',');
194 
195  /* errcontext */
196  if (!edata->hide_ctx)
197  appendCSVLiteral(&buf, edata->context);
198  appendStringInfoChar(&buf, ',');
199 
200  /* user query --- only reported if not disabled by the caller */
201  print_stmt = check_log_of_query(edata);
202  if (print_stmt)
204  appendStringInfoChar(&buf, ',');
205  if (print_stmt && edata->cursorpos > 0)
206  appendStringInfo(&buf, "%d", edata->cursorpos);
207  appendStringInfoChar(&buf, ',');
208 
209  /* file error location */
211  {
212  StringInfoData msgbuf;
213 
214  initStringInfo(&msgbuf);
215 
216  if (edata->funcname && edata->filename)
217  appendStringInfo(&msgbuf, "%s, %s:%d",
218  edata->funcname, edata->filename,
219  edata->lineno);
220  else if (edata->filename)
221  appendStringInfo(&msgbuf, "%s:%d",
222  edata->filename, edata->lineno);
223  appendCSVLiteral(&buf, msgbuf.data);
224  pfree(msgbuf.data);
225  }
226  appendStringInfoChar(&buf, ',');
227 
228  /* application name */
229  if (application_name)
231 
232  appendStringInfoChar(&buf, ',');
233 
234  /* backend type */
236  appendStringInfoChar(&buf, ',');
237 
238  /* leader PID */
239  if (MyProc)
240  {
241  PGPROC *leader = MyProc->lockGroupLeader;
242 
243  /*
244  * Show the leader only for active parallel workers. This leaves out
245  * the leader of a parallel group.
246  */
247  if (leader && leader->pid != MyProcPid)
248  appendStringInfo(&buf, "%d", leader->pid);
249  }
250  appendStringInfoChar(&buf, ',');
251 
252  /* query id */
253  appendStringInfo(&buf, "%lld", (long long) pgstat_get_my_query_id());
254 
255  appendStringInfoChar(&buf, '\n');
256 
257  /* If in the syslogger process, try to write messages direct to file */
258  if (MyBackendType == B_LOGGER)
260  else
262 
263  pfree(buf.data);
264 }
uint64 pgstat_get_my_query_id(void)
#define InvalidBackendId
Definition: backendid.h:23
static void appendCSVLiteral(StringInfo buf, const char *data)
Definition: csvlog.c:39
void write_csvlog(ErrorData *edata)
Definition: csvlog.c:65
bool check_log_of_query(ErrorData *edata)
Definition: elog.c:2686
char * get_formatted_log_time(void)
Definition: elog.c:2612
int Log_error_verbosity
Definition: elog.c:111
const char * error_severity(int elevel)
Definition: elog.c:3628
const char * get_backend_type_for_log(void)
Definition: elog.c:2709
void write_pipe_chunks(char *data, int len, int dest)
Definition: elog.c:3387
char * unpack_sql_state(int sql_state)
Definition: elog.c:3124
char * get_formatted_start_time(void)
Definition: elog.c:2662
#define _(x)
Definition: elog.c:91
void reset_formatted_start_time(void)
Definition: elog.c:2650
@ PGERROR_VERBOSE
Definition: elog.h:481
#define LOG_DESTINATION_CSVLOG
Definition: elog.h:495
int MyProcPid
Definition: globals.c:44
struct Port * MyProcPort
Definition: globals.c:47
pg_time_t MyStartTime
Definition: globals.c:45
char * application_name
Definition: guc_tables.c:541
void pfree(void *pointer)
Definition: mcxt.c:1456
@ B_LOGGER
Definition: miscadmin.h:336
BackendType MyBackendType
Definition: miscinit.c:63
const void * data
static char * buf
Definition: pg_test_fsync.c:67
const char * debug_query_string
Definition: postgres.c:85
char * c
const char * get_ps_display(int *displen)
Definition: ps_status.c:505
PGPROC * MyProc
Definition: proc.c:66
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:227
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128
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:162
LocalTransactionId lxid
Definition: proc.h:183
BackendId backendId
Definition: proc.h:197
int pid
Definition: proc.h:186
PGPROC * lockGroupLeader
Definition: proc.h:295
char * user_name
Definition: libpq-be.h:167
char * remote_port
Definition: libpq-be.h:158
char * database_name
Definition: libpq-be.h:166
char * remote_host
Definition: libpq-be.h:153
void write_syslogger_file(const char *buffer, int count, int destination)
Definition: syslogger.c:1143
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:432