PostgreSQL Source Code git master
Loading...
Searching...
No Matches
logging.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 * Logging framework for frontend programs
3 *
4 * Copyright (c) 2018-2026, PostgreSQL Global Development Group
5 *
6 * src/common/logging.c
7 *
8 *-------------------------------------------------------------------------
9 */
10
11#ifndef FRONTEND
12#error "This file is not expected to be compiled for backend code"
13#endif
14
15#include "postgres_fe.h"
16
17#include <unistd.h>
18
19#include "common/logging.h"
20
22
23static const char *progname;
24static int log_flags;
25
27static void (*log_locus_callback) (const char **, uint64 *);
28
30
31static const char *sgr_error = NULL;
32static const char *sgr_warning = NULL;
33static const char *sgr_note = NULL;
34static const char *sgr_locus = NULL;
35
36#define SGR_ERROR_DEFAULT "01;31"
37#define SGR_WARNING_DEFAULT "01;35"
38#define SGR_NOTE_DEFAULT "01;36"
39#define SGR_LOCUS_DEFAULT "01"
40
41#define ANSI_ESCAPE_FMT "\x1b[%sm"
42#define ANSI_ESCAPE_RESET "\x1b[0m"
43
44#ifdef WIN32
45
46#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
47#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
48#endif
49
50/*
51 * Attempt to enable VT100 sequence processing for colorization on Windows.
52 * If current environment is not VT100-compatible or if this mode could not
53 * be enabled, return false.
54 */
55static bool
57{
58 /* Check stderr */
60 DWORD dwMode = 0;
61
63 return false;
64
65 /*
66 * Look for the current console settings and check if VT100 is already
67 * enabled.
68 */
70 return false;
72 return true;
73
76 return false;
77 return true;
78}
79#endif /* WIN32 */
80
81/*
82 * This should be called before any output happens.
83 */
84void
86{
87 const char *pg_color_env = getenv("PG_COLOR");
88 bool log_color = false;
89 bool color_terminal = isatty(fileno(stderr));
90
91#ifdef WIN32
92
93 /*
94 * On Windows, check if environment is VT100-compatible if using a
95 * terminal.
96 */
99#endif
100
101 /* usually the default, but not on Windows */
103
106
107 if (pg_color_env)
108 {
109 if (strcmp(pg_color_env, "always") == 0 ||
110 (strcmp(pg_color_env, "auto") == 0 && color_terminal))
111 log_color = true;
112 }
113
114 if (log_color)
115 {
116 const char *pg_colors_env = getenv("PG_COLORS");
117
118 if (pg_colors_env)
119 {
120 char *colors = strdup(pg_colors_env);
121
122 if (colors)
123 {
124 char *token;
125 char *cp = colors;
126
127 while ((token = strsep(&cp, ":")))
128 {
129 char *e = strchr(token, '=');
130
131 if (e)
132 {
133 char *name;
134 char *value;
135
136 *e = '\0';
137 name = token;
138 value = e + 1;
139
140 if (strcmp(name, "error") == 0)
142 if (strcmp(name, "warning") == 0)
144 if (strcmp(name, "note") == 0)
146 if (strcmp(name, "locus") == 0)
148 }
149 }
150
151 free(colors);
152 }
153 }
154 else
155 {
160 }
161 }
162}
163
164/*
165 * Change the logging flags.
166 */
167void
172
173/*
174 * pg_logging_init sets the default log level to INFO. Programs that prefer
175 * a different default should use this to set it, immediately afterward.
176 */
177void
182
183/*
184 * Command line switches such as --verbose should invoke this.
185 */
186void
188{
189 /*
190 * The enum values are chosen such that we have to decrease __pg_log_level
191 * in order to become more verbose.
192 */
195}
196
197void
199{
200 log_pre_callback = cb;
201}
202
203void
204pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno))
205{
207}
208
209void
214
215void
220
221void
223 const char *pg_restrict fmt,...)
224{
225 va_list ap;
226
227 va_start(ap, fmt);
228 pg_log_generic_v(level, part, fmt, ap);
229 va_end(ap);
230}
231
232void
234 const char *pg_restrict fmt, va_list ap)
235{
236 int save_errno = errno;
237 const char *filename = NULL;
238 uint64 lineno = 0;
239 va_list ap2;
240 size_t required_len;
241 char *buf;
242
244 Assert(level);
245 Assert(fmt);
246 Assert(fmt[strlen(fmt) - 1] != '\n');
247
248 /* Do nothing if log level is too low. */
249 if (level < __pg_log_level)
250 return;
251
252 /*
253 * Flush stdout before output to stderr, to ensure sync even when stdout
254 * is buffered.
255 */
256 fflush(stdout);
257
260
262 log_locus_callback(&filename, &lineno);
263
264 fmt = _(fmt);
265
267 {
268 if (sgr_locus)
271 fprintf(stderr, "%s:", progname);
272 if (filename)
273 {
274 fprintf(stderr, "%s:", filename);
275 if (lineno > 0)
276 fprintf(stderr, UINT64_FORMAT ":", lineno);
277 }
278 fprintf(stderr, " ");
279 if (sgr_locus)
281 }
282
284 {
285 switch (part)
286 {
287 case PG_LOG_PRIMARY:
288 switch (level)
289 {
290 case PG_LOG_ERROR:
291 if (sgr_error)
293 fprintf(stderr, _("error: "));
294 if (log_logfile)
295 fprintf(log_logfile, _("error: "));
296 if (sgr_error)
298 break;
299 case PG_LOG_WARNING:
300 if (sgr_warning)
302 fprintf(stderr, _("warning: "));
303 if (log_logfile)
304 fprintf(log_logfile, _("warning: "));
305 if (sgr_warning)
307 break;
308 default:
309 break;
310 }
311 break;
312 case PG_LOG_DETAIL:
313 if (sgr_note)
315 fprintf(stderr, _("detail: "));
316 if (log_logfile)
317 fprintf(log_logfile, _("detail: "));
318 if (sgr_note)
320 break;
321 case PG_LOG_HINT:
322 if (sgr_note)
324 fprintf(stderr, _("hint: "));
325 if (log_logfile)
326 fprintf(log_logfile, _("hint: "));
327 if (sgr_note)
329 break;
330 }
331 }
332
334
335 va_copy(ap2, ap);
336 required_len = vsnprintf(NULL, 0, fmt, ap2) + 1;
337 va_end(ap2);
338
340
341 errno = save_errno; /* malloc might change errno */
342
343 if (!buf)
344 {
345 /* memory trouble, just print what we can and get out of here */
347 return;
348 }
349
351
352 /* strip one newline, for PQerrorMessage() */
353 if (required_len >= 2 && buf[required_len - 2] == '\n')
354 buf[required_len - 2] = '\0';
355
356 fprintf(stderr, "%s\n", buf);
357 if (log_logfile)
358 {
359 fprintf(log_logfile, "%s\n", buf);
361 }
362
363 free(buf);
364}
#define Assert(condition)
Definition c.h:943
#define UINT64_FORMAT
Definition c.h:635
uint64_t uint64
Definition c.h:625
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
#define _(x)
Definition elog.c:96
void * pg_malloc_extended(size_t size, int flags)
Definition fe_memutils.c:59
#define MCXT_ALLOC_NO_OOM
Definition fe_memutils.h:29
#define token
static struct @177 value
void pg_logging_unset_logfile(void)
Definition logging.c:216
void pg_logging_increase_verbosity(void)
Definition logging.c:187
static int log_flags
Definition logging.c:24
#define SGR_WARNING_DEFAULT
Definition logging.c:37
void pg_logging_set_logfile(FILE *logfile)
Definition logging.c:210
#define SGR_NOTE_DEFAULT
Definition logging.c:38
static const char * sgr_note
Definition logging.c:33
static const char * sgr_error
Definition logging.c:31
#define SGR_LOCUS_DEFAULT
Definition logging.c:39
void pg_logging_init(const char *argv0)
Definition logging.c:85
#define SGR_ERROR_DEFAULT
Definition logging.c:36
void pg_logging_set_locus_callback(void(*cb)(const char **filename, uint64 *lineno))
Definition logging.c:204
static const char * sgr_warning
Definition logging.c:32
static void(* log_pre_callback)(void)
Definition logging.c:26
static void(* log_locus_callback)(const char **, uint64 *)
Definition logging.c:27
static const char * sgr_locus
Definition logging.c:34
void pg_logging_config(int new_flags)
Definition logging.c:168
void pg_logging_set_level(enum pg_log_level new_level)
Definition logging.c:178
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt, va_list ap)
Definition logging.c:233
void pg_logging_set_pre_callback(void(*cb)(void))
Definition logging.c:198
static const char * progname
Definition logging.c:23
enum pg_log_level __pg_log_level
Definition logging.c:21
static FILE * log_logfile
Definition logging.c:29
#define ANSI_ESCAPE_RESET
Definition logging.c:42
void pg_log_generic(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt,...)
Definition logging.c:222
#define ANSI_ESCAPE_FMT
Definition logging.c:41
#define PG_LOG_FLAG_TERSE
Definition logging.h:86
pg_log_part
Definition logging.h:62
@ PG_LOG_PRIMARY
Definition logging.h:67
@ PG_LOG_HINT
Definition logging.h:79
@ PG_LOG_DETAIL
Definition logging.h:73
pg_log_level
Definition logging.h:17
@ PG_LOG_INFO
Definition logging.h:33
@ PG_LOG_NOTSET
Definition logging.h:21
@ PG_LOG_WARNING
Definition logging.h:38
@ PG_LOG_ERROR
Definition logging.h:43
static char * argv0
Definition pg_ctl.c:94
static char * filename
Definition pg_dumpall.c:133
static FILE * logfile
Definition pg_regress.c:128
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define vsnprintf
Definition port.h:259
char * strsep(char **stringp, const char *delim)
Definition strsep.c:49
#define vfprintf
Definition port.h:263
const char * get_progname(const char *argv0)
Definition path.c:652
e
static int fb(int x)
#define free(a)
const char * name