# HG changeset patch # User Vladimir Homutov # Date 1399898055 -14400 # Node ID 777202558122148190b1bc4a26b2e22b67bc481c # Parent 1209b8a7b077c7bbf161e502964308736c84db6f Added syslog support for error_log and access_log directives. diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -37,7 +37,8 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_resolver.h \ src/core/ngx_open_file_cache.h \ src/core/ngx_crypt.h \ - src/core/ngx_proxy_protocol.h" + src/core/ngx_proxy_protocol.h \ + src/core/ngx_syslog.h" CORE_SRCS="src/core/nginx.c \ @@ -69,7 +70,8 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_resolver.c \ src/core/ngx_open_file_cache.c \ src/core/ngx_crypt.c \ - src/core/ngx_proxy_protocol.c" + src/core/ngx_proxy_protocol.c \ + src/core/ngx_syslog.c" REGEX_MODULE=ngx_regex_module diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -77,6 +77,7 @@ typedef void (*ngx_connection_handler_pt #include #include #include +#include #include diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -148,6 +148,12 @@ ngx_log_error_core(ngx_uint_t level, ngx break; } + if (log->writer) { + log->writer(log, level, errstr, p - errstr); + log = log->next; + continue; + } + (void) ngx_write_fd(log->file->fd, errstr, p - errstr); if (log->file->fd == ngx_stderr) { @@ -366,15 +372,33 @@ ngx_log_init(u_char *prefix) ngx_int_t ngx_log_open_default(ngx_cycle_t *cycle) { - static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH); + ngx_log_t *log; + static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH); - if (cycle->new_log.file == NULL) { - cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); - if (cycle->new_log.file == NULL) { + if (ngx_log_get_file_log(&cycle->new_log) != NULL) { + return NGX_OK; + } + + if (cycle->new_log.log_level != 0) { + /* there are some error logs, but no files */ + + log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)); + if (log == NULL) { return NGX_ERROR; } - cycle->new_log.log_level = NGX_LOG_ERR; + log->log_level = NGX_LOG_ERR; + ngx_log_insert(&cycle->new_log, log); + + } else { + /* no error logs at all */ + log = &cycle->new_log; + log->log_level = NGX_LOG_ERR; + } + + log->file = ngx_conf_open_file(cycle, &error_log); + if (log->file == NULL) { + return NGX_ERROR; } return NGX_OK; @@ -390,7 +414,8 @@ ngx_log_redirect_stderr(ngx_cycle_t *cyc return NGX_OK; } - fd = cycle->log->file->fd; + /* file log always exists when we are called */ + fd = ngx_log_get_file_log(cycle->log)->file->fd; if (fd != ngx_stderr) { if (ngx_set_stderr(fd) == NGX_FILE_ERROR) { @@ -405,6 +430,21 @@ ngx_log_redirect_stderr(ngx_cycle_t *cyc } +ngx_log_t * +ngx_log_get_file_log(ngx_log_t *head) +{ + ngx_log_t *log; + + for (log = head; log; log = log->next) { + if (log->file != NULL) { + return log; + } + } + + return NULL; +} + + static char * ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log) { @@ -482,8 +522,9 @@ ngx_error_log(ngx_conf_t *cf, ngx_comman char * ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head) { - ngx_log_t *new_log; - ngx_str_t *value, name; + ngx_log_t *new_log; + ngx_str_t *value, name; + ngx_syslog_peer_t *peer; if (*head != NULL && (*head)->log_level == 0) { new_log = *head; @@ -506,13 +547,30 @@ ngx_log_set_log(ngx_conf_t *cf, ngx_log_ ngx_str_null(&name); cf->cycle->log_use_stderr = 1; - } else { - name = value[1]; - } + new_log->file = ngx_conf_open_file(cf->cycle, &name); + if (new_log->file == NULL) { + return NGX_CONF_ERROR; + } + + + } else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) { + peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t)); + if (peer == NULL) { + return NGX_CONF_ERROR; + } - new_log->file = ngx_conf_open_file(cf->cycle, &name); - if (new_log->file == NULL) { - return NGX_CONF_ERROR; + if (ngx_syslog_process_conf(cf, peer) != NGX_CONF_OK) { + return NGX_CONF_ERROR; + } + + new_log->writer = ngx_syslog_writer; + new_log->wdata = peer; + + } else { + new_log->file = ngx_conf_open_file(cf->cycle, &value[1]); + if (new_log->file == NULL) { + return NGX_CONF_ERROR; + } } if (ngx_log_set_levels(cf, new_log) != NGX_CONF_OK) { diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -43,6 +43,8 @@ typedef u_char *(*ngx_log_handler_pt) (ngx_log_t *log, u_char *buf, size_t len); +typedef void (*ngx_log_writer_pt) (ngx_log_t *log, ngx_uint_t level, + u_char *buf, size_t len); struct ngx_log_s { @@ -54,6 +56,9 @@ struct ngx_log_s { ngx_log_handler_pt handler; void *data; + ngx_log_writer_pt writer; + void *wdata; + /* * we declare "action" as "char *" because the actions are usually * the static strings and in the "u_char *" case we have to override @@ -227,6 +232,7 @@ void ngx_cdecl ngx_log_stderr(ngx_err_t u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err); ngx_int_t ngx_log_open_default(ngx_cycle_t *cycle); ngx_int_t ngx_log_redirect_stderr(ngx_cycle_t *cycle); +ngx_log_t *ngx_log_get_file_log(ngx_log_t *head); char *ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head); diff --git a/src/core/ngx_syslog.c b/src/core/ngx_syslog.c new file mode 100644 --- /dev/null +++ b/src/core/ngx_syslog.c @@ -0,0 +1,332 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#include +#include +#include + + +#define NGX_SYSLOG_MAX_STR \ + NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1 \ + + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */ \ + + 32 /* tag */ + 2 /* colon, space */ + + +static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer); +static ngx_int_t ngx_syslog_init_peer(ngx_syslog_peer_t *peer); +static void ngx_syslog_cleanup(void *data); + + +static char *facilities[] = { + "kern", "user", "mail", "daemon", "auth", "intern", "lpr", "news", "uucp", + "clock", "authpriv", "ftp", "ntp", "audit", "alert", "cron", "local0", + "local1", "local2", "local3", "local4", "local5", "local6", "local7", + NULL +}; + +/* note 'error/warn' like in nginx.conf, not 'err/warning' */ +static char *severities[] = { + "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug", NULL +}; + +static ngx_log_t ngx_syslog_dummy_log; +static ngx_event_t ngx_syslog_dummy_event; + + +char * +ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer) +{ + peer->pool = cf->pool; + peer->facility = NGX_CONF_UNSET_UINT; + peer->severity = NGX_CONF_UNSET_UINT; + + if (ngx_syslog_parse_args(cf, peer) != NGX_CONF_OK) { + return NGX_CONF_ERROR; + } + + if (peer->server.sockaddr == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "no syslog server specified"); + return NGX_CONF_ERROR; + } + + if (peer->facility == NGX_CONF_UNSET_UINT) { + peer->facility = 23; /* local7 */ + } + + if (peer->severity == NGX_CONF_UNSET_UINT) { + peer->severity = 6; /* info */ + } + + if (peer->tag.data == NULL) { + ngx_str_set(&peer->tag, "nginx"); + } + + peer->conn.fd = (ngx_socket_t) -1; + + return NGX_CONF_OK; +} + + +static char * +ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer) +{ + u_char *p, *comma, c; + size_t len; + ngx_str_t *value; + ngx_url_t u; + ngx_uint_t i; + + value = cf->args->elts; + + p = value[1].data + sizeof("syslog:") - 1; + + for ( ;; ) { + comma = (u_char *) ngx_strchr(p, ','); + + if (comma != NULL) { + len = comma - p; + *comma = '\0'; + + } else { + len = value[1].data + value[1].len - p; + } + + if (ngx_strncmp(p, "server=", 7) == 0) { + + if (peer->server.sockaddr != NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate syslog \"server\""); + return NGX_CONF_ERROR; + } + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.url.data = p + 7; + u.url.len = len - 7; + u.default_port = 514; + + if (ngx_parse_url(cf->pool, &u) != NGX_OK) { + if (u.err) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "%s in syslog server \"%V\"", + u.err, &u.url); + } + + return NGX_CONF_ERROR; + } + + peer->server = u.addrs[0]; + + } else if (ngx_strncmp(p, "facility=", 9) == 0) { + + if (peer->facility != NGX_CONF_UNSET_UINT) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate syslog \"facility\""); + return NGX_CONF_ERROR; + } + + for (i = 0; facilities[i] != NULL; i++) { + + if (ngx_strcmp(p + 9, facilities[i]) == 0) { + peer->facility = i; + goto next; + } + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown syslog facility \"%s\"", p + 9); + return NGX_CONF_ERROR; + + } else if (ngx_strncmp(p, "severity=", 9) == 0) { + + if (peer->severity != NGX_CONF_UNSET_UINT) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate syslog \"severity\""); + return NGX_CONF_ERROR; + } + + for (i = 0; severities[i] != NULL; i++) { + + if (ngx_strcmp(p + 9, severities[i]) == 0) { + peer->severity = i; + goto next; + } + } + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown syslog severity \"%s\"", p + 9); + return NGX_CONF_ERROR; + + } else if (ngx_strncmp(p, "tag=", 4) == 0) { + + if (peer->tag.data != NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate syslog \"tag\""); + return NGX_CONF_ERROR; + } + + /* + * RFC 3164: the TAG is a string of ABNF alphanumeric characters + * that MUST NOT exceed 32 characters. + */ + if (len - 4 > 32) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "syslog tag length exceeds 32"); + return NGX_CONF_ERROR; + } + + for (i = 4; i < len; i++) { + c = ngx_tolower(p[i]); + + if (c < '0' || (c > '9' && c < 'a') || c > 'z') { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "syslog \"tag\" only allows " + "alphanumeric characters"); + return NGX_CONF_ERROR; + } + } + + peer->tag.data = p + 4; + peer->tag.len = len - 4; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "unknown syslog parameter \"%s\"", p); + return NGX_CONF_ERROR; + } + + next: + + if (comma == NULL) { + break; + } + + p = comma + 1; + } + + return NGX_CONF_OK; +} + + +u_char * +ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf) +{ + ngx_uint_t pri; + + pri = peer->facility * 8 + peer->severity; + + return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time, + &ngx_cycle->hostname, &peer->tag); +} + + +void +ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf, + size_t len) +{ + u_char *p, msg[NGX_SYSLOG_MAX_STR]; + ngx_uint_t head_len; + ngx_syslog_peer_t *peer; + + peer = log->wdata; + + if (peer->processing) { + return; + } + + peer->processing = 1; + peer->severity = level - 1; + + p = ngx_syslog_add_header(peer, msg); + head_len = p - msg; + + len -= NGX_LINEFEED_SIZE; + + if (len > NGX_SYSLOG_MAX_STR - head_len) { + len = NGX_SYSLOG_MAX_STR - head_len; + } + + p = ngx_snprintf(p, len, "%s", buf); + + (void) ngx_syslog_send(peer, msg, p - msg); + + peer->processing = 0; +} + + +ssize_t +ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len) +{ + if (peer->conn.fd == (ngx_socket_t) -1) { + if (ngx_syslog_init_peer(peer) != NGX_OK) { + return NGX_ERROR; + } + } + + if (ngx_send) { + return ngx_send(&peer->conn, buf, len); + + } else { + /* event module has not yet set ngx_io */ + return ngx_os_io.send(&peer->conn, buf, len); + } +} + + +static ngx_int_t +ngx_syslog_init_peer(ngx_syslog_peer_t *peer) +{ + ngx_socket_t fd; + ngx_pool_cleanup_t *cln; + + peer->conn.read = &ngx_syslog_dummy_event; + peer->conn.write = &ngx_syslog_dummy_event; + peer->conn.log = &ngx_syslog_dummy_log; + + ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log; + + cln = ngx_pool_cleanup_add(peer->pool, 0); + if (cln == NULL) { + return NGX_ERROR; + } + + cln->data = peer; + cln->handler = ngx_syslog_cleanup; + + fd = ngx_socket(peer->server.sockaddr->sa_family, SOCK_DGRAM, 0); + if (fd == (ngx_socket_t) -1) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, + ngx_socket_n " failed"); + return NGX_ERROR; + } + + if (ngx_nonblocking(fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, + ngx_nonblocking_n " failed"); + return NGX_ERROR; + } + + if (connect(fd, peer->server.sockaddr, peer->server.socklen) == -1) { + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno, + "connect() failed"); + return NGX_ERROR; + } + + peer->conn.fd = fd; + return NGX_OK; +} + + +static void +ngx_syslog_cleanup(void *data) +{ + ngx_syslog_peer_t *peer = data; + + if (peer->conn.fd != (ngx_socket_t) -1) { + (void) ngx_close_socket(peer->conn.fd); + } +} diff --git a/src/core/ngx_syslog.h b/src/core/ngx_syslog.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_syslog.h @@ -0,0 +1,30 @@ + +/* + * Copyright (C) Nginx, Inc. + */ + + +#ifndef _NGX_SYSLOG_H_INCLUDED_ +#define _NGX_SYSLOG_H_INCLUDED_ + + +typedef struct { + ngx_pool_t *pool; + ngx_uint_t facility; + ngx_uint_t severity; + ngx_str_t tag; + + ngx_addr_t server; + ngx_connection_t conn; + ngx_uint_t processing; /* unsigned processing:1; */ +} ngx_syslog_peer_t; + + +char *ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer); +u_char *ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf); +void ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf, + size_t len); +ssize_t ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len); + + +#endif /* _NGX_SYSLOG_H_INCLUDED_ */ diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -29,6 +29,7 @@ volatile ngx_str_t ngx_cached_err_ volatile ngx_str_t ngx_cached_http_time; volatile ngx_str_t ngx_cached_http_log_time; volatile ngx_str_t ngx_cached_http_log_iso8601; +volatile ngx_str_t ngx_cached_syslog_time; #if !(NGX_WIN32) @@ -50,6 +51,8 @@ static u_char cached_http_log [sizeof("28/Sep/1970:12:00:00 +0600")]; static u_char cached_http_log_iso8601[NGX_TIME_SLOTS] [sizeof("1970-09-28T12:00:00+06:00")]; +static u_char cached_syslog_time[NGX_TIME_SLOTS] + [sizeof("Sep 28 12:00:00")]; static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -63,6 +66,7 @@ ngx_time_init(void) ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1; ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1; ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1; + ngx_cached_syslog_time.len = sizeof("Sep 28 12:00:00") - 1; ngx_cached_time = &cached_time[0]; @@ -73,7 +77,7 @@ ngx_time_init(void) void ngx_time_update(void) { - u_char *p0, *p1, *p2, *p3; + u_char *p0, *p1, *p2, *p3, *p4; ngx_tm_t tm, gmt; time_t sec; ngx_uint_t msec; @@ -166,6 +170,11 @@ ngx_time_update(void) tp->gmtoff < 0 ? '-' : '+', ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60)); + p4 = &cached_syslog_time[slot][0]; + + (void) ngx_sprintf(p4, "%s %2d %02d:%02d:%02d", + months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday, + tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); ngx_memory_barrier(); @@ -174,6 +183,7 @@ ngx_time_update(void) ngx_cached_err_log_time.data = p1; ngx_cached_http_log_time.data = p2; ngx_cached_http_log_iso8601.data = p3; + ngx_cached_syslog_time.data = p4; ngx_unlock(&ngx_time_lock); } @@ -184,7 +194,7 @@ ngx_time_update(void) void ngx_time_sigsafe_update(void) { - u_char *p; + u_char *p, *p2; ngx_tm_t tm; time_t sec; ngx_time_t *tp; @@ -224,9 +234,16 @@ ngx_time_sigsafe_update(void) tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); + p2 = &cached_syslog_time[slot][0]; + + (void) ngx_sprintf(p2, "%s %2d %02d:%02d:%02d", + months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday, + tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); + ngx_memory_barrier(); ngx_cached_err_log_time.data = p; + ngx_cached_syslog_time.data = p2; ngx_unlock(&ngx_time_lock); } diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h --- a/src/core/ngx_times.h +++ b/src/core/ngx_times.h @@ -40,6 +40,7 @@ extern volatile ngx_str_t ngx_cached_ extern volatile ngx_str_t ngx_cached_http_time; extern volatile ngx_str_t ngx_cached_http_log_time; extern volatile ngx_str_t ngx_cached_http_log_iso8601; +extern volatile ngx_str_t ngx_cached_syslog_time; /* * milliseconds elapsed since epoch and truncated to ngx_msec_t, diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -66,6 +66,7 @@ typedef struct { ngx_http_log_script_t *script; time_t disk_full_time; time_t error_log_time; + ngx_syslog_peer_t *syslog_peer; ngx_http_log_fmt_t *format; ngx_http_complex_value_t *filter; } ngx_http_log_t; @@ -240,7 +241,8 @@ static ngx_int_t ngx_http_log_handler(ngx_http_request_t *r) { u_char *line, *p; - size_t len; + size_t len, size; + ssize_t n; ngx_str_t val; ngx_uint_t i, l; ngx_http_log_t *log; @@ -294,6 +296,16 @@ ngx_http_log_handler(ngx_http_request_t } } + if (log[l].syslog_peer) { + + /* length of syslog's PRI and HEADER message parts */ + len += sizeof("<255>Jan 01 00:00:00 ") - 1 + + ngx_cycle->hostname.len + 1 + + log[l].syslog_peer->tag.len + 2; + + goto alloc_line; + } + len += NGX_LINEFEED_SIZE; buffer = log[l].file ? log[l].file->data : NULL; @@ -332,6 +344,8 @@ ngx_http_log_handler(ngx_http_request_t } } + alloc_line: + line = ngx_pnalloc(r->pool, len); if (line == NULL) { return NGX_ERROR; @@ -339,10 +353,33 @@ ngx_http_log_handler(ngx_http_request_t p = line; + if (log[l].syslog_peer) { + p = ngx_syslog_add_header(log[l].syslog_peer, line); + } + for (i = 0; i < log[l].format->ops->nelts; i++) { p = op[i].run(r, p, &op[i]); } + if (log[l].syslog_peer) { + + size = p - line; + + n = ngx_syslog_send(log[l].syslog_peer, line, size); + + if (n < 0) { + ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, + "send() to syslog failed"); + + } else if ((size_t) n != size) { + ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, + "send() to syslog has written only %z of %uz", + n, size); + } + + continue; + } + ngx_linefeed(p); ngx_http_log_write(r, &log[l], line, p - line); @@ -1080,6 +1117,7 @@ ngx_http_log_merge_loc_conf(ngx_conf_t * log->script = NULL; log->disk_full_time = 0; log->error_log_time = 0; + log->syslog_peer = NULL; lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module); fmt = lmcf->formats.elts; @@ -1103,6 +1141,7 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx ngx_msec_t flush; ngx_str_t *value, name, s, filter; ngx_http_log_t *log; + ngx_syslog_peer_t *peer; ngx_http_log_buf_t *buffer; ngx_http_log_fmt_t *fmt; ngx_http_log_main_conf_t *lmcf; @@ -1138,6 +1177,23 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx ngx_memzero(log, sizeof(ngx_http_log_t)); + + if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) { + + peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t)); + if (peer == NULL) { + return NGX_CONF_ERROR; + } + + if (ngx_syslog_process_conf(cf, peer) != NGX_CONF_OK) { + return NGX_CONF_ERROR; + } + + log->syslog_peer = peer; + + goto process_formats; + } + n = ngx_http_script_variables_count(&value[1]); if (n == 0) { @@ -1171,6 +1227,8 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx } } +process_formats: + if (cf->args->nelts >= 3) { name = value[2]; @@ -1199,6 +1257,17 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } + if (log->syslog_peer != NULL) { + if (cf->args->nelts > 3) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "parameter \"%V\" is not supported by syslog", + &value[3]); + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; + } + size = 0; flush = 0; gzip = 0; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -587,6 +587,8 @@ extern ngx_http_header_out_t ngx_http_ \ c->log->file = l->file; \ c->log->next = l->next; \ + c->log->writer = l->writer; \ + c->log->wdata = l->wdata; \ if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { \ c->log->log_level = l->log_level; \ } diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -710,11 +710,13 @@ ngx_master_process_exit(ngx_cycle_t *cyc * ngx_cycle->pool is already destroyed. */ - ngx_exit_log_file.fd = ngx_cycle->log->file->fd; - ngx_exit_log = *ngx_cycle->log; + ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log); + + ngx_exit_log_file.fd = ngx_exit_log.file->fd; ngx_exit_log.file = &ngx_exit_log_file; ngx_exit_log.next = NULL; + ngx_exit_log.writer = NULL; ngx_exit_cycle.log = &ngx_exit_log; ngx_exit_cycle.files = ngx_cycle->files; @@ -1065,11 +1067,12 @@ ngx_worker_process_exit(ngx_cycle_t *cyc * ngx_cycle->pool is already destroyed. */ - ngx_exit_log_file.fd = ngx_cycle->log->file->fd; + ngx_exit_log = *ngx_log_get_file_log(ngx_cycle->log); - ngx_exit_log = *ngx_cycle->log; + ngx_exit_log_file.fd = ngx_exit_log.file->fd; ngx_exit_log.file = &ngx_exit_log_file; ngx_exit_log.next = NULL; + ngx_exit_log.writer = NULL; ngx_exit_cycle.log = &ngx_exit_log; ngx_exit_cycle.files = ngx_cycle->files;