📄 ngx_http_log_module.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>#include <nginx.h>typedef struct ngx_http_log_op_s ngx_http_log_op_t;typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r, uintptr_t data);struct ngx_http_log_op_s { size_t len; ngx_http_log_op_getlen_pt getlen; ngx_http_log_op_run_pt run; uintptr_t data;};typedef struct { ngx_str_t name; ngx_array_t *ops; /* array of ngx_http_log_op_t */} ngx_http_log_fmt_t;typedef struct { ngx_array_t formats; /* array of ngx_http_log_fmt_t */ ngx_uint_t combined_used; /* unsigned combined_used:1 */} ngx_http_log_main_conf_t;typedef struct { ngx_open_file_t *file; time_t disk_full_time; time_t error_log_time; ngx_array_t *ops; /* array of ngx_http_log_op_t */} ngx_http_log_t;typedef struct { ngx_array_t *logs; /* array of ngx_http_log_t */ ngx_uint_t off; /* unsigned off:1 */} ngx_http_log_loc_conf_t;typedef struct { ngx_str_t name; size_t len; ngx_http_log_op_run_pt run;} ngx_http_log_var_t;static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, size_t len);static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, ngx_str_t *value);static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data);static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op);static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static char *ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);static ngx_command_t ngx_http_log_commands[] = { { ngx_string("log_format"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, ngx_http_log_set_format, NGX_HTTP_MAIN_CONF_OFFSET, 0, NULL }, { ngx_string("access_log"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123, ngx_http_log_set_log, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, ngx_null_command};static ngx_http_module_t ngx_http_log_module_ctx = { NULL, /* preconfiguration */ ngx_http_log_init, /* postconfiguration */ ngx_http_log_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_log_create_loc_conf, /* create location configration */ ngx_http_log_merge_loc_conf /* merge location configration */};ngx_module_t ngx_http_log_module = { NGX_MODULE_V1, &ngx_http_log_module_ctx, /* module context */ ngx_http_log_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING};static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH);static ngx_str_t ngx_http_combined_fmt = ngx_string("$remote_addr - $remote_user [$time_local] " "\"$request\" $status $body_bytes_sent " "\"$http_referer\" \"$http_user_agent\"");static ngx_http_log_var_t ngx_http_log_vars[] = { { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection }, { ngx_string("pipe"), 1, ngx_http_log_pipe }, { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, ngx_http_log_time }, { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec }, { ngx_string("request_time"), NGX_TIME_T_LEN + 4, ngx_http_log_request_time }, { ngx_string("status"), 3, ngx_http_log_status }, { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent }, { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_body_bytes_sent }, { ngx_string("apache_bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_body_bytes_sent }, { ngx_string("request_length"), NGX_SIZE_T_LEN, ngx_http_log_request_length }, { ngx_null_string, 0, NULL }};ngx_int_tngx_http_log_handler(ngx_http_request_t *r){ u_char *line, *p; size_t len; ngx_uint_t i, l; ngx_http_log_t *log; ngx_open_file_t *file; ngx_http_log_op_t *op; ngx_http_log_loc_conf_t *lcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http log handler"); lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module); if (lcf->off) { return NGX_OK; } log = lcf->logs->elts; for (l = 0; l < lcf->logs->nelts; l++) { if (ngx_time() == log[l].disk_full_time) { /* * on FreeBSD writing to a full filesystem with enabled softupdates * may block process for much longer time than writing to non-full * filesystem, so we skip writing to a log for one second */ continue; } len = 0; op = log[l].ops->elts; for (i = 0; i < log[l].ops->nelts; i++) { if (op[i].len == 0) { len += op[i].getlen(r, op[i].data); } else { len += op[i].len; } } len += NGX_LINEFEED_SIZE; file = log[l].file; if (file->buffer) { if (len > (size_t) (file->last - file->pos)) { ngx_http_log_write(r, &log[l], file->buffer, file->pos - file->buffer); file->pos = file->buffer; } if (len <= (size_t) (file->last - file->pos)) { p = file->pos; for (i = 0; i < log[l].ops->nelts; i++) { p = op[i].run(r, p, &op[i]); } ngx_linefeed(p); file->pos = p; continue; } } line = ngx_palloc(r->pool, len); if (line == NULL) { return NGX_ERROR; } p = line; for (i = 0; i < log[l].ops->nelts; i++) { p = op[i].run(r, p, &op[i]); } ngx_linefeed(p); ngx_http_log_write(r, &log[l], line, p - line); } return NGX_OK;}static voidngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf, size_t len){ time_t now; ssize_t n; ngx_err_t err; n = ngx_write_fd(log->file->fd, buf, len); if (n == (ssize_t) len) { return; } now = ngx_time(); if (n == -1) { err = ngx_errno; if (err == NGX_ENOSPC) { log->disk_full_time = now; } if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, ngx_write_fd_n " to \"%V\" failed", &log->file->name); log->error_log_time = now; } return; } if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz", &log->file->name, n, len); log->error_log_time = now; }}static u_char *ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ size_t len; uintptr_t data; len = op->len; data = op->data; while (len--) { *buf++ = (u_char) (data & 0xff); data >>= 8; } return buf;}static u_char *ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_cpymem(buf, (u_char *) op->data, op->len);}static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_sprintf(buf, "%ui", r->connection->number);}static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ if (r->pipeline) { *buf = 'p'; } else { *buf = '.'; } return buf + 1;}static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_cpymem(buf, ngx_cached_http_log_time.data, ngx_cached_http_log_time.len);}static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ ngx_time_t *tp; tp = ngx_timeofday(); return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);}static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ ngx_time_t *tp; ngx_msec_int_t ms; tp = ngx_timeofday(); ms = (tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec); ms = (ms >= 0) ? ms : 0; return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000);}static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_sprintf(buf, "%ui", r->err_status ? r->err_status : r->headers_out.status);}static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_sprintf(buf, "%O", r->connection->sent);}/* * although there is a real $body_bytes_sent variable, * this log operation code function is more optimized for logging */static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ off_t length; length = r->connection->sent - r->header_size; if (length > 0) { return ngx_sprintf(buf, "%O", length); } *buf = '0'; return buf + 1;}static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op){ return ngx_sprintf(buf, "%O", r->request_length);}static ngx_int_tngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op, ngx_str_t *value){ ngx_int_t index; index = ngx_http_get_variable_index(cf, value); if (index == NGX_ERROR) { return NGX_ERROR; } op->len = 0; op->getlen = ngx_http_log_variable_getlen; op->run = ngx_http_log_variable; op->data = index; return NGX_OK;}static size_tngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data){ ngx_http_variable_value_t *value; value = ngx_http_get_indexed_variable(r, data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -