summaryrefslogtreecommitdiffstats
path: root/src/include/common/logging.h
blob: 99e888af93d394a3b315870b7410a0b24757466e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*-------------------------------------------------------------------------
 * Logging framework for frontend programs
 *
 * Copyright (c) 2018-2023, PostgreSQL Global Development Group
 *
 * src/include/common/logging.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef COMMON_LOGGING_H
#define COMMON_LOGGING_H

/*
 * Log levels are informational only.  They do not affect program flow.
 */
enum pg_log_level
{
	/*
	 * Not initialized yet (not to be used as an actual message log level).
	 */
	PG_LOG_NOTSET = 0,

	/*
	 * Low level messages that are normally off by default.
	 */
	PG_LOG_DEBUG,

	/*
	 * Any program messages that go to stderr, shown by default.  (The
	 * program's normal output should go to stdout and not use the logging
	 * system.)
	 */
	PG_LOG_INFO,

	/*
	 * Warnings and "almost" errors, depends on the program
	 */
	PG_LOG_WARNING,

	/*
	 * Errors
	 */
	PG_LOG_ERROR,

	/*
	 * Turn all logging off (not to be used as an actual message log level).
	 */
	PG_LOG_OFF,
};

/*
 * __pg_log_level is the minimum log level that will actually be shown.
 */
extern enum pg_log_level __pg_log_level;

/*
 * A log message can have several parts.  The primary message is required,
 * others are optional.  When emitting multiple parts, do so in the order of
 * this enum, for consistency.
 */
enum pg_log_part
{
	/*
	 * The primary message.  Try to keep it to one line; follow the backend's
	 * style guideline for primary messages.
	 */
	PG_LOG_PRIMARY,

	/*
	 * Additional detail.  Follow the backend's style guideline for detail
	 * messages.
	 */
	PG_LOG_DETAIL,

	/*
	 * Hint (not guaranteed correct) about how to fix the problem.  Follow the
	 * backend's style guideline for hint messages.
	 */
	PG_LOG_HINT,
};

/*
 * Kind of a hack to be able to produce the psql output exactly as required by
 * the regression tests.
 */
#define PG_LOG_FLAG_TERSE	1

void		pg_logging_init(const char *argv0);
void		pg_logging_config(int new_flags);
void		pg_logging_set_level(enum pg_log_level new_level);
void		pg_logging_increase_verbosity(void);
void		pg_logging_set_pre_callback(void (*cb) (void));
void		pg_logging_set_locus_callback(void (*cb) (const char **filename, uint64 *lineno));

void		pg_log_generic(enum pg_log_level level, enum pg_log_part part,
						   const char *pg_restrict fmt,...)
			pg_attribute_printf(3, 4);
void		pg_log_generic_v(enum pg_log_level level, enum pg_log_part part,
							 const char *pg_restrict fmt, va_list ap)
			pg_attribute_printf(3, 0);

/*
 * Preferred style is to use these macros to perform logging; don't call
 * pg_log_generic[_v] directly, except perhaps in error interface code.
 */
#define pg_log_error(...) \
	pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__)

#define pg_log_error_detail(...) \
	pg_log_generic(PG_LOG_ERROR, PG_LOG_DETAIL, __VA_ARGS__)

#define pg_log_error_hint(...) \
	pg_log_generic(PG_LOG_ERROR, PG_LOG_HINT, __VA_ARGS__)

#define pg_log_warning(...) \
	pg_log_generic(PG_LOG_WARNING, PG_LOG_PRIMARY, __VA_ARGS__)

#define pg_log_warning_detail(...) \
	pg_log_generic(PG_LOG_WARNING, PG_LOG_DETAIL, __VA_ARGS__)

#define pg_log_warning_hint(...) \
	pg_log_generic(PG_LOG_WARNING, PG_LOG_HINT, __VA_ARGS__)

#define pg_log_info(...) \
	pg_log_generic(PG_LOG_INFO, PG_LOG_PRIMARY, __VA_ARGS__)

#define pg_log_info_detail(...) \
	pg_log_generic(PG_LOG_INFO, PG_LOG_DETAIL, __VA_ARGS__)

#define pg_log_info_hint(...) \
	pg_log_generic(PG_LOG_INFO, PG_LOG_HINT, __VA_ARGS__)

#define pg_log_debug(...) do { \
		if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
			pg_log_generic(PG_LOG_DEBUG, PG_LOG_PRIMARY, __VA_ARGS__); \
	} while(0)

#define pg_log_debug_detail(...) do { \
		if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
			pg_log_generic(PG_LOG_DEBUG, PG_LOG_DETAIL, __VA_ARGS__); \
	} while(0)

#define pg_log_debug_hint(...) do { \
		if (unlikely(__pg_log_level <= PG_LOG_DEBUG)) \
			pg_log_generic(PG_LOG_DEBUG, PG_LOG_HINT, __VA_ARGS__); \
	} while(0)

/*
 * A common shortcut: pg_log_error() and immediately exit(1).
 */
#define pg_fatal(...) do { \
		pg_log_generic(PG_LOG_ERROR, PG_LOG_PRIMARY, __VA_ARGS__); \
		exit(1); \
	} while(0)

#endif							/* COMMON_LOGGING_H */