该模块的实现原理比较简单:在NGX_LOG_PHASE阶段加入一个handler,根据请求是否upstream,再结合upstream->peer.cached参数即可判断该请求是否复用长连接。
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <nginx.h>
#include <ngx_files.h>
#define KEEPALIVE_LOG_DEBUG
#define KEEPALIVE_LOG_DEBUG_LEVEL NGX_LOG_NOTICE
#define KEEPALIVE_LOG_MAX_LOG_LEN 1024
typedef struct {
ngx_log_t *default_log;
}ngx_http_keepalive_log_main_conf_t;
typedef struct {
ngx_flag_t on;
ngx_log_t *log;
} ngx_http_keepalive_log_loc_conf_t;
static void* ngx_http_keepalive_log_create_main_conf(ngx_conf_t *cf);
static void* ngx_http_keepalive_log_create_loc_conf(ngx_conf_t *cf);
static char* ngx_http_keepalive_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);
static ngx_int_t ngx_http_keepalive_log_init(ngx_conf_t *cf);
static ngx_int_t ngx_http_keepalive_log_init_process(ngx_cycle_t *cycle);
static ngx_int_t ngx_http_keepalive_log_handler(ngx_http_request_t *r);
static void ngx_http_keepalive_log_get_req_info(ngx_http_request_t *r, ngx_str_t *serv, ngx_str_t *hostname, ngx_str_t *ip);
static ngx_log_t *ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name);
static char* ngx_http_keepalive_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_http_module_t ngx_http_keepalive_log_module_ctx = {
NULL,
ngx_http_keepalive_log_init, /* postconfiguration */
ngx_http_keepalive_log_create_main_conf, /* create main configuration */
NULL,
NULL,
NULL,
ngx_http_keepalive_log_create_loc_conf,
ngx_http_keepalive_log_merge_loc_conf
};
static ngx_command_t ngx_http_keepalive_log_commands[] = {
{
ngx_string("keepalive_log"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_HTTP_LIF_CONF | NGX_CONF_TAKE1,
ngx_http_keepalive_log_set_log,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
{
ngx_string("keepalive_log_enable"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_keepalive_log_loc_conf_t, on),
NULL
},
ngx_null_command
};
ngx_module_t ngx_http_keepalive_log_module = {
NGX_MODULE_V1,
&ngx_http_keepalive_log_module_ctx,
ngx_http_keepalive_log_commands,
NGX_HTTP_MODULE,
NULL, /* init master */
NULL, /* init module */
ngx_http_keepalive_log_init_process, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
static ngx_int_t
ngx_http_keepalive_log_init_process(ngx_cycle_t *cycle)
{
ngx_http_keepalive_log_main_conf_t *kmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_keepalive_log_module);
kmcf->default_log = &cycle->new_log;
return NGX_OK;
}
static void*
ngx_http_keepalive_log_create_main_conf(ngx_conf_t *cf)
{
ngx_http_keepalive_log_main_conf_t *kmcf;
kmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_keepalive_log_main_conf_t));
if(!kmcf) {
return NGX_CONF_ERROR;
}
kmcf->default_log = NULL;
return kmcf;
}
static void*
ngx_http_keepalive_log_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_keepalive_log_loc_conf_t *klcf;
klcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_keepalive_log_loc_conf_t));
if(klcf == NULL) {
return NULL;
}
klcf->on = NGX_CONF_UNSET;
klcf->log = NGX_CONF_UNSET_PTR;
return klcf;
}
static char*
ngx_http_keepalive_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_keepalive_log_loc_conf_t *prev = parent;
ngx_http_keepalive_log_loc_conf_t *conf = child;
ngx_conf_merge_value(conf->on, prev->on, 0);
ngx_conf_merge_ptr_value(conf->log, prev->log, NULL);
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_keepalive_log_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;