0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9
|
|
10
|
|
11 static void ngx_log_write(ngx_log_t *log, char *errstr, size_t len);
|
|
12 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
|
13
|
|
14
|
|
15 static ngx_command_t ngx_errlog_commands[] = {
|
|
16
|
|
17 {ngx_string("error_log"),
|
|
18 NGX_MAIN_CONF|NGX_CONF_1MORE,
|
|
19 ngx_set_error_log,
|
|
20 0,
|
|
21 0,
|
|
22 NULL},
|
|
23
|
|
24 ngx_null_command
|
|
25 };
|
|
26
|
|
27
|
|
28 static ngx_core_module_t ngx_errlog_module_ctx = {
|
|
29 ngx_string("errlog"),
|
|
30 NULL,
|
|
31 NULL
|
|
32 };
|
|
33
|
|
34
|
|
35 ngx_module_t ngx_errlog_module = {
|
|
36 NGX_MODULE,
|
|
37 &ngx_errlog_module_ctx, /* module context */
|
|
38 ngx_errlog_commands, /* module directives */
|
|
39 NGX_CORE_MODULE, /* module type */
|
|
40 NULL, /* init module */
|
|
41 NULL /* init child */
|
|
42 };
|
|
43
|
|
44
|
|
45 static ngx_log_t ngx_log;
|
|
46 static ngx_open_file_t ngx_stderr;
|
|
47
|
|
48
|
|
49 static const char *err_levels[] = {
|
|
50 "stderr", "emerg", "alert", "crit", "error",
|
|
51 "warn", "notice", "info", "debug"
|
|
52 };
|
|
53
|
|
54 static const char *debug_levels[] = {
|
|
55 "debug_core", "debug_alloc", "debug_mutex", "debug_event",
|
|
56 "debug_http", "debug_imap"
|
|
57 };
|
|
58
|
|
59
|
|
60 #if (HAVE_VARIADIC_MACROS)
|
|
61 void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
|
|
62 const char *fmt, ...)
|
|
63 #else
|
|
64 void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
|
|
65 const char *fmt, va_list args)
|
|
66 #endif
|
|
67 {
|
|
68 char errstr[MAX_ERROR_STR];
|
|
69 size_t len, max;
|
|
70 #if (HAVE_VARIADIC_MACROS)
|
|
71 va_list args;
|
|
72 #endif
|
|
73
|
|
74 if (log->file->fd == NGX_INVALID_FILE) {
|
|
75 return;
|
|
76 }
|
|
77
|
|
78 ngx_memcpy(errstr, ngx_cached_err_log_time.data,
|
|
79 ngx_cached_err_log_time.len);
|
|
80
|
|
81 #if (WIN32)
|
|
82 max = MAX_ERROR_STR - 2;
|
|
83 #else
|
|
84 max = MAX_ERROR_STR - 1;
|
|
85 #endif
|
|
86
|
|
87 len = ngx_cached_err_log_time.len;
|
|
88
|
|
89 len += ngx_snprintf(errstr + len, max - len, " [%s] ", err_levels[level]);
|
|
90
|
|
91 /* pid#tid */
|
|
92 len += ngx_snprintf(errstr + len, max - len,
|
|
93 PID_T_FMT "#" TID_T_FMT ": ", ngx_log_pid, ngx_log_tid);
|
|
94
|
|
95 if (log->data && *(int *) log->data != -1) {
|
|
96 len += ngx_snprintf(errstr + len, max - len,
|
|
97 "*%u ", *(u_int *) log->data);
|
|
98 }
|
|
99
|
|
100 #if (HAVE_VARIADIC_MACROS)
|
|
101
|
|
102 va_start(args, fmt);
|
|
103 len += ngx_vsnprintf(errstr + len, max - len, fmt, args);
|
|
104 va_end(args);
|
|
105
|
|
106 #else
|
|
107
|
|
108 len += ngx_vsnprintf(errstr + len, max - len, fmt, args);
|
|
109
|
|
110 #endif
|
|
111
|
|
112 if (err) {
|
|
113
|
|
114 if (len > max - 50) {
|
|
115
|
|
116 /* leave a space for an error code */
|
|
117
|
|
118 len = max - 50;
|
|
119 errstr[len++] = '.';
|
|
120 errstr[len++] = '.';
|
|
121 errstr[len++] = '.';
|
|
122 }
|
|
123
|
|
124 #if (WIN32)
|
|
125 if ((unsigned) err >= 0x80000000) {
|
|
126 len += ngx_snprintf(errstr + len, max - len, " (%X: ", err);
|
|
127 } else {
|
|
128 len += ngx_snprintf(errstr + len, max - len, " (%d: ", err);
|
|
129 }
|
|
130 #else
|
|
131 len += ngx_snprintf(errstr + len, max - len, " (%d: ", err);
|
|
132 #endif
|
|
133
|
|
134 if (len >= max) {
|
|
135 ngx_log_write(log, errstr, max);
|
|
136 return;
|
|
137 }
|
|
138
|
|
139 len += ngx_strerror_r(err, errstr + len, max - len);
|
|
140
|
|
141 if (len >= max) {
|
|
142 ngx_log_write(log, errstr, max);
|
|
143 return;
|
|
144 }
|
|
145
|
|
146 errstr[len++] = ')';
|
|
147
|
|
148 if (len >= max) {
|
|
149 ngx_log_write(log, errstr, max);
|
|
150 return;
|
|
151 }
|
|
152
|
|
153 } else {
|
|
154 if (len >= max) {
|
|
155 ngx_log_write(log, errstr, max);
|
|
156 return;
|
|
157 }
|
|
158 }
|
|
159
|
|
160 if (level != NGX_LOG_DEBUG && log->handler) {
|
|
161 len += log->handler(log->data, errstr + len, max - len);
|
|
162
|
|
163 if (len >= max) {
|
|
164 len = max;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 ngx_log_write(log, errstr, len);
|
|
169 }
|
|
170
|
|
171
|
|
172 static void ngx_log_write(ngx_log_t *log, char *errstr, size_t len)
|
|
173 {
|
|
174 #if (WIN32)
|
|
175 u_long written;
|
|
176
|
|
177 errstr[len++] = CR;
|
|
178 errstr[len++] = LF;
|
|
179 WriteFile(log->file->fd, errstr, len, &written, NULL);
|
|
180
|
|
181 #else
|
|
182
|
|
183 errstr[len++] = LF;
|
|
184 write(log->file->fd, errstr, len);
|
|
185
|
|
186 #endif
|
|
187 }
|
|
188
|
|
189
|
|
190 #if !(HAVE_VARIADIC_MACROS)
|
|
191
|
|
192 void ngx_log_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
|
|
193 const char *fmt, ...)
|
|
194 {
|
|
195 va_list args;
|
|
196
|
|
197 if (log->log_level >= level) {
|
|
198 va_start(args, fmt);
|
|
199 ngx_log_error_core(level, log, err, fmt, args);
|
|
200 va_end(args);
|
|
201 }
|
|
202 }
|
|
203
|
|
204
|
|
205 void ngx_log_debug_core(ngx_log_t *log, ngx_err_t err, const char *fmt, ...)
|
|
206 {
|
|
207 va_list args;
|
|
208
|
|
209 va_start(args, fmt);
|
|
210 ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, args);
|
|
211 va_end(args);
|
|
212 }
|
|
213
|
|
214
|
|
215 void ngx_assert_core(ngx_log_t *log, const char *fmt, ...)
|
|
216 {
|
|
217 va_list args;
|
|
218
|
|
219 va_start(args, fmt);
|
|
220 ngx_log_error_core(NGX_LOG_ALERT, log, 0, fmt, args);
|
|
221 va_end(args);
|
|
222 }
|
|
223
|
|
224 #endif
|
|
225
|
|
226
|
|
227 ngx_log_t *ngx_log_init_stderr()
|
|
228 {
|
|
229 #if (WIN32)
|
|
230
|
|
231 ngx_stderr_fileno = GetStdHandle(STD_ERROR_HANDLE);
|
|
232 ngx_stderr.fd = ngx_stderr_fileno;
|
|
233
|
|
234 if (ngx_stderr_fileno == NGX_INVALID_FILE) {
|
|
235
|
|
236 /* TODO: where can we log error ? */
|
|
237
|
|
238 return NULL;
|
|
239
|
|
240 } else if (ngx_stderr_fileno == NULL) {
|
|
241
|
|
242 /* there are no associated standard handles */
|
|
243
|
|
244 /* TODO: where can we can log possible errors ? */
|
|
245
|
|
246 ngx_stderr.fd = NGX_INVALID_FILE;
|
|
247 }
|
|
248
|
|
249 #else
|
|
250
|
|
251 ngx_stderr.fd = STDERR_FILENO;
|
|
252
|
|
253 #endif
|
|
254
|
|
255 ngx_log.file = &ngx_stderr;
|
|
256 ngx_log.log_level = NGX_LOG_ERR;
|
|
257
|
|
258 return &ngx_log;
|
|
259 }
|
|
260
|
|
261
|
|
262 #if 0
|
|
263
|
|
264 ngx_int_t ngx_log_init_error_log()
|
|
265 {
|
|
266 ngx_fd_t fd;
|
|
267
|
|
268 #ifdef NGX_ERROR_LOG_PATH
|
|
269
|
|
270 fd = ngx_open_file(NGX_ERROR_LOG_PATH, NGX_FILE_RDWR,
|
|
271 NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
|
|
272
|
|
273 if (fd == NGX_INVALID_FILE) {
|
|
274 ngx_log_error(NGX_LOG_EMERG, (&ngx_log), ngx_errno,
|
|
275 ngx_open_file_n " \"" NGX_ERROR_LOG_PATH "\" failed");
|
|
276 return NGX_ERROR;
|
|
277 }
|
|
278
|
|
279 #if (WIN32)
|
|
280
|
|
281 if (ngx_file_append_mode(fd) == NGX_ERROR) {
|
|
282 ngx_log_error(NGX_LOG_EMERG, (&ngx_log), ngx_errno,
|
|
283 ngx_file_append_mode_n " \"" NGX_ERROR_LOG_PATH
|
|
284 "\" failed");
|
|
285 return NGX_ERROR;
|
|
286 }
|
|
287
|
|
288 #else
|
|
289
|
|
290 if (dup2(fd, STDERR_FILENO) == NGX_ERROR) {
|
|
291 ngx_log_error(NGX_LOG_EMERG, (&ngx_log), ngx_errno,
|
|
292 "dup2(STDERR) failed");
|
|
293 return NGX_ERROR;
|
|
294 }
|
|
295
|
|
296 #endif
|
|
297
|
|
298 #else /* no NGX_ERROR_LOG_PATH */
|
|
299
|
|
300 ngx_log.log_level = NGX_LOG_INFO;
|
|
301
|
|
302 #endif
|
|
303
|
|
304 return NGX_OK;
|
|
305 }
|
|
306
|
|
307 #endif
|
|
308
|
|
309
|
|
310 ngx_log_t *ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_array_t *args)
|
|
311 {
|
|
312 ngx_log_t *log;
|
|
313 ngx_str_t *value, *name;
|
|
314
|
|
315 if (args) {
|
|
316 value = args->elts;
|
|
317 name = &value[1];
|
|
318
|
|
319 } else {
|
|
320 name = NULL;
|
|
321 }
|
|
322
|
|
323 if (!(log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)))) {
|
|
324 return NULL;
|
|
325 }
|
|
326
|
|
327 if (!(log->file = ngx_conf_open_file(cycle, name))) {
|
|
328 return NULL;
|
|
329 }
|
|
330
|
|
331 return log;
|
|
332 }
|
|
333
|
|
334
|
|
335 char *ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log)
|
|
336 {
|
|
337 ngx_uint_t i, n, d;
|
|
338 ngx_str_t *value;
|
|
339
|
|
340 value = cf->args->elts;
|
|
341
|
|
342 for (i = 2; i < cf->args->nelts; i++) {
|
|
343
|
|
344 for (n = 1; n <= NGX_LOG_DEBUG; n++) {
|
|
345 if (ngx_strcmp(value[i].data, err_levels[n]) == 0) {
|
|
346
|
|
347 if (log->log_level != 0) {
|
|
348 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
349 "invalid log level \"%s\"",
|
|
350 value[i].data);
|
|
351 return NGX_CONF_ERROR;
|
|
352 }
|
|
353
|
|
354 log->log_level = n;
|
|
355 continue;
|
|
356 }
|
|
357 }
|
|
358
|
|
359 for (n = 0, d = NGX_LOG_DEBUG_FIRST; d <= NGX_LOG_DEBUG_LAST; d <<= 1) {
|
|
360 if (ngx_strcmp(value[i].data, debug_levels[n++]) == 0) {
|
|
361 if (log->log_level & ~NGX_LOG_DEBUG_ALL) {
|
|
362 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
363 "invalid log level \"%s\"",
|
|
364 value[i].data);
|
|
365 return NGX_CONF_ERROR;
|
|
366 }
|
|
367
|
|
368 log->log_level |= d;
|
|
369 }
|
|
370 }
|
|
371
|
|
372
|
|
373 if (log->log_level == 0) {
|
|
374 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
375 "invalid log level \"%s\"", value[i].data);
|
|
376 return NGX_CONF_ERROR;
|
|
377 }
|
|
378 }
|
|
379
|
|
380 if (log->log_level == NGX_LOG_DEBUG) {
|
|
381 log->log_level = NGX_LOG_DEBUG_ALL;
|
|
382 }
|
|
383
|
|
384 return NGX_CONF_OK;
|
|
385 }
|
|
386
|
|
387
|
|
388 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|
389 {
|
|
390 ngx_str_t *value;
|
|
391
|
|
392 value = cf->args->elts;
|
|
393
|
|
394 if (value[1].len == 6 && ngx_strcmp(value[1].data, "stderr") == 0) {
|
|
395 cf->cycle->new_log->file->fd = ngx_stderr.fd;
|
|
396 cf->cycle->new_log->file->name.len = 0;
|
|
397 cf->cycle->new_log->file->name.data = NULL;
|
|
398
|
|
399 } else {
|
|
400 cf->cycle->new_log->file->name = value[1];
|
|
401
|
|
402 if (ngx_conf_full_name(cf->cycle, &cf->cycle->new_log->file->name)
|
|
403 == NGX_ERROR)
|
|
404 {
|
|
405 return NGX_CONF_ERROR;
|
|
406 }
|
|
407 }
|
|
408
|
|
409 return ngx_set_error_log_levels(cf, cf->cycle->new_log);
|
|
410 }
|