diff options
author | Zhidao HONG <z.hong@f5.com> | 2022-07-14 11:14:20 +0800 |
---|---|---|
committer | Zhidao HONG <z.hong@f5.com> | 2022-07-14 11:14:20 +0800 |
commit | 8761501b4845656a0f2e5c0e7bf98f948c45fb5f (patch) | |
tree | 84779f016ea8e2d2d2b5152e1ee42a35d914b697 /src/nxt_router_access_log.c | |
parent | 2bd4a455278dbce756c1dc8be07515f73d611e3b (diff) | |
download | unit-8761501b4845656a0f2e5c0e7bf98f948c45fb5f.tar.gz unit-8761501b4845656a0f2e5c0e7bf98f948c45fb5f.tar.bz2 |
Log: split access log from nxt_router.c.
No functional changes.
Diffstat (limited to '')
-rw-r--r-- | src/nxt_router_access_log.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/src/nxt_router_access_log.c b/src/nxt_router_access_log.c new file mode 100644 index 00000000..d92e80c3 --- /dev/null +++ b/src/nxt_router_access_log.c @@ -0,0 +1,446 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Valentin V. Bartenev + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_router.h> +#include <nxt_conf.h> +#include <nxt_http.h> + + +static void nxt_router_access_log_writer(nxt_task_t *task, + nxt_http_request_t *r, nxt_router_access_log_t *access_log); +static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static void nxt_router_access_log_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, + void *data); +static void nxt_router_access_log_reopen_ready(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_router_access_log_reopen_error(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); + + +nxt_int_t +nxt_router_access_log_create(nxt_task_t *task, nxt_router_conf_t *rtcf, + nxt_conf_value_t *value) +{ + nxt_str_t path; + nxt_router_t *router; + nxt_router_access_log_t *access_log; + + router = nxt_router; + + nxt_conf_get_string(value, &path); + + access_log = router->access_log; + + if (access_log != NULL && nxt_strstr_eq(&path, &access_log->path)) { + nxt_router_access_log_use(&router->lock, access_log); + + } else { + access_log = nxt_malloc(sizeof(nxt_router_access_log_t) + + path.length); + if (access_log == NULL) { + nxt_alert(task, "failed to allocate access log structure"); + return NXT_ERROR; + } + + access_log->fd = -1; + access_log->handler = &nxt_router_access_log_writer; + access_log->count = 1; + + access_log->path.length = path.length; + access_log->path.start = (u_char *) access_log + + sizeof(nxt_router_access_log_t); + + nxt_memcpy(access_log->path.start, path.start, path.length); + } + + rtcf->access_log = access_log; + + return NXT_OK; +} + + +static void +nxt_router_access_log_writer(nxt_task_t *task, nxt_http_request_t *r, + nxt_router_access_log_t *access_log) +{ + size_t size; + u_char *buf, *p; + nxt_off_t bytes; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_router_access_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + size = r->remote->address_length + + 6 /* ' - - [' */ + + date_cache.size + + 3 /* '] "' */ + + r->method->length + + 1 /* space */ + + r->target.length + + 1 /* space */ + + r->version.length + + 2 /* '" ' */ + + 3 /* status */ + + 1 /* space */ + + NXT_OFF_T_LEN + + 2 /* ' "' */ + + (r->referer != NULL ? r->referer->value_length : 1) + + 3 /* '" "' */ + + (r->user_agent != NULL ? r->user_agent->value_length : 1) + + 2 /* '"\n' */ + ; + + buf = nxt_mp_nget(r->mem_pool, size); + if (nxt_slow_path(buf == NULL)) { + return; + } + + p = nxt_cpymem(buf, nxt_sockaddr_address(r->remote), + r->remote->address_length); + + p = nxt_cpymem(p, " - - [", 6); + + p = nxt_thread_time_string(task->thread, &date_cache, p); + + p = nxt_cpymem(p, "] \"", 3); + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" ", 2); + + p = nxt_sprintf(p, p + 3, "%03d", r->status); + + *p++ = ' '; + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + p = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", bytes); + + p = nxt_cpymem(p, " \"", 2); + + if (r->referer != NULL) { + p = nxt_cpymem(p, r->referer->value, r->referer->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\" \"", 3); + + if (r->user_agent != NULL) { + p = nxt_cpymem(p, r->user_agent->value, r->user_agent->value_length); + + } else { + *p++ = '-'; + } + + p = nxt_cpymem(p, "\"\n", 2); + + nxt_fd_write(access_log->fd, buf, p - buf); +} + + +static u_char * +nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +void +nxt_router_access_log_open(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) +{ + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + + access_log = tmcf->router_conf->access_log; + + b = nxt_buf_mem_alloc(tmcf->mem_pool, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_buf_dummy_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_ready, + nxt_router_access_log_error, + -1, tmcf); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + return; + +fail: + + nxt_router_conf_error(task, tmcf); +} + + +static void +nxt_router_access_log_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + nxt_router_access_log_t *access_log; + + tmcf = data; + + access_log = tmcf->router_conf->access_log; + + access_log->fd = msg->fd[0]; + + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + nxt_router_conf_apply, task, tmcf, NULL); +} + + +static void +nxt_router_access_log_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_temp_conf_t *tmcf; + + tmcf = data; + + nxt_router_conf_error(task, tmcf); +} + + +void +nxt_router_access_log_use(nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + access_log->count++; + + nxt_thread_spin_unlock(lock); +} + + +void +nxt_router_access_log_release(nxt_task_t *task, nxt_thread_spinlock_t *lock, + nxt_router_access_log_t *access_log) +{ + if (access_log == NULL) { + return; + } + + nxt_thread_spin_lock(lock); + + if (--access_log->count != 0) { + access_log = NULL; + } + + nxt_thread_spin_unlock(lock); + + if (access_log != NULL) { + + if (access_log->fd != -1) { + nxt_fd_close(access_log->fd); + } + + nxt_free(access_log); + } +} + + +typedef struct { + nxt_mp_t *mem_pool; + nxt_router_access_log_t *access_log; +} nxt_router_access_log_reopen_t; + + +void +nxt_router_access_log_reopen_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + nxt_mp_t *mp; + uint32_t stream; + nxt_int_t ret; + nxt_buf_t *b; + nxt_port_t *main_port, *router_port; + nxt_runtime_t *rt; + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + access_log = nxt_router->access_log; + + if (access_log == NULL) { + return; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (nxt_slow_path(mp == NULL)) { + return; + } + + reopen = nxt_mp_get(mp, sizeof(nxt_router_access_log_reopen_t)); + if (nxt_slow_path(reopen == NULL)) { + goto fail; + } + + reopen->mem_pool = mp; + reopen->access_log = access_log; + + b = nxt_buf_mem_alloc(mp, access_log->path.length + 1, 0); + if (nxt_slow_path(b == NULL)) { + goto fail; + } + + b->completion_handler = nxt_router_access_log_reopen_completion; + + nxt_buf_cpystr(b, &access_log->path); + *b->mem.free++ = '\0'; + + rt = task->thread->runtime; + main_port = rt->port_by_type[NXT_PROCESS_MAIN]; + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + stream = nxt_port_rpc_register_handler(task, router_port, + nxt_router_access_log_reopen_ready, + nxt_router_access_log_reopen_error, + -1, reopen); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_ACCESS_LOG, -1, + stream, router_port->id, b); + + if (nxt_slow_path(ret != NXT_OK)) { + nxt_port_rpc_cancel(task, router_port, stream); + goto fail; + } + + nxt_mp_retain(mp); + + return; + +fail: + + nxt_mp_destroy(mp); +} + + +static void +nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj, void *data) +{ + nxt_mp_t *mp; + nxt_buf_t *b; + + b = obj; + mp = b->data; + + nxt_mp_release(mp); +} + + +static void +nxt_router_access_log_reopen_ready(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_t *access_log; + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + access_log = reopen->access_log; + + if (access_log == nxt_router->access_log) { + + if (nxt_slow_path(dup2(msg->fd[0], access_log->fd) == -1)) { + nxt_alert(task, "dup2(%FD, %FD) failed %E", + msg->fd[0], access_log->fd, nxt_errno); + } + } + + nxt_fd_close(msg->fd[0]); + nxt_mp_release(reopen->mem_pool); +} + + +static void +nxt_router_access_log_reopen_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_router_access_log_reopen_t *reopen; + + reopen = data; + + nxt_mp_release(reopen->mem_pool); +} |