nginx⽇志模块ngx_http_log_module源码分析
⽇志相关的代码在ngx_http_log_module.c中
在f中相关的指令为:
log_format proxyformat "$time_iso8601 $remote_addr:$remote_port $server_addr:$server_port $upstream_addr $request_time $upstream_re th $body_bytes_sent \"$request_method $scheme://$http_host$request_uri $server_protocol\" \"$http_referer\" \"$http_user_agent\"";
access_log syslog:facility=local3,severity=info,server=127.0.0.1:514,tag=tengine proxyformat;
先关注log模块的初始化
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 configuration */
ngx_http_log_merge_loc_conf /* merge location configuration */
};
static void *
ngx_http_log_create_main_conf(ngx_conf_t *cf)
{
ngx_http_log_main_conf_t *conf;
ngx_http_log_fmt_t *fmt;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
if (conf == NULL) {
return NULL;
}
// 初始化format
if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
!= NGX_OK)
{
return NULL;
return conf;
}
static ngx_int_t
cacheablengx_http_log_init(ngx_conf_t *cf)
{
// 这块有判断是否使⽤默认的combine的逻辑,在tengine中,⾃定义了⼀波,所以不care // 将handler加⼊log阶段
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_log_handler;
return NGX_OK;
}
⽽在log_format指令的处理函数中,将这个fmt给保存下来
static char *
ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
// 获取loc_main_conf
ngx_http_log_main_conf_t *lmcf = conf;
// 初始化fmt
fmt = lmcf->formats.elts;
fmt = ngx_array_push(&lmcf->formats);
if (fmt == NULL) {
return NGX_CONF_ERROR;
}
// 赋值name
fmt->name = value[1];
// 初始化flushes和ops
fmt->flushes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
if (fmt->flushes == NULL) {
return NGX_CONF_ERROR;
}
fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
if (fmt->ops == NULL) {
return NGX_CONF_ERROR;
// 最后把整个⽇志格式编译
return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2); }
static char *
ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
{
// 遍历所有的args
for ( /* void */ ; s < args->nelts; s++) {
// 在已有的ngx_http_log_vars中看有没有指定的⽇志格式
for (v = ngx_http_log_vars; v->name.len; v++) {
if (v->name.len == var.len
&& ngx_strncmp(v->name.data, var.data, var.len) == 0)
{
// 将对应的⽅法,长度赋值给对应op,等待写⼊
op->len = v->len;
op->getlen = NULL;
op->run = v->run;
op->data = 0;
goto found;
}
}
// 没有的话则调⽤该函数
if (ngx_http_log_variable_compile(cf, op, &var) != NGX_OK) {
return NGX_CONF_ERROR;
}
if (len) {
op->len = len;
op->getlen = NULL;
// 如果长度⼩的话,就直接⽤data来记录
if (len <= sizeof(uintptr_t)) {
op->run = ngx_http_log_copy_short;
op->data = 0;
// 记录data
while (len--) {
op->data <<= 8;
op->data |= data[len];
}
// ⽐较长的话,记录成指针来指向,函数也是获取指针来进⾏获取值
} else {
op->run = ngx_http_log_copy_long;
p = ngx_pnalloc(cf->pool, len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
ngx_memcpy(p, data, len);
op->data = (uintptr_t) p;
}
}
}
static ngx_int_t
ngx_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);
op->len = 0;
op->getlen = ngx_http_log_variable_getlen;
op->run = ngx_http_log_variable;
op->data = index;
}
// ⽽这些可以进⼊⽇志中的参数,则是在core_preconfiguration函数中的ngx_http_variables_add_core_vars函数ngx_int_t
ngx_http_variables_add_core_vars(ngx_conf_t *cf)
{
cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
sizeof(ngx_hash_keys_arrays_t));
for (cv = ngx_http_core_variables; cv->name.len; cv++) {
v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
if (v == NULL) {
return NGX_ERROR;
}
*v = *cv;
rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
NGX_HASH_READONLY_KEY);
if (rc == NGX_OK) {
continue;
}
if (rc == NGX_BUSY) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"conflicting variable name \"%V\"", &v->name);
}
return NGX_ERROR;
}
接下来可以看下整个的ngx_http_core_variables
static ngx_http_variable_t ngx_http_core_variables[] = {
{ ngx_string("http_host"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.host), 0, 0 },
{ ngx_string("http_user_agent"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.user_agent), 0, 0 },
{ ngx_string("http_referer"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, ferer), 0, 0 },
#if (NGX_HTTP_GZIP)
{ ngx_string("http_via"), NULL, ngx_http_variable_header,
offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
#endif
#if (NGX_HTTP_X_FORWARDED_FOR)
{ ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_headers,
offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
#endif
{ ngx_string("http_cookie"), NULL, ngx_http_variable_cookies,
offsetof(ngx_http_request_t, kies), 0, 0 },
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论