forked from aarond10/https_dns_proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogging.c
More file actions
228 lines (197 loc) · 6.59 KB
/
logging.c
File metadata and controls
228 lines (197 loc) · 6.59 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/time.h>
#include <syslog.h>
#include <unistd.h>
#include "logging.h"
#include "ring_buffer.h"
#define LOG_IDENT "https_dns_proxy"
// logs of this severity or higher are flushed immediately after write
#define LOG_FLUSH_LEVEL DOH_LOG_WARNING
enum {
LOG_LINE_SIZE = 2048 // Log line should be at least 100
};
static int use_syslog = 0;
static FILE *logfile = NULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static int loglevel = DOH_LOG_ERROR; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static ev_timer logging_timer; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static ev_signal sigusr2; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static ev_async flight_recorder_async; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static struct ev_loop *logging_loop = NULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static struct ring_buffer * flight_recorder = NULL; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
// 将syslog优先级映射到本地severity
static inline int severity_to_syslog(int severity) {
switch (severity) {
case DOH_LOG_DEBUG: return LOG_DEBUG;
case DOH_LOG_INFO: return LOG_INFO;
case DOH_LOG_WARNING: return LOG_WARNING;
case DOH_LOG_ERROR: return EV_ERROR;
case DOH_LOG_STATS: return LOG_INFO; // 统计信息作为info
case DOH_LOG_FATAL: return LOG_CRIT;
default: return LOG_INFO;
}
}
static const char * const SeverityStr[] = {
"[D]",
"[I]",
"[W]",
"[E]",
"[S]",
"[F]"
};
void logging_timer_cb(struct ev_loop __attribute__((unused)) *loop,
ev_timer __attribute__((unused)) *w,
int __attribute__((unused)) revents) {
if (logfile) {
(void)fflush(logfile);
}
}
void logging_flight_recorder_dump(void) {
if (flight_recorder) {
ILOG("Flight recorder dump"); // will be also at the end of the dump :)
ring_buffer_dump(flight_recorder, logfile);
} else {
ILOG("Flight recorder is disabled");
}
}
static void logging_flight_recorder_dump_async_cb(struct ev_loop __attribute__((unused)) *loop,
ev_async __attribute__((__unused__)) *w,
int __attribute__((__unused__)) revents) {
logging_flight_recorder_dump();
}
static void logging_flight_recorder_dump_cb(struct ev_loop __attribute__((unused)) *loop,
ev_signal __attribute__((__unused__)) *w,
int __attribute__((__unused__)) revents) {
// Signal handler: just trigger async watcher to defer to main loop
// This ensures fprintf() is called outside of signal context
ev_async_send(logging_loop, &flight_recorder_async);
}
void logging_events_init(struct ev_loop *loop) {
logging_loop = loop;
/* don't start timer if we will never write messages that are not flushed */
if (loglevel < LOG_FLUSH_LEVEL) {
DLOG("starting periodic log flush timer");
ev_timer_init(&logging_timer, logging_timer_cb, 0, 10);
ev_timer_start(loop, &logging_timer);
}
DLOG("starting SIGUSR2 handler");
ev_async_init(&flight_recorder_async, logging_flight_recorder_dump_async_cb);
ev_async_start(loop, &flight_recorder_async);
ev_signal_init(&sigusr2, logging_flight_recorder_dump_cb, SIGUSR2);
ev_signal_start(loop, &sigusr2);
}
void logging_events_cleanup(struct ev_loop *loop) {
ev_timer_stop(loop, &logging_timer);
ev_signal_stop(loop, &sigusr2);
ev_async_stop(loop, &flight_recorder_async);
}
void logging_init(int fd, int level, uint32_t flight_recorder_size, int syslog_flag) {
use_syslog = syslog_flag;
if (use_syslog) {
// 打开syslog连接
openlog(LOG_IDENT, LOG_PID | LOG_DEBUG, LOG_DEBUG);
// 如果使用了syslog,关闭可能打开的文件描述符
if (logfile) {
(void)fclose(logfile);
logfile = NULL;
}
} else {
if (logfile) {
(void)fclose(logfile);
logfile = NULL;
}
logfile = fdopen(fd, "a");
if (logfile == NULL) {
// fdopen failed, can't log but we can still continue
return;
}
}
loglevel = level;
ring_buffer_init(&flight_recorder, flight_recorder_size);
}
void logging_cleanup(void) {
if (flight_recorder) {
ring_buffer_free(&flight_recorder);
flight_recorder = NULL;
}
if (use_syslog) {
// 关闭syslog连接
closelog();
} else if (logfile) {
(void)fclose(logfile);
}
logfile = NULL;
use_syslog = 0;
}
int logging_debug_enabled(void) {
return loglevel <= DOH_LOG_DEBUG || flight_recorder;
}
// NOLINTNEXTLINE(misc-no-recursion) because of severity check
void _log(const char *file, int line, int severity, const char *fmt, ...) {
if (severity < loglevel && !flight_recorder) {
return;
}
if (severity < 0 || severity >= DOH_LOG_MAX) {
FLOG("Unknown log severity: %d", severity);
}
// 如果没有使用syslog且logfile为空,尝试使用stdout
if (!use_syslog && !logfile) {
logfile = fdopen(STDOUT_FILENO, "w");
if (!logfile) {
// Can't even log to stdout, abort
abort();
}
}
struct timeval tv;
gettimeofday(&tv, NULL);
char buff[LOG_LINE_SIZE];
uint32_t buff_pos = 0;
int chars = snprintf(buff, LOG_LINE_SIZE, "%s %8"PRIu64".%06"PRIu64" %s:%d ",
SeverityStr[severity], (uint64_t)tv.tv_sec, (uint64_t)tv.tv_usec, file, line);
if (chars < 0 || chars >= LOG_LINE_SIZE/2) {
abort(); // must be impossible
}
buff_pos += (uint32_t)chars;
va_list args;
va_start(args, fmt);
chars = vsnprintf(buff + buff_pos, LOG_LINE_SIZE - buff_pos, fmt, args); // NOLINT(clang-diagnostic-format-nonliteral)
va_end(args);
if (chars < 0) {
abort(); // must be impossible
}
buff_pos += (uint32_t)chars;
if (buff_pos >= LOG_LINE_SIZE) {
buff_pos = LOG_LINE_SIZE - 1;
buff[buff_pos - 1] = '$'; // indicate truncation
}
if (flight_recorder) {
ring_buffer_push_back(flight_recorder, buff, buff_pos);
}
if (severity < loglevel) {
return;
}
// 根据配置输出日志
if (use_syslog) {
// 输出到syslog(不带时间戳和文件名,因为syslog会自动添加)
va_start(args, fmt);
vsyslog(severity_to_syslog(severity), fmt, args);
va_end(args);
} else {
(void)fprintf(logfile, "%s\n", buff);
}
if (!use_syslog && severity >= LOG_FLUSH_LEVEL) {
(void)fflush(logfile);
}
if (severity == DOH_LOG_FATAL) {
if (flight_recorder) {
ring_buffer_dump(flight_recorder, logfile);
}
#ifdef DEBUG
abort();
#else
exit(1);
#endif
}
}