comparison src/core/ngx_log.c @ 5254:7ecaa9e4bf1b

Core: support several "error_log" directives. When several "error_log" directives are specified in the same configuration block, logs are written to all files with a matching log level. All logs are stored in the singly-linked list that is sorted by log level in the descending order. Specific debug levels (NGX_LOG_DEBUG_HTTP,EVENT, etc.) are not supported if several "error_log" directives are specified. In this case all logs will use debug level that has largest absolute value.
author Vladimir Homutov <vl@nginx.com>
date Thu, 20 Jun 2013 20:47:39 +0400
parents 3bb51e5afa9e
children e088695737c3
comparison
equal deleted inserted replaced
5253:a82f305487c2 5254:7ecaa9e4bf1b
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 10
11 11
12 static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 12 static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
13 static char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
14 static void ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log);
13 15
14 16
15 static ngx_command_t ngx_errlog_commands[] = { 17 static ngx_command_t ngx_errlog_commands[] = {
16 18
17 {ngx_string("error_log"), 19 {ngx_string("error_log"),
84 const char *fmt, va_list args) 86 const char *fmt, va_list args)
85 87
86 #endif 88 #endif
87 { 89 {
88 #if (NGX_HAVE_VARIADIC_MACROS) 90 #if (NGX_HAVE_VARIADIC_MACROS)
89 va_list args; 91 va_list args;
90 #endif 92 #endif
91 u_char *p, *last, *msg; 93 u_char *p, *last, *msg;
92 u_char errstr[NGX_MAX_ERROR_STR]; 94 u_char errstr[NGX_MAX_ERROR_STR];
93 95 ngx_uint_t wrote_stderr, debug_connection;
94 if (log->file->fd == NGX_INVALID_FILE) {
95 return;
96 }
97 96
98 last = errstr + NGX_MAX_ERROR_STR; 97 last = errstr + NGX_MAX_ERROR_STR;
99 98
100 ngx_memcpy(errstr, ngx_cached_err_log_time.data, 99 ngx_memcpy(errstr, ngx_cached_err_log_time.data,
101 ngx_cached_err_log_time.len); 100 ngx_cached_err_log_time.len);
138 p = last - NGX_LINEFEED_SIZE; 137 p = last - NGX_LINEFEED_SIZE;
139 } 138 }
140 139
141 ngx_linefeed(p); 140 ngx_linefeed(p);
142 141
143 (void) ngx_write_fd(log->file->fd, errstr, p - errstr); 142 wrote_stderr = 0;
143 debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;
144
145 while (log) {
146
147 if (log->log_level < level && !debug_connection) {
148 break;
149 }
150
151 (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
152
153 if (log->file->fd == ngx_stderr) {
154 wrote_stderr = 1;
155 }
156
157 log = log->next;
158 }
144 159
145 if (!ngx_use_stderr 160 if (!ngx_use_stderr
146 || level > NGX_LOG_WARN 161 || level > NGX_LOG_WARN
147 || log->file->fd == ngx_stderr) 162 || wrote_stderr)
148 { 163 {
149 return; 164 return;
150 } 165 }
151 166
152 msg -= (7 + err_levels[level].len + 3); 167 msg -= (7 + err_levels[level].len + 3);
346 361
347 return &ngx_log; 362 return &ngx_log;
348 } 363 }
349 364
350 365
351 ngx_log_t * 366 static char *
352 ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
353 {
354 ngx_log_t *log;
355
356 log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
357 if (log == NULL) {
358 return NULL;
359 }
360
361 log->file = ngx_conf_open_file(cycle, name);
362 if (log->file == NULL) {
363 return NULL;
364 }
365
366 return log;
367 }
368
369
370 char *
371 ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log) 367 ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
372 { 368 {
373 ngx_uint_t i, n, d, found; 369 ngx_uint_t i, n, d, found;
374 ngx_str_t *value; 370 ngx_str_t *value;
371
372 if (cf->args->nelts == 2) {
373 log->log_level = NGX_LOG_ERR;
374 return NGX_CONF_OK;
375 }
375 376
376 value = cf->args->elts; 377 value = cf->args->elts;
377 378
378 for (i = 2; i < cf->args->nelts; i++) { 379 for (i = 2; i < cf->args->nelts; i++) {
379 found = 0; 380 found = 0;
426 427
427 428
428 static char * 429 static char *
429 ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 430 ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
430 { 431 {
432 ngx_log_t *dummy;
433
434 dummy = &cf->cycle->new_log;
435
436 return ngx_log_set_log(cf, &dummy);
437 }
438
439
440 char *
441 ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head)
442 {
443 ngx_log_t *new_log;
431 ngx_str_t *value, name; 444 ngx_str_t *value, name;
432 445
433 if (cf->cycle->new_log.file) { 446 if (*head != NULL && (*head)->log_level == 0) {
434 return "is duplicate"; 447 new_log = *head;
448
449 } else {
450
451 new_log = ngx_pcalloc(cf->pool, sizeof(ngx_log_t));
452 if (new_log == NULL) {
453 return NGX_CONF_ERROR;
454 }
455
456 if (*head == NULL) {
457 *head = new_log;
458 }
435 } 459 }
436 460
437 value = cf->args->elts; 461 value = cf->args->elts;
438 462
439 if (ngx_strcmp(value[1].data, "stderr") == 0) { 463 if (ngx_strcmp(value[1].data, "stderr") == 0) {
442 466
443 } else { 467 } else {
444 name = value[1]; 468 name = value[1];
445 } 469 }
446 470
447 cf->cycle->new_log.file = ngx_conf_open_file(cf->cycle, &name); 471 new_log->file = ngx_conf_open_file(cf->cycle, &name);
448 if (cf->cycle->new_log.file == NULL) { 472 if (new_log->file == NULL) {
449 return NULL; 473 return NGX_CONF_ERROR;
450 } 474 }
451 475
452 if (cf->args->nelts == 2) { 476 if (ngx_log_set_levels(cf, new_log) != NGX_CONF_OK) {
453 cf->cycle->new_log.log_level = NGX_LOG_ERR; 477 return NGX_CONF_ERROR;
454 return NGX_CONF_OK; 478 }
455 } 479
456 480 if (*head != new_log) {
457 return ngx_log_set_levels(cf, &cf->cycle->new_log); 481 ngx_log_insert(*head, new_log);
458 } 482 }
483
484 return NGX_CONF_OK;
485 }
486
487
488 static void
489 ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log)
490 {
491 ngx_log_t tmp;
492
493 if (new_log->log_level > log->log_level) {
494
495 /*
496 * list head address is permanent, insert new log after
497 * head and swap its contents with head
498 */
499
500 tmp = *log;
501 *log = *new_log;
502 *new_log = tmp;
503
504 log->next = new_log;
505 return;
506 }
507
508 while (log->next) {
509 if (new_log->log_level > log->next->log_level) {
510 new_log->next = log->next;
511 log->next = new_log;
512 return;
513 }
514
515 log = log->next;
516 }
517
518 log->next = new_log;
519 }