From f363b0cfe277bd8f2da7bfdea8029e088f0ff3f4 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Tue, 12 May 2009 17:51:50 +0400 Subject: [PATCH 01/11] Implment a basic status API Cc: catap@catap.ru `ngx_status_add_counter' add a counter `ngx_status_fetch_add' +1 to counter `ngx_status_get_value' get counter value `ngx_status_get_counters' get list of counters --- auto/modules | 8 +++ auto/options | 6 ++ auto/sources | 4 + src/core/ngx_core.h | 4 +- src/core/ngx_status.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ngx_status.h | 40 ++++++++++++ 6 files changed, 227 insertions(+), 1 deletions(-) create mode 100644 src/core/ngx_status.c create mode 100644 src/core/ngx_status.h diff --git a/auto/modules b/auto/modules index 9bc2e04db161cd187841bbb039f3b00026b6ccfa..d9f3dd579dbc1c9b109052eb6b7c798990927d81 100644 --- a/auto/modules +++ b/auto/modules @@ -424,6 +424,14 @@ if [ $NGX_CPP_TEST = YES ]; then fi +if [ $NGX_STATUS = YES ]; then + have=NGX_STATUS . auto/have + modules="$modules $NGX_STATUS_MODULE" + CORE_SRCS="$CORE_SRCS $NGX_STATUS_SRCS" + CORE_DEPS="$CORE_DEPS $NGX_STATUS_DEPS" +fi + + cat << END > $NGX_MODULES_C #include diff --git a/auto/options b/auto/options index 3b3ee0fae8093fecba53d69343adf592b24217ca..b48f1fba2ad3b4ae9874996873412dbe7ca89dc6 100644 --- a/auto/options +++ b/auto/options @@ -131,6 +131,8 @@ NGX_CPP_TEST=NO NGX_CPU_CACHE_LINE= +NGX_STATUS=YES + opt= for option @@ -260,6 +262,8 @@ do --with-zlib-opt=*) ZLIB_OPT="$value" ;; --with-zlib-asm=*) ZLIB_ASM="$value" ;; + --without-status) NGX_STATUS=NO ;; + --test-build-devpoll) NGX_TEST_BUILD_DEVPOLL=YES ;; --test-build-eventport) NGX_TEST_BUILD_EVENTPORT=YES ;; --test-build-epoll) NGX_TEST_BUILD_EPOLL=YES ;; @@ -394,6 +398,8 @@ cat << END --with-openssl=DIR set path to OpenSSL library sources --with-openssl-opt=OPTIONS set additional options for OpenSSL building + --without-status disable status + --with-debug enable the debugging logging END diff --git a/auto/sources b/auto/sources index e4649b030eaa64d005f4af07435f40dfe671ebd4..eb72a0a3618118df2680df1bd07856f6ea5a3957 100644 --- a/auto/sources +++ b/auto/sources @@ -484,3 +484,7 @@ NGX_GOOGLE_PERFTOOLS_MODULE=ngx_google_perftools_module NGX_GOOGLE_PERFTOOLS_SRCS=src/misc/ngx_google_perftools_module.c NGX_CPP_TEST_SRCS=src/misc/ngx_cpp_test_module.cpp + +NGX_STATUS_MODULE=ngx_status_module +NGX_STATUS_SRCS=src/core/ngx_status.c +NGX_STATUS_DEPS=src/core/ngx_status.h diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h index d5f18b84c2ac40e72aaef7d2f2429fe3aa5fac37..e4b07aadabdec7135df3a0ca3994cf7be8035c54 100644 --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -75,7 +75,9 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c); #include #include #include - +#if (NGX_PCRE) +#include +#endif #define LF (u_char) 10 #define CR (u_char) 13 diff --git a/src/core/ngx_status.c b/src/core/ngx_status.c new file mode 100644 index 0000000000000000000000000000000000000000..68c6f4b0200bf70da1dad7c34b7f98be322a5f48 --- /dev/null +++ b/src/core/ngx_status.c @@ -0,0 +1,166 @@ + +/* + * Copyright (C) Kirill A. Korinskiy + */ + + +#include +#include + + +static void *ngx_status_module_create_conf(ngx_cycle_t *cycle); + +static ngx_int_t ngx_status_module_init(ngx_cycle_t *cycle); + +typedef struct { + ngx_uint_t count; + ngx_status_list_t **counters; +} ngx_status_conf_t; + +static ngx_core_module_t ngx_status_module_ctx = { + ngx_string("ngx_status"), + ngx_status_module_create_conf, + NULL +}; + + +ngx_module_t ngx_status_module = { + NGX_MODULE_V1, + &ngx_status_module_ctx, /* module context */ + NULL, /* module directives */ + NGX_CORE_MODULE, /* module type */ + NULL, /* init master */ + ngx_status_module_init, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +ngx_int_t +ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, + ngx_status_counter_t *counter) +{ + ngx_status_conf_t *conf; + ngx_status_list_t *c, *cc; + + conf = (ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module); + + c = ngx_palloc(cycle->pool, sizeof(ngx_status_list_t)); + if (c == NULL) { + return NGX_ERROR; + } + + c->counter = counter; + c->next = NULL; + + if (conf->counters[module->index] == NULL) { + conf->counters[module->index] = c; + } else { + cc = conf->counters[module->index]; + + for (; cc->next; cc = cc->next); + + cc->next = c; + } + + conf->count++; + + return NGX_OK; +} + + +ngx_int_t +ngx_status_fetch_add(ngx_status_counter_t *counter) +{ + ngx_atomic_fetch_add(counter->value, 1); + + return NGX_OK; +} + + +ngx_int_t +ngx_status_get_value(ngx_status_counter_t *counter) +{ + return *(counter->value); +} + + +ngx_status_list_t ** +ngx_status_get_counters(ngx_cycle_t *cycle) +{ + return ((ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module))->counters; +} + + +static void * +ngx_status_module_create_conf(ngx_cycle_t *cycle) +{ + ngx_status_conf_t *conf; + ngx_uint_t i; + + conf = ngx_pcalloc(cycle->pool, sizeof(ngx_status_conf_t)); + if (conf == NULL) { + return NULL; + } + + for (i = 0; ngx_modules[i]; i++); + + conf->counters = ngx_pcalloc(cycle->pool, sizeof(ngx_status_list_t) * i); + if (conf->counters == NULL) { + return NULL; + } + + conf->count = 0; + + return conf; +} + + +static ngx_int_t +ngx_status_module_init(ngx_cycle_t *cycle) +{ + u_char *shared; + size_t size, cl; + ngx_shm_t shm; + ngx_uint_t i, j; + ngx_status_conf_t *conf; + ngx_status_list_t *c; + + conf = (ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module); + + if (!conf->count) { + return NGX_OK; + } + + /* cl should be equal or bigger than cache line size */ + cl = 128; + + size = conf->count * cl; + + shm.size = size; + shm.name.len = sizeof("nginx_status_shared_zone"); + shm.name.data = (u_char *) "nginx_status_shared_zone"; + shm.log = cycle->log; + + if (ngx_shm_alloc(&shm) != NGX_OK) { + return NGX_ERROR; + } + + shared = shm.addr; + + for (i = 0, j = 0; ngx_modules[i]; i++) { + c = conf->counters[ngx_modules[i]->index]; + + while (c) { + c->counter->value = (ngx_atomic_t *)(shared + (j * cl)); + j++; + c = c->next; + } + } + + return NGX_OK; +} diff --git a/src/core/ngx_status.h b/src/core/ngx_status.h new file mode 100644 index 0000000000000000000000000000000000000000..2b881a36bdebae0d8e83e8a48aef939531e977df --- /dev/null +++ b/src/core/ngx_status.h @@ -0,0 +1,40 @@ + +/* + * Copyright (C) Kirill A. Korinskiy + */ + + +#ifndef _NGX_STATUS_H_INCLUDED_ +#define _NGX_STATUS_H_INCLUDED_ + + +#include +#include + + +typedef struct ngx_status_list_s ngx_status_list_t; + +typedef struct { + ngx_str_t name; + ngx_str_t caption; + ngx_atomic_t *value; +} ngx_status_counter_t; + +struct ngx_status_list_s { + ngx_status_counter_t *counter; + ngx_status_list_t *next; +}; + +extern ngx_module_t ngx_status_module; + + +ngx_int_t ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, + ngx_status_counter_t *counter); + +ngx_int_t ngx_status_fetch_add(ngx_status_counter_t *counter); +ngx_int_t ngx_status_get_value(ngx_status_counter_t *counter); + +ngx_status_list_t **ngx_status_get_counters(ngx_cycle_t *cycle); + + +#endif /* _NGX_STATUS_H_INCLUDED_ */ -- 1.6.2 From da9c9cf9dea103b3abe9870a597d6217a89c4d61 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Fri, 15 May 2009 20:58:05 +0400 Subject: [PATCH 02/11] Add simple implement of status_txt Cc: catap@catap.ru --- auto/modules | 7 + auto/options | 3 + auto/sources | 3 + src/http/modules/ngx_http_status_txt_module.c | 222 +++++++++++++++++++++++++ 4 files changed, 235 insertions(+), 0 deletions(-) create mode 100644 src/http/modules/ngx_http_status_txt_module.c diff --git a/auto/modules b/auto/modules index d9f3dd579dbc1c9b109052eb6b7c798990927d81..72cb16b4f3790e2f3a31ee2d1e81c8c88d8b690b 100644 --- a/auto/modules +++ b/auto/modules @@ -325,6 +325,13 @@ if [ $HTTP_STUB_STATUS = YES ]; then HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_stub_status_module.c" fi +if [ $NGX_STATUS = YES ]; then + if [ $HTTP_STATUS_TXT = YES ]; then + HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_TXT_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_STATUS_TXT_SRCS" + fi +fi + #if [ -r $NGX_OBJS/auto ]; then # . $NGX_OBJS/auto #fi diff --git a/auto/options b/auto/options index b48f1fba2ad3b4ae9874996873412dbe7ca89dc6..3c2b2b5abed383641a68b922431384c5f54de1da 100644 --- a/auto/options +++ b/auto/options @@ -132,6 +132,7 @@ NGX_CPP_TEST=NO NGX_CPU_CACHE_LINE= NGX_STATUS=YES +HTTP_STATUS_TXT=YES opt= @@ -263,6 +264,7 @@ do --with-zlib-asm=*) ZLIB_ASM="$value" ;; --without-status) NGX_STATUS=NO ;; + --without-http_status_txt) NGX_HTTP_STATUS_TXT=NO ;; --test-build-devpoll) NGX_TEST_BUILD_DEVPOLL=YES ;; --test-build-eventport) NGX_TEST_BUILD_EVENTPORT=YES ;; @@ -399,6 +401,7 @@ cat << END --with-openssl-opt=OPTIONS set additional options for OpenSSL building --without-status disable status + --without-http_status_txt disable http_status_txt --with-debug enable the debugging logging diff --git a/auto/sources b/auto/sources index eb72a0a3618118df2680df1bd07856f6ea5a3957..cd3f2ae94f20377fef751da8c262016e1c99d14c 100644 --- a/auto/sources +++ b/auto/sources @@ -488,3 +488,6 @@ NGX_CPP_TEST_SRCS=src/misc/ngx_cpp_test_module.cpp NGX_STATUS_MODULE=ngx_status_module NGX_STATUS_SRCS=src/core/ngx_status.c NGX_STATUS_DEPS=src/core/ngx_status.h + +HTTP_STATUS_TXT_MODULE=ngx_http_status_txt_module +HTTP_STATUS_TXT_SRCS=src/http/modules/ngx_http_status_txt_module.c diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c new file mode 100644 index 0000000000000000000000000000000000000000..9a2486ff8c43f170cf1e0441822f80fbaa0ec16c --- /dev/null +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -0,0 +1,222 @@ + +/* + * Copyright (C) Kirill A. Korinskiy + */ + + +#include +#include +#include +#include + + +static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + +static ngx_command_t ngx_http_status_commands[] = { + + { ngx_string("status_txt"), + NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_http_status_txt, + 0, + 0, + NULL }, + + ngx_null_command +}; + + + +static ngx_http_module_t ngx_http_status_txt_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_status_txt_module = { + NGX_MODULE_V1, + &ngx_http_status_txt_module_ctx, /* module context */ + ngx_http_status_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_time_t last_configure; +static ngx_str_t last_configure_human_time; + + +static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) +{ + size_t size; + ngx_int_t rc; + ngx_buf_t *b; + ngx_uint_t i; + ngx_chain_t out; + + ngx_status_list_t **counters, *c; + + ngx_http_core_srv_conf_t *cscf; + + ngx_uint_t uptime, uptime_days, uptime_hours, uptime_minutes, uptime_seconds; + + if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + return NGX_HTTP_NOT_ALLOWED; + } + + rc = ngx_http_discard_request_body(r); + + if (rc != NGX_OK) { + return rc; + } + + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + if (cscf == NULL) { + return NGX_ERROR; + } + + uptime = ngx_time() - last_configure.sec; + uptime_days = uptime / 86400; + uptime -= uptime_days * 86400; + uptime_hours = uptime / 3600; + uptime -= uptime_hours * 3600; + uptime_minutes = uptime / 60; + uptime -= uptime_minutes * 60; + uptime_seconds = uptime; + uptime = ngx_time() - last_configure.sec; + + + counters = ngx_status_get_counters((ngx_cycle_t *)ngx_cycle); + + r->headers_out.content_type.len = sizeof("text/plain") - 1; + r->headers_out.content_type.data = (u_char *) "text/plain"; + + if (r->method == NGX_HTTP_HEAD) { + r->headers_out.status = NGX_HTTP_OK; + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + return rc; + } + } + + size = sizeof("Server " NGINX_VER " \n") - 1 + + cscf->server_name.len + + sizeof("Last config reload: ()\n") - 1 + NGX_INT_T_LEN + + last_configure_human_time.len + + sizeof("Uptime: (d h m s)\n") - 1 + NGX_INT_T_LEN + + NGX_INT_T_LEN + NGX_INT_T_LEN + NGX_INT_T_LEN + NGX_INT_T_LEN; + + for (i = 0; ngx_modules[i]; i++) { + c = counters[ngx_modules[i]->index]; + + if (c == NULL) { + continue; + } + + size += sizeof("\n") - 1; + + while (c) { + size += c->counter->caption.len + sizeof(": \n") - 1 + NGX_INT_T_LEN; + c = c->next; + } + } + + + b = ngx_create_temp_buf(r->pool, size); + if (b == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + out.buf = b; + out.next = NULL; + + b->last = ngx_sprintf(b->last, "Server " NGINX_VER " %V\n", + &cscf->server_name); + + b->last = ngx_sprintf(b->last, "Last config reload: %uA (%V)\n", + last_configure.sec, + &last_configure_human_time); + + b->last = ngx_sprintf(b->last, "Uptime: %uA (%uAd %uAh %uAm %uAs)\n", + uptime, uptime_days, uptime_hours, + uptime_minutes, uptime_seconds); + + for (i = 0; ngx_modules[i]; i++) { + c = counters[ngx_modules[i]->index]; + + if (c == NULL) { + continue; + } + + b->last = ngx_sprintf(b->last, "\n"); + + while (c) { + b->last = ngx_sprintf(b->last, "%V: %uA\n", + &c->counter->caption, ngx_status_get_value(c->counter)); + c = c->next; + } + } + + r->headers_out.status = NGX_HTTP_OK; + r->headers_out.content_length_n = b->last - b->pos; + + b->last_buf = 1; + + rc = ngx_http_send_header(r); + + if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { + return rc; + } + + return ngx_http_output_filter(r, &out); +} + +static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + +static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_tm_t tm; + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + clcf->handler = ngx_http_status_txt_handler; + + last_configure = *ngx_cached_time; + last_configure_human_time.len = sizeof("28/Sep/1970 12:00:00 +0600") - 1; + last_configure_human_time.data = ngx_palloc(cf->pool, last_configure_human_time.len); + if (last_configure_human_time.data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_gmtime(ngx_cached_time->sec + ngx_cached_time->gmtoff * 60, &tm); + + (void) ngx_sprintf(last_configure_human_time.data, + "%02d/%s/%d %02d:%02d:%02d %c%02d%02d", + tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], + tm.ngx_tm_year, tm.ngx_tm_hour, + tm.ngx_tm_min, tm.ngx_tm_sec, + ngx_cached_time->gmtoff < 0 ? '-' : '+', + ngx_abs(ngx_cached_time->gmtoff / 60), + ngx_abs(ngx_cached_time->gmtoff % 60)); + + return NGX_CONF_OK; +} -- 1.6.2 From 1c6a049c0240efccd68c58065c84990c4f671436 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Sat, 16 May 2009 10:17:18 +0400 Subject: [PATCH 03/11] Add information from classic nginx status to new status Cc: catap@catap.ru --- src/event/ngx_event.c | 6 +++--- src/event/ngx_event.h | 2 +- src/event/ngx_event_accept.c | 8 ++++---- src/http/modules/ngx_http_status_txt_module.c | 25 +++++++++++++++++++++++++ src/http/ngx_http_request.c | 18 +++++++++--------- src/http/ngx_http_request.h | 2 +- src/mail/ngx_mail_handler.c | 2 +- 7 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index e30c5636a7201bdeb39d20414a8770b3c069b120..dac0c01f7651719e3e7ac06c3f589281b5c7d186 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -57,7 +57,7 @@ ngx_int_t ngx_accept_disabled; ngx_file_t ngx_accept_mutex_lock_file; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_t ngx_stat_accepted0; ngx_atomic_t *ngx_stat_accepted = &ngx_stat_accepted0; @@ -494,7 +494,7 @@ ngx_event_module_init(ngx_cycle_t *cycle) size = cl /* ngx_accept_mutex */ + cl; /* ngx_connection_counter */ -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) size += cl /* ngx_stat_accepted */ + cl /* ngx_stat_handled */ @@ -526,7 +526,7 @@ ngx_event_module_init(ngx_cycle_t *cycle) ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl); -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_stat_accepted = (ngx_atomic_t *) (shared + 2 * cl); ngx_stat_handled = (ngx_atomic_t *) (shared + 3 * cl); diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 33c8cdc2d7d9bdac5b12228540a2467c4a61b0b9..791beaac3ebcbb368bc87f67fb72ed777131d8c2 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -477,7 +477,7 @@ extern ngx_msec_t ngx_accept_mutex_delay; extern ngx_int_t ngx_accept_disabled; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) extern ngx_atomic_t *ngx_stat_accepted; extern ngx_atomic_t *ngx_stat_handled; diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index a17d6303839b33e0a7ea130043ec5dfac69bdd8a..bc75a5adaa3d3e07b55ad4cc78bc2aff0d3f9e59 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -74,7 +74,7 @@ ngx_event_accept(ngx_event_t *ev) return; } -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_accepted, 1); #endif @@ -92,7 +92,7 @@ ngx_event_accept(ngx_event_t *ev) return; } -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_active, 1); #endif @@ -187,7 +187,7 @@ ngx_event_accept(ngx_event_t *ev) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_handled, 1); #endif @@ -378,7 +378,7 @@ ngx_close_accepted_connection(ngx_connection_t *c) ngx_destroy_pool(c->pool); } -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif } diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index 9a2486ff8c43f170cf1e0441822f80fbaa0ec16c..e5a37e1049ef56f27a79b2e78b0776aada50c986 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -69,6 +69,8 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) ngx_uint_t i; ngx_chain_t out; + ngx_atomic_int_t ap, hn, ac, rq, rd, wr; + ngx_status_list_t **counters, *c; ngx_http_core_srv_conf_t *cscf; @@ -123,6 +125,11 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) + sizeof("Uptime: (d h m s)\n") - 1 + NGX_INT_T_LEN + NGX_INT_T_LEN + NGX_INT_T_LEN + NGX_INT_T_LEN + NGX_INT_T_LEN; + size += sizeof("\nActive connections: \n") + NGX_ATOMIC_T_LEN + + sizeof("server accepts handled requests\n") - 1 + + 6 + 3 * NGX_ATOMIC_T_LEN + + sizeof("Reading: Writing: Waiting: \n") + 3 * NGX_ATOMIC_T_LEN; + for (i = 0; ngx_modules[i]; i++) { c = counters[ngx_modules[i]->index]; @@ -158,6 +165,24 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) uptime, uptime_days, uptime_hours, uptime_minutes, uptime_seconds); + ap = *ngx_stat_accepted; + hn = *ngx_stat_handled; + ac = *ngx_stat_active; + rq = *ngx_stat_requests; + rd = *ngx_stat_reading; + wr = *ngx_stat_writing; + + b->last = ngx_sprintf(b->last, "\nActive connections: %uA \n", ac); + + b->last = ngx_cpymem(b->last, "server accepts handled requests\n", + sizeof("server accepts handled requests\n") - 1); + + b->last = ngx_sprintf(b->last, " %uA %uA %uA \n", ap, hn, rq); + + b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA \n", + rd, wr, ac - (rd + wr)); + + for (i = 0; ngx_modules[i]; i++) { c = counters[ngx_modules[i]->index]; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 32f120c8e9cbb349712980a8eacc94090c7a1ca0..543a434227c88e1135765c05f04cf2769899c4c7 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -197,7 +197,7 @@ ngx_http_init_connection(ngx_connection_t *c) rev->handler = ngx_http_init_request; c->write->handler = ngx_http_empty_handler; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif @@ -216,7 +216,7 @@ ngx_http_init_connection(ngx_connection_t *c) ngx_add_timer(rev, c->listening->post_accept_timeout); if (ngx_handle_read_event(rev, 0) != NGX_OK) { -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif ngx_http_close_connection(c); @@ -246,7 +246,7 @@ ngx_http_init_request(ngx_event_t *rev) ngx_http_in6_addr_t *addr6; #endif -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, -1); #endif @@ -494,7 +494,7 @@ ngx_http_init_request(ngx_event_t *rev) ctx->current_request = r; r->log_handler = ngx_http_log_error_handler; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, 1); r->stat_reading = 1; ngx_atomic_fetch_add(ngx_stat_requests, 1); @@ -1541,7 +1541,7 @@ ngx_http_process_request(ngx_http_request_t *r) ngx_del_timer(c->read); } -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, -1); r->stat_reading = 0; ngx_atomic_fetch_add(ngx_stat_writing, 1); @@ -2308,7 +2308,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request"); -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif @@ -2538,7 +2538,7 @@ ngx_http_keepalive_handler(ngx_event_t *rev) b->last += n; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_reading, 1); #endif @@ -2765,7 +2765,7 @@ ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error) } } -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) if (r->stat_reading) { ngx_atomic_fetch_add(ngx_stat_reading, -1); @@ -2852,7 +2852,7 @@ ngx_http_close_connection(ngx_connection_t *c) #endif -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 4fef7c36cab74b4609407f81c32e94e9d0731b48..0d62cf9b27067fd866254c00406f9a45c56ae19f 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -496,7 +496,7 @@ struct ngx_http_request_s { unsigned filter_need_temporary:1; unsigned allow_ranges:1; -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) unsigned stat_reading:1; unsigned stat_writing:1; #endif diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c index 44ebdede23a21ab524751779b360a776b68bb37e..a44a1035a87a473ae1d5d4d39b8d2b2b878fd7da 100644 --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -673,7 +673,7 @@ ngx_mail_close_connection(ngx_connection_t *c) #endif -#if (NGX_STAT_STUB) +#if (NGX_STAT_STUB) || (NGX_STATUS) ngx_atomic_fetch_add(ngx_stat_active, -1); #endif -- 1.6.2 From 7db8f438953e1a79c5062a1ac6797deba8aedde8 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Fri, 15 May 2009 16:50:42 +0400 Subject: [PATCH 04/11] Implement support to status API in http core module Cc: catap@catap.ru --- src/http/ngx_http_core_module.c | 126 +++++++++++++++++++++++++++++++++++++++ src/http/ngx_http_core_module.h | 8 +++ src/http/ngx_http_request.c | 5 ++ 3 files changed, 139 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 73d7af96934db865d855506ca53483b88ec53c39..a23882799f00d2dfccd68c333cf164767f9ec9ff 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -838,6 +838,10 @@ ngx_http_core_find_config_phase(ngx_http_request_t *r, clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); +#if (NGX_STATUS) + ngx_status_fetch_add(clcf->request_counter); +#endif + if (!r->internal && clcf->internal) { ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); return NGX_OK; @@ -2398,6 +2402,59 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) *cf = pcf; +#if (NGX_STATUS) + cscf->request_counter = + ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); + if (cscf->request_counter == NULL) { + return NGX_CONF_ERROR; + } + + cscf->request_counter->name.len = sizeof("request_host_") - 1; + cscf->request_counter->caption.len = sizeof("Request for host ") - 1; + + if (cscf->server_name.len) { + cscf->request_counter->name.len += cscf->server_name.len; + cscf->request_counter->caption.len += cscf->server_name.len; + } else { + cscf->request_counter->name.len += sizeof("default") - 1; + cscf->request_counter->caption.len += sizeof("default") - 1; + } + + cscf->request_counter->name.data = + ngx_palloc(cf->pool, cscf->request_counter->name.len); + if (cscf->request_counter->name.data == NULL) { + return NGX_CONF_ERROR; + } + + cscf->request_counter->caption.data = + ngx_palloc(cf->pool, cscf->request_counter->caption.len); + if (cscf->request_counter->caption.data == NULL) { + return NGX_CONF_ERROR; + } + + if (cscf->server_name.len) { + ngx_sprintf(cscf->request_counter->name.data, + "request_host_%V", + &cscf->server_name); + + ngx_sprintf(cscf->request_counter->caption.data, + "Request for host %V", + &cscf->server_name); + } else { + ngx_sprintf(cscf->request_counter->name.data, + "request_host_default"); + + ngx_sprintf(cscf->request_counter->caption.data, + "Request for host default"); + } + + if (ngx_status_add_counter(cf->cycle, &ngx_http_module, + cscf->request_counter) != NGX_OK) { + return NGX_CONF_ERROR; + } + +#endif + return rv; } @@ -2414,6 +2471,9 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx, *pctx; ngx_http_core_loc_conf_t *clcf, *pclcf; +#if (NGX_STATUS) + ngx_http_core_srv_conf_t *cscf; +#endif ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); if (ctx == NULL) { @@ -2592,6 +2652,63 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) *cf = save; +#if (NGX_STATUS) + cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); + + clcf->request_counter = + ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); + if (clcf->request_counter == NULL) { + return NGX_CONF_ERROR; + } + + clcf->request_counter->name.len = sizeof("request_host__location_") - 1 + + clcf->name.len; + clcf->request_counter->caption.len = sizeof("Request for host , Location ") - 1 + + clcf->name.len; + + if (cscf->server_name.len) { + clcf->request_counter->name.len += cscf->server_name.len; + clcf->request_counter->caption.len += cscf->server_name.len; + } else { + clcf->request_counter->name.len += sizeof("default") - 1; + clcf->request_counter->caption.len += sizeof("default") - 1; + } + + clcf->request_counter->name.data = + ngx_palloc(cf->pool, clcf->request_counter->name.len); + if (clcf->request_counter->name.data == NULL) { + return NGX_CONF_ERROR; + } + + clcf->request_counter->caption.data = + ngx_palloc(cf->pool, clcf->request_counter->caption.len); + if (clcf->request_counter->caption.data == NULL) { + return NGX_CONF_ERROR; + } + + if (cscf->server_name.len) { + ngx_sprintf(clcf->request_counter->name.data, + "request_host_%V_location_%V", + &cscf->server_name, &clcf->name); + + ngx_sprintf(clcf->request_counter->caption.data, + "Request for host %V, Location %V", + &cscf->server_name, &clcf->name); + } else { + ngx_sprintf(clcf->request_counter->name.data, + "request_host_default_location_%V", &clcf->name); + + ngx_sprintf(clcf->request_counter->caption.data, + "Request for host default, Location %V", &clcf->name); + } + + if (ngx_status_add_counter(cf->cycle, &ngx_http_module, + clcf->request_counter) != NGX_OK) { + return NGX_CONF_ERROR; + } + +#endif + return rv; } @@ -2946,6 +3063,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) * lcf->auto_redirect = 0; * lcf->alias = 0; * lcf->gzip_proxied = 0; + * lcf->request_counter = NULL; */ lcf->client_max_body_size = NGX_CONF_UNSET; @@ -3243,6 +3361,14 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) #endif +#if (NGX_STATUS) + if (prev->request_counter) { + + conf->request_counter = prev->request_counter; + + } +#endif + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 2c4e45acd2da5260654552ec05a306d9ac822fb0..cfe2e642cea1a22062f5740a09ecfd14b2b23886 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -168,6 +168,10 @@ typedef struct { ngx_flag_t underscores_in_headers; ngx_http_core_loc_conf_t **named_locations; + +#if (NGX_STATUS) + ngx_status_counter_t *request_counter; +#endif } ngx_http_core_srv_conf_t; @@ -384,6 +388,10 @@ struct ngx_http_core_loc_conf_s { ngx_queue_t *locations; +#if (NGX_STATUS) + ngx_status_counter_t *request_counter; +#endif + #if 0 ngx_http_core_loc_conf_t *prev_location; #endif diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 543a434227c88e1135765c05f04cf2769899c4c7..ccc4d82de0f4bc16ea62bc7c89ec0b46ced38f82 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -500,6 +500,11 @@ ngx_http_init_request(ngx_event_t *rev) ngx_atomic_fetch_add(ngx_stat_requests, 1); #endif +#if (NGX_STATUS) + ngx_status_fetch_add(cscf->request_counter); +#endif + + rev->handler(rev); } -- 1.6.2 From 727c25106d973ea77e11f916923a794acd377eb2 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Mon, 18 May 2009 00:55:54 +0400 Subject: [PATCH 05/11] Implement periodic counter Cc: catap@catap.ru Add directive `status_window' Extend formats fot directive `status_txt' --- src/core/ngx_status.c | 138 ++++++++++++++++++----- src/core/ngx_status.h | 8 +- src/http/modules/ngx_http_status_txt_module.c | 149 ++++++++++++++++++++----- 3 files changed, 234 insertions(+), 61 deletions(-) diff --git a/src/core/ngx_status.c b/src/core/ngx_status.c index 68c6f4b0200bf70da1dad7c34b7f98be322a5f48..2517cf9055c4e5714d2b35fca0b6ab3910a6e11c 100644 --- a/src/core/ngx_status.c +++ b/src/core/ngx_status.c @@ -9,25 +9,41 @@ static void *ngx_status_module_create_conf(ngx_cycle_t *cycle); +static char *ngx_status_module_init_conf(ngx_cycle_t *cycle, void *conf); static ngx_int_t ngx_status_module_init(ngx_cycle_t *cycle); typedef struct { + ngx_uint_t window; ngx_uint_t count; ngx_status_list_t **counters; } ngx_status_conf_t; + +static ngx_command_t ngx_status_commands[] = { + + { ngx_string("status_window"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + 0, + offsetof(ngx_status_conf_t, window), + NULL }, + + ngx_null_command +}; + + static ngx_core_module_t ngx_status_module_ctx = { ngx_string("ngx_status"), ngx_status_module_create_conf, - NULL + ngx_status_module_init_conf }; ngx_module_t ngx_status_module = { NGX_MODULE_V1, &ngx_status_module_ctx, /* module context */ - NULL, /* module directives */ + ngx_status_commands, /* module directives */ NGX_CORE_MODULE, /* module type */ NULL, /* init master */ ngx_status_module_init, /* init module */ @@ -51,20 +67,20 @@ ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, c = ngx_palloc(cycle->pool, sizeof(ngx_status_list_t)); if (c == NULL) { - return NGX_ERROR; + return NGX_ERROR; } c->counter = counter; c->next = NULL; if (conf->counters[module->index] == NULL) { - conf->counters[module->index] = c; + conf->counters[module->index] = c; } else { - cc = conf->counters[module->index]; + cc = conf->counters[module->index]; - for (; cc->next; cc = cc->next); + for (; cc->next; cc = cc->next); - cc->next = c; + cc->next = c; } conf->count++; @@ -76,47 +92,109 @@ ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, ngx_int_t ngx_status_fetch_add(ngx_status_counter_t *counter) { - ngx_atomic_fetch_add(counter->value, 1); + ngx_atomic_t *window; + ngx_status_conf_t *conf; + + conf = (ngx_status_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx, + ngx_status_module); + + window = counter->windows + (ngx_time() % (2 * conf->window)); + + ngx_atomic_fetch_add(window, 1); + + if (window - conf->window > counter->windows) { + *(window - conf->window) = 0; + } else { + *(window + conf->window) = 0; + } + + ngx_atomic_fetch_add(counter->accumulate, 1); return NGX_OK; } ngx_int_t -ngx_status_get_value(ngx_status_counter_t *counter) +ngx_status_get_accumulate_value(ngx_status_counter_t *counter) { - return *(counter->value); + return *(counter->accumulate); +} + + +ngx_int_t +ngx_status_get_periodic_value(ngx_status_counter_t *counter, ngx_uint_t period) +{ + ngx_int_t sum ; + ngx_atomic_t *start, *last; + ngx_status_conf_t *conf; + + + conf = (ngx_status_conf_t *) + ngx_get_conf(ngx_cycle->conf_ctx, ngx_status_module); + + if (period > conf->window) { + period = conf->window; + } + + sum = 0; + last = counter->windows + 2 * conf->window; + start = counter->windows + (ngx_time() % (2 * conf->window)); + + for (; period; period--) { + sum += *start; + if (start - 1 < counter->windows) { + start = last; + } else { + start--; + } + } + + return sum; } ngx_status_list_t ** ngx_status_get_counters(ngx_cycle_t *cycle) { - return ((ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module))->counters; + return ((ngx_status_conf_t *) + ngx_get_conf(cycle->conf_ctx, ngx_status_module))->counters; } static void * ngx_status_module_create_conf(ngx_cycle_t *cycle) { - ngx_status_conf_t *conf; + ngx_status_conf_t *scf; ngx_uint_t i; - conf = ngx_pcalloc(cycle->pool, sizeof(ngx_status_conf_t)); - if (conf == NULL) { - return NULL; + scf = ngx_pcalloc(cycle->pool, sizeof(ngx_status_conf_t)); + if (scf == NULL) { + return NULL; } + scf->window = NGX_CONF_UNSET_UINT; + for (i = 0; ngx_modules[i]; i++); - conf->counters = ngx_pcalloc(cycle->pool, sizeof(ngx_status_list_t) * i); - if (conf->counters == NULL) { - return NULL; + scf->counters = ngx_pcalloc(cycle->pool, sizeof(ngx_status_list_t) * i); + if (scf->counters == NULL) { + return NULL; } - conf->count = 0; + scf->count = 0; - return conf; + return scf; +} + + +static char * +ngx_status_module_init_conf(ngx_cycle_t *cycle, void *conf) +{ + ngx_status_conf_t *scf = conf; + + ngx_conf_init_uint_value(scf->window, 300); + + return NGX_CONF_OK; } @@ -133,13 +211,13 @@ ngx_status_module_init(ngx_cycle_t *cycle) conf = (ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module); if (!conf->count) { - return NGX_OK; + return NGX_OK; } /* cl should be equal or bigger than cache line size */ cl = 128; - size = conf->count * cl; + size = conf->count * cl + 2 * conf->window * conf->count * cl; shm.size = size; shm.name.len = sizeof("nginx_status_shared_zone"); @@ -153,13 +231,15 @@ ngx_status_module_init(ngx_cycle_t *cycle) shared = shm.addr; for (i = 0, j = 0; ngx_modules[i]; i++) { - c = conf->counters[ngx_modules[i]->index]; - - while (c) { - c->counter->value = (ngx_atomic_t *)(shared + (j * cl)); - j++; - c = c->next; - } + c = conf->counters[ngx_modules[i]->index]; + + while (c) { + c->counter->accumulate = (ngx_atomic_t *)(shared + (j * cl)); + c->counter->windows = (ngx_atomic_t *)(shared + (conf->count * cl) + + (2 * j * cl * conf->window)); + j++; + c = c->next; + } } return NGX_OK; diff --git a/src/core/ngx_status.h b/src/core/ngx_status.h index 2b881a36bdebae0d8e83e8a48aef939531e977df..dc2f159a244ef0f5c136f6734edb07584f92f7b6 100644 --- a/src/core/ngx_status.h +++ b/src/core/ngx_status.h @@ -17,7 +17,8 @@ typedef struct ngx_status_list_s ngx_status_list_t; typedef struct { ngx_str_t name; ngx_str_t caption; - ngx_atomic_t *value; + ngx_atomic_t *accumulate; + ngx_atomic_t *windows; } ngx_status_counter_t; struct ngx_status_list_s { @@ -32,7 +33,10 @@ ngx_int_t ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, ngx_status_counter_t *counter); ngx_int_t ngx_status_fetch_add(ngx_status_counter_t *counter); -ngx_int_t ngx_status_get_value(ngx_status_counter_t *counter); + +ngx_int_t ngx_status_get_accumulate_value(ngx_status_counter_t *counter); +ngx_int_t ngx_status_get_periodic_value(ngx_status_counter_t *counter, + ngx_uint_t period); ngx_status_list_t **ngx_status_get_counters(ngx_cycle_t *cycle); diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index e5a37e1049ef56f27a79b2e78b0776aada50c986..b4911ef0aeccfb12e272feb96b77b1683364d1e8 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -10,23 +10,31 @@ #include +typedef struct { + ngx_array_t *periods; +} ngx_http_status_txt_loc_conf_t; + + +static void *ngx_http_status_txt_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_status_txt_merge_loc_conf(ngx_conf_t *cf, + void *parent, void *child); + static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_command_t ngx_http_status_commands[] = { { ngx_string("status_txt"), - NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, ngx_http_status_txt, - 0, - 0, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_status_txt_loc_conf_t, periods), NULL }, ngx_null_command }; - static ngx_http_module_t ngx_http_status_txt_module_ctx = { NULL, /* preconfiguration */ NULL, /* postconfiguration */ @@ -37,8 +45,8 @@ static ngx_http_module_t ngx_http_status_txt_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ - NULL, /* create location configuration */ - NULL /* merge location configuration */ + ngx_http_status_txt_create_loc_conf, /* create location configuration */ + ngx_http_status_txt_merge_loc_conf /* merge location configuration */ }; @@ -66,7 +74,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) size_t size; ngx_int_t rc; ngx_buf_t *b; - ngx_uint_t i; + ngx_uint_t i, j; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr; @@ -77,6 +85,8 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) ngx_uint_t uptime, uptime_days, uptime_hours, uptime_minutes, uptime_seconds; + ngx_http_status_txt_loc_conf_t *conf; + if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } @@ -87,6 +97,8 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) return rc; } + conf = ngx_http_get_module_loc_conf(r, ngx_http_status_txt_module); + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); if (cscf == NULL) { return NGX_ERROR; @@ -131,18 +143,21 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) + sizeof("Reading: Writing: Waiting: \n") + 3 * NGX_ATOMIC_T_LEN; for (i = 0; ngx_modules[i]; i++) { - c = counters[ngx_modules[i]->index]; + c = counters[ngx_modules[i]->index]; - if (c == NULL) { - continue; - } + if (c == NULL) { + continue; + } - size += sizeof("\n") - 1; + size += sizeof("\n") - 1; - while (c) { - size += c->counter->caption.len + sizeof(": \n") - 1 + NGX_INT_T_LEN; - c = c->next; - } + while (c) { + size += c->counter->caption.len + sizeof(": \n") - 1 + NGX_INT_T_LEN; + c = c->next; + if (conf->periods) { + size += conf->periods->nelts * (sizeof(", ") - 1 + NGX_INT_T_LEN); + } + } } @@ -163,7 +178,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) b->last = ngx_sprintf(b->last, "Uptime: %uA (%uAd %uAh %uAm %uAs)\n", uptime, uptime_days, uptime_hours, - uptime_minutes, uptime_seconds); + uptime_minutes, uptime_seconds); ap = *ngx_stat_accepted; hn = *ngx_stat_handled; @@ -184,19 +199,31 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) for (i = 0; ngx_modules[i]; i++) { - c = counters[ngx_modules[i]->index]; + c = counters[ngx_modules[i]->index]; + + if (c == NULL) { + continue; + } + + b->last = ngx_sprintf(b->last, "\n"); - if (c == NULL) { - continue; - } + while (c) { + b->last = ngx_sprintf(b->last, "%V: %uA", + &c->counter->caption, + ngx_status_get_accumulate_value(c->counter)); + if (conf->periods) { + for (j = 0; j < conf->periods->nelts; j++) { + b->last = ngx_sprintf(b->last, ", %uA", + ngx_status_get_periodic_value( + c->counter, + ((ngx_int_t *)conf->periods->elts)[j])); + } + } - b->last = ngx_sprintf(b->last, "\n"); + b->last = ngx_sprintf(b->last, "\n"); - while (c) { - b->last = ngx_sprintf(b->last, "%V: %uA\n", - &c->counter->caption, ngx_status_get_value(c->counter)); - c = c->next; - } + c = c->next; + } } r->headers_out.status = NGX_HTTP_OK; @@ -213,21 +240,64 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) return ngx_http_output_filter(r, &out); } + +static void * +ngx_http_status_txt_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_status_txt_loc_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_status_txt_loc_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + return conf; +} + + +static char * +ngx_http_status_txt_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_status_txt_loc_conf_t *prev = parent; + ngx_http_status_txt_loc_conf_t *conf = child; + + if (conf->periods == NULL) { + conf->periods = prev->periods; + } + + return NGX_CONF_OK; +} + + static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_tm_t tm; + u_char *p = conf; + ngx_tm_t tm; + ngx_str_t *value; + ngx_uint_t *period, i; + ngx_array_t **periods; + ngx_http_core_loc_conf_t *clcf; + periods = (ngx_array_t **) (p + cmd->offset); + + value = cf->args->elts; + + if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) { + return NGX_CONF_OK; + } + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_status_txt_handler; last_configure = *ngx_cached_time; - last_configure_human_time.len = sizeof("28/Sep/1970 12:00:00 +0600") - 1; - last_configure_human_time.data = ngx_palloc(cf->pool, last_configure_human_time.len); + last_configure_human_time.len = sizeof("28/May/1987 17:30:00 +0400") - 1; + last_configure_human_time.data = ngx_palloc(cf->pool, + last_configure_human_time.len); if (last_configure_human_time.data == NULL) { return NGX_CONF_ERROR; } @@ -243,5 +313,24 @@ static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_abs(ngx_cached_time->gmtoff / 60), ngx_abs(ngx_cached_time->gmtoff % 60)); + if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) { + return NGX_CONF_OK; + } + + *periods = ngx_array_create(cf->pool, cf->args->nelts - 1, + sizeof(ngx_uint_t)); + if (*periods == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 1; i < cf->args->nelts; i++) { + period = ngx_array_push(*periods); + *period = ngx_atoi(value[i].data, value[i].len); + + if ((ngx_int_t)*period == NGX_ERROR) { + return NGX_CONF_ERROR; + } + } + return NGX_CONF_OK; } -- 1.6.2 From 984e9929449fa013e8218e9d924ef00d4aac0fc7 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Mon, 18 May 2009 16:47:40 +0400 Subject: [PATCH 06/11] Add counter action per seconds or avg value for period Cc: catap@catap.ru --- src/http/modules/ngx_http_status_txt_module.c | 20 +++++++++++++------- 1 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index b4911ef0aeccfb12e272feb96b77b1683364d1e8..33b660cc2db36a528a52b7ca4587442825bb8448 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -72,9 +72,9 @@ static ngx_str_t last_configure_human_time; static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) { size_t size; - ngx_int_t rc; + ngx_int_t rc, periodic_value; ngx_buf_t *b; - ngx_uint_t i, j; + ngx_uint_t i, j, period; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr; @@ -155,7 +155,9 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) size += c->counter->caption.len + sizeof(": \n") - 1 + NGX_INT_T_LEN; c = c->next; if (conf->periods) { - size += conf->periods->nelts * (sizeof(", ") - 1 + NGX_INT_T_LEN); + size += sizeof("()") - 1 + NGX_INT_T_LEN; + size += conf->periods->nelts * (sizeof(", ()") - 1 + + NGX_INT_T_LEN + NGX_INT_T_LEN); } } } @@ -212,11 +214,15 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) &c->counter->caption, ngx_status_get_accumulate_value(c->counter)); if (conf->periods) { + periodic_value = ngx_status_get_periodic_value(c->counter, 1); + b->last = ngx_sprintf(b->last, "(%uA)", periodic_value); for (j = 0; j < conf->periods->nelts; j++) { - b->last = ngx_sprintf(b->last, ", %uA", - ngx_status_get_periodic_value( - c->counter, - ((ngx_int_t *)conf->periods->elts)[j])); + period = ((ngx_int_t *)conf->periods->elts)[j]; + periodic_value = + ngx_status_get_periodic_value(c->counter, period); + b->last = + ngx_sprintf(b->last, ", %uA(%uA)", + periodic_value, periodic_value / period); } } -- 1.6.2 From b384bc82376c3c0f8da6f54ea118f1237c16705f Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Mon, 18 May 2009 17:43:46 +0400 Subject: [PATCH 07/11] Write a full location name Cc: catap@catap.ru --- src/http/ngx_http_core_module.c | 68 +++++++++++++++++++++++--------------- 1 files changed, 41 insertions(+), 27 deletions(-) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index a23882799f00d2dfccd68c333cf164767f9ec9ff..1e9ea366530202e9bfa6f61d4ddbaae4c12b45e2 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2473,6 +2473,8 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) ngx_http_core_loc_conf_t *clcf, *pclcf; #if (NGX_STATUS) ngx_http_core_srv_conf_t *cscf; + u_char *p_name; + u_char *p_caption; #endif ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); @@ -2640,18 +2642,6 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) } } - if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { - return NGX_CONF_ERROR; - } - - save = *cf; - cf->ctx = ctx; - cf->cmd_type = NGX_HTTP_LOC_CONF; - - rv = ngx_conf_parse(cf, NULL); - - *cf = save; - #if (NGX_STATUS) cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); @@ -2661,10 +2651,8 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - clcf->request_counter->name.len = sizeof("request_host__location_") - 1 - + clcf->name.len; - clcf->request_counter->caption.len = sizeof("Request for host , Location ") - 1 - + clcf->name.len; + clcf->request_counter->name.len = sizeof("request_host__location_") - 1 + value[1].len; + clcf->request_counter->caption.len = sizeof("Request for host , Location ") - 1 + value[1].len; if (cscf->server_name.len) { clcf->request_counter->name.len += cscf->server_name.len; @@ -2674,6 +2662,11 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) clcf->request_counter->caption.len += sizeof("default") - 1; } + if (cf->args->nelts == 3) { + clcf->request_counter->name.len += sizeof("_") - 1 + value[2].len; + clcf->request_counter->caption.len += sizeof(" ") - 1 + value[2].len; + } + clcf->request_counter->name.data = ngx_palloc(cf->pool, clcf->request_counter->name.len); if (clcf->request_counter->name.data == NULL) { @@ -2686,20 +2679,29 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) return NGX_CONF_ERROR; } - if (cscf->server_name.len) { - ngx_sprintf(clcf->request_counter->name.data, - "request_host_%V_location_%V", - &cscf->server_name, &clcf->name); + p_name = clcf->request_counter->name.data; + p_caption = clcf->request_counter->caption.data; + + p_name = ngx_sprintf(p_name, "request_host_"); + p_caption = ngx_sprintf(p_caption, "Request for host "); - ngx_sprintf(clcf->request_counter->caption.data, - "Request for host %V, Location %V", - &cscf->server_name, &clcf->name); + if (cscf->server_name.len) { + p_name = ngx_sprintf(p_name, "%V", &cscf->server_name); + p_caption = ngx_sprintf(p_caption, "%V", &cscf->server_name); } else { - ngx_sprintf(clcf->request_counter->name.data, - "request_host_default_location_%V", &clcf->name); + p_name = ngx_sprintf(p_name, "default"); + p_caption = ngx_sprintf(p_caption, "default"); + } + + p_name = ngx_sprintf(p_name, "_location_"); + p_caption = ngx_sprintf(p_caption, " Location "); - ngx_sprintf(clcf->request_counter->caption.data, - "Request for host default, Location %V", &clcf->name); + if (cf->args->nelts == 3) { + p_name = ngx_sprintf(p_name, "%V_%V", &value[1], &value[2]); + p_caption = ngx_sprintf(p_caption, "%V %V", &value[1], &value[2]); + } else { + p_name = ngx_sprintf(p_name, "%V", &value[1]); + p_caption = ngx_sprintf(p_caption, "%V", &value[1]); } if (ngx_status_add_counter(cf->cycle, &ngx_http_module, @@ -2709,6 +2711,18 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) #endif + if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { + return NGX_CONF_ERROR; + } + + save = *cf; + cf->ctx = ctx; + cf->cmd_type = NGX_HTTP_LOC_CONF; + + rv = ngx_conf_parse(cf, NULL); + + *cf = save; + return rv; } -- 1.6.2 From f35dcdf98672e4d98b4570f8606b1302f6b39c2c Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Tue, 19 May 2009 18:08:43 +0400 Subject: [PATCH 08/11] Add tree-based counters Cc: catap@catap.ru --- src/core/ngx_status.c | 63 +++++++++-- src/core/ngx_status.h | 12 ++- src/http/modules/ngx_http_status_txt_module.c | 100 +++++++++++----- src/http/ngx_http_core_module.c | 156 ++++++++++++------------- 4 files changed, 206 insertions(+), 125 deletions(-) diff --git a/src/core/ngx_status.c b/src/core/ngx_status.c index 2517cf9055c4e5714d2b35fca0b6ab3910a6e11c..982d192914341cb4a998ede34c5bd8c58718c9fc 100644 --- a/src/core/ngx_status.c +++ b/src/core/ngx_status.c @@ -90,6 +90,39 @@ ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, ngx_int_t +ngx_status_add_child(ngx_cycle_t *cycle, ngx_status_counter_t *parent, + ngx_status_counter_t *child) +{ + ngx_status_conf_t *conf; + ngx_status_list_t *c, *cc; + + conf = (ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module); + + c = ngx_palloc(cycle->pool, sizeof(ngx_status_list_t)); + if (c == NULL) { + return NGX_ERROR; + } + + c->counter = child; + c->next = NULL; + + if (parent->childs == NULL) { + parent->childs = c; + } else { + cc = parent->childs; + + for (; cc->next; cc = cc->next); + + cc->next = c; + } + + conf->count++; + + return NGX_OK; +} + + +ngx_int_t ngx_status_fetch_add(ngx_status_counter_t *counter) { ngx_atomic_t *window; @@ -197,6 +230,24 @@ ngx_status_module_init_conf(ngx_cycle_t *cycle, void *conf) return NGX_CONF_OK; } +static ngx_uint_t +ngx_status_set_associating_memory(u_char *shared, size_t cl, + ngx_uint_t count, ngx_uint_t window, ngx_status_list_t *c, ngx_uint_t j) +{ + while (c) { + c->counter->accumulate = (ngx_atomic_t *)(shared + (j * cl)); + c->counter->windows = (ngx_atomic_t *)(shared + (count * cl) + + (2 * j * cl * window)); + + j = ngx_status_set_associating_memory(shared, cl, count, window, + c->counter->childs, j + 1); + + c = c->next; + } + + return j; +} + static ngx_int_t ngx_status_module_init(ngx_cycle_t *cycle) @@ -206,7 +257,6 @@ ngx_status_module_init(ngx_cycle_t *cycle) ngx_shm_t shm; ngx_uint_t i, j; ngx_status_conf_t *conf; - ngx_status_list_t *c; conf = (ngx_status_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_status_module); @@ -231,15 +281,8 @@ ngx_status_module_init(ngx_cycle_t *cycle) shared = shm.addr; for (i = 0, j = 0; ngx_modules[i]; i++) { - c = conf->counters[ngx_modules[i]->index]; - - while (c) { - c->counter->accumulate = (ngx_atomic_t *)(shared + (j * cl)); - c->counter->windows = (ngx_atomic_t *)(shared + (conf->count * cl) - + (2 * j * cl * conf->window)); - j++; - c = c->next; - } + j = ngx_status_set_associating_memory(shared, cl, conf->count, + conf->window, conf->counters[ngx_modules[i]->index], j); } return NGX_OK; diff --git a/src/core/ngx_status.h b/src/core/ngx_status.h index dc2f159a244ef0f5c136f6734edb07584f92f7b6..4491d83f455b99ee4f091bb25a325b6c6a6d62be 100644 --- a/src/core/ngx_status.h +++ b/src/core/ngx_status.h @@ -15,10 +15,11 @@ typedef struct ngx_status_list_s ngx_status_list_t; typedef struct { - ngx_str_t name; - ngx_str_t caption; - ngx_atomic_t *accumulate; - ngx_atomic_t *windows; + ngx_str_t name; + ngx_str_t caption; + ngx_atomic_t *accumulate; + ngx_atomic_t *windows; + ngx_status_list_t *childs; } ngx_status_counter_t; struct ngx_status_list_s { @@ -32,6 +33,9 @@ extern ngx_module_t ngx_status_module; ngx_int_t ngx_status_add_counter(ngx_cycle_t *cycle, ngx_module_t *module, ngx_status_counter_t *counter); +ngx_int_t ngx_status_add_child(ngx_cycle_t *cycle, ngx_status_counter_t *parent, + ngx_status_counter_t *child); + ngx_int_t ngx_status_fetch_add(ngx_status_counter_t *counter); ngx_int_t ngx_status_get_accumulate_value(ngx_status_counter_t *counter); diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index 33b660cc2db36a528a52b7ca4587442825bb8448..972aba4a63521cb210c9ac3023e59d0d254926f2 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -69,12 +69,76 @@ static ngx_time_t last_configure; static ngx_str_t last_configure_human_time; +static ngx_int_t +ngx_http_status_calcualte_len(ngx_status_list_t *c, + ngx_array_t *periods, ngx_uint_t level) +{ + ngx_uint_t size = 0; + + while (c) { + size += level * (sizeof(" ") - 1); + size += sizeof(": \n") - 1 + c->counter->caption.len + + NGX_INT_T_LEN; + + if (periods) { + size += sizeof("()") - 1 + NGX_INT_T_LEN; + size += periods->nelts * (sizeof(", ()") - 1 + + NGX_INT_T_LEN + NGX_INT_T_LEN); + } + + size += ngx_http_status_calcualte_len(c->counter->childs, periods, level + 1); + + c = c->next; + } + + return size; +} + + +static u_char* +ngx_http_status_write_counter(u_char *p, ngx_status_list_t *c, + ngx_array_t *periods, ngx_uint_t level) +{ + ngx_int_t periodic_value; + ngx_uint_t i, j, period; + + while (c) { + for (i = level; i; i--) { + *(p++) = ' '; + } + + p = ngx_sprintf(p, "%V: %uA", &c->counter->caption, + ngx_status_get_accumulate_value(c->counter)); + + if (periods) { + periodic_value = ngx_status_get_periodic_value(c->counter, 1); + p = ngx_sprintf(p, "(%uA)", periodic_value); + for (j = 0; j < periods->nelts; j++) { + period = ((ngx_int_t *)periods->elts)[j]; + periodic_value = + ngx_status_get_periodic_value(c->counter, period); + p = ngx_sprintf(p, ", %uA(%uA)", periodic_value, + periodic_value / period); + } + } + + *(p++) = '\n'; + + p = ngx_http_status_write_counter(p, c->counter->childs, periods, level + 1); + + c = c->next; + } + + return p; +} + + static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) { size_t size; - ngx_int_t rc, periodic_value; + ngx_int_t rc; ngx_buf_t *b; - ngx_uint_t i, j, period; + ngx_uint_t i; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr; @@ -151,15 +215,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) size += sizeof("\n") - 1; - while (c) { - size += c->counter->caption.len + sizeof(": \n") - 1 + NGX_INT_T_LEN; - c = c->next; - if (conf->periods) { - size += sizeof("()") - 1 + NGX_INT_T_LEN; - size += conf->periods->nelts * (sizeof(", ()") - 1 - + NGX_INT_T_LEN + NGX_INT_T_LEN); - } - } + size += ngx_http_status_calcualte_len(c, conf->periods, 0); } @@ -209,27 +265,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) b->last = ngx_sprintf(b->last, "\n"); - while (c) { - b->last = ngx_sprintf(b->last, "%V: %uA", - &c->counter->caption, - ngx_status_get_accumulate_value(c->counter)); - if (conf->periods) { - periodic_value = ngx_status_get_periodic_value(c->counter, 1); - b->last = ngx_sprintf(b->last, "(%uA)", periodic_value); - for (j = 0; j < conf->periods->nelts; j++) { - period = ((ngx_int_t *)conf->periods->elts)[j]; - periodic_value = - ngx_status_get_periodic_value(c->counter, period); - b->last = - ngx_sprintf(b->last, ", %uA(%uA)", - periodic_value, periodic_value / period); - } - } - - b->last = ngx_sprintf(b->last, "\n"); - - c = c->next; - } + b->last = ngx_http_status_write_counter(b->last, c, conf->periods, 0); } r->headers_out.status = NGX_HTTP_OK; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 1e9ea366530202e9bfa6f61d4ddbaae4c12b45e2..237fb7dc4f77ca2505016434a7c9d69c973aa55f 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2391,9 +2391,15 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) *cscfp = cscf; +#if (NGX_STATUS) + cscf->request_counter = + ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); + if (cscf->request_counter == NULL) { + return NGX_CONF_ERROR; + } +#endif /* parse inside server{} */ - pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_HTTP_SRV_CONF; @@ -2403,54 +2409,48 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) *cf = pcf; #if (NGX_STATUS) - cscf->request_counter = - ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); - if (cscf->request_counter == NULL) { - return NGX_CONF_ERROR; - } - cscf->request_counter->name.len = sizeof("request_host_") - 1; cscf->request_counter->caption.len = sizeof("Request for host ") - 1; if (cscf->server_name.len) { - cscf->request_counter->name.len += cscf->server_name.len; - cscf->request_counter->caption.len += cscf->server_name.len; + cscf->request_counter->name.len += cscf->server_name.len; + cscf->request_counter->caption.len += cscf->server_name.len; } else { - cscf->request_counter->name.len += sizeof("default") - 1; - cscf->request_counter->caption.len += sizeof("default") - 1; + cscf->request_counter->name.len += sizeof("default") - 1; + cscf->request_counter->caption.len += sizeof("default") - 1; } cscf->request_counter->name.data = - ngx_palloc(cf->pool, cscf->request_counter->name.len); + ngx_palloc(cf->pool, cscf->request_counter->name.len); if (cscf->request_counter->name.data == NULL) { - return NGX_CONF_ERROR; + return NGX_CONF_ERROR; } cscf->request_counter->caption.data = - ngx_palloc(cf->pool, cscf->request_counter->caption.len); + ngx_palloc(cf->pool, cscf->request_counter->caption.len); if (cscf->request_counter->caption.data == NULL) { - return NGX_CONF_ERROR; + return NGX_CONF_ERROR; } if (cscf->server_name.len) { - ngx_sprintf(cscf->request_counter->name.data, - "request_host_%V", - &cscf->server_name); + ngx_sprintf(cscf->request_counter->name.data, + "request_host_%V", + &cscf->server_name); - ngx_sprintf(cscf->request_counter->caption.data, - "Request for host %V", - &cscf->server_name); + ngx_sprintf(cscf->request_counter->caption.data, + "Request for host %V", + &cscf->server_name); } else { - ngx_sprintf(cscf->request_counter->name.data, - "request_host_default"); + ngx_sprintf(cscf->request_counter->name.data, + "request_host_default"); - ngx_sprintf(cscf->request_counter->caption.data, - "Request for host default"); + ngx_sprintf(cscf->request_counter->caption.data, + "Request for host default"); } if (ngx_status_add_counter(cf->cycle, &ngx_http_module, - cscf->request_counter) != NGX_OK) { - return NGX_CONF_ERROR; + cscf->request_counter) != NGX_OK) { + return NGX_CONF_ERROR; } #endif @@ -2645,68 +2645,66 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) #if (NGX_STATUS) cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); - clcf->request_counter = - ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); - if (clcf->request_counter == NULL) { - return NGX_CONF_ERROR; - } + if (cscf->request_counter) { - clcf->request_counter->name.len = sizeof("request_host__location_") - 1 + value[1].len; - clcf->request_counter->caption.len = sizeof("Request for host , Location ") - 1 + value[1].len; + clcf->request_counter = + ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); + if (clcf->request_counter == NULL) { + return NGX_CONF_ERROR; + } - if (cscf->server_name.len) { - clcf->request_counter->name.len += cscf->server_name.len; - clcf->request_counter->caption.len += cscf->server_name.len; - } else { - clcf->request_counter->name.len += sizeof("default") - 1; - clcf->request_counter->caption.len += sizeof("default") - 1; - } + clcf->request_counter->name.len = sizeof("request_host__location_") - 1 + value[1].len; + clcf->request_counter->caption.len = sizeof("Location ") - 1 + value[1].len; - if (cf->args->nelts == 3) { - clcf->request_counter->name.len += sizeof("_") - 1 + value[2].len; - clcf->request_counter->caption.len += sizeof(" ") - 1 + value[2].len; - } + if (cscf->server_name.len) { + clcf->request_counter->name.len += cscf->server_name.len; + } else { + clcf->request_counter->name.len += sizeof("default") - 1; + } - clcf->request_counter->name.data = - ngx_palloc(cf->pool, clcf->request_counter->name.len); - if (clcf->request_counter->name.data == NULL) { - return NGX_CONF_ERROR; - } + if (cf->args->nelts == 3) { + clcf->request_counter->name.len += sizeof("_") - 1 + value[2].len; + clcf->request_counter->caption.len += sizeof(" ") - 1 + value[2].len; + } - clcf->request_counter->caption.data = - ngx_palloc(cf->pool, clcf->request_counter->caption.len); - if (clcf->request_counter->caption.data == NULL) { - return NGX_CONF_ERROR; - } + clcf->request_counter->name.data = + ngx_palloc(cf->pool, clcf->request_counter->name.len); + if (clcf->request_counter->name.data == NULL) { + return NGX_CONF_ERROR; + } - p_name = clcf->request_counter->name.data; - p_caption = clcf->request_counter->caption.data; + clcf->request_counter->caption.data = + ngx_palloc(cf->pool, clcf->request_counter->caption.len); + if (clcf->request_counter->caption.data == NULL) { + return NGX_CONF_ERROR; + } - p_name = ngx_sprintf(p_name, "request_host_"); - p_caption = ngx_sprintf(p_caption, "Request for host "); + p_name = clcf->request_counter->name.data; + p_caption = clcf->request_counter->caption.data; - if (cscf->server_name.len) { - p_name = ngx_sprintf(p_name, "%V", &cscf->server_name); - p_caption = ngx_sprintf(p_caption, "%V", &cscf->server_name); - } else { - p_name = ngx_sprintf(p_name, "default"); - p_caption = ngx_sprintf(p_caption, "default"); - } + p_name = ngx_sprintf(p_name, "request_host_"); - p_name = ngx_sprintf(p_name, "_location_"); - p_caption = ngx_sprintf(p_caption, " Location "); + if (cscf->server_name.len) { + p_name = ngx_sprintf(p_name, "%V", &cscf->server_name); + } else { + p_name = ngx_sprintf(p_name, "default"); + } - if (cf->args->nelts == 3) { - p_name = ngx_sprintf(p_name, "%V_%V", &value[1], &value[2]); - p_caption = ngx_sprintf(p_caption, "%V %V", &value[1], &value[2]); - } else { - p_name = ngx_sprintf(p_name, "%V", &value[1]); - p_caption = ngx_sprintf(p_caption, "%V", &value[1]); - } + p_name = ngx_sprintf(p_name, "_location_"); + p_caption = ngx_sprintf(p_caption, "Location "); - if (ngx_status_add_counter(cf->cycle, &ngx_http_module, - clcf->request_counter) != NGX_OK) { - return NGX_CONF_ERROR; + if (cf->args->nelts == 3) { + p_name = ngx_sprintf(p_name, "%V_%V", &value[1], &value[2]); + p_caption = ngx_sprintf(p_caption, "%V %V", &value[1], &value[2]); + } else { + p_name = ngx_sprintf(p_name, "%V", &value[1]); + p_caption = ngx_sprintf(p_caption, "%V", &value[1]); + } + + if (ngx_status_add_child(cf->cycle, cscf->request_counter, + clcf->request_counter) != NGX_OK) { + return NGX_CONF_ERROR; + } } #endif @@ -3378,7 +3376,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) #if (NGX_STATUS) if (prev->request_counter) { - conf->request_counter = prev->request_counter; + conf->request_counter = prev->request_counter; } #endif -- 1.6.2 From e1957b78c7a52ae677d9f51296d350d6e6b101b9 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Tue, 19 May 2009 19:12:16 +0400 Subject: [PATCH 09/11] Add lables for childrens Cc: catap@catap.ru --- src/core/ngx_status.h | 1 + src/http/modules/ngx_http_status_txt_module.c | 25 +++++++++++++++++++++++-- src/http/ngx_http_core_module.c | 2 ++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/core/ngx_status.h b/src/core/ngx_status.h index 4491d83f455b99ee4f091bb25a325b6c6a6d62be..b6da09b2a639594916723cf0b597e769b7dd9ece 100644 --- a/src/core/ngx_status.h +++ b/src/core/ngx_status.h @@ -17,6 +17,7 @@ typedef struct ngx_status_list_s ngx_status_list_t; typedef struct { ngx_str_t name; ngx_str_t caption; + ngx_str_t label_for_childs; ngx_atomic_t *accumulate; ngx_atomic_t *windows; ngx_status_list_t *childs; diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index 972aba4a63521cb210c9ac3023e59d0d254926f2..bf32423a9c96cbd54400ad888c095d1c984e1cb1 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -86,7 +86,16 @@ ngx_http_status_calcualte_len(ngx_status_list_t *c, + NGX_INT_T_LEN + NGX_INT_T_LEN); } - size += ngx_http_status_calcualte_len(c->counter->childs, periods, level + 1); + if (c->counter->childs) { + if (c->counter->label_for_childs.len) { + size += (level + 1) * (sizeof(" ") - 1) + sizeof(":\n") - 1 + + c->counter->label_for_childs.len; + size += ngx_http_status_calcualte_len(c->counter->childs, + periods, level + 2); + } + size += ngx_http_status_calcualte_len(c->counter->childs, periods, + level + 1); + } c = c->next; } @@ -124,7 +133,19 @@ ngx_http_status_write_counter(u_char *p, ngx_status_list_t *c, *(p++) = '\n'; - p = ngx_http_status_write_counter(p, c->counter->childs, periods, level + 1); + if (c->counter->childs) { + if (c->counter->label_for_childs.len) { + for (i = level + 1; i; i--) { + *(p++) = ' '; + } + p = ngx_sprintf(p, "%V:\n", &c->counter->label_for_childs); + p = ngx_http_status_write_counter(p, c->counter->childs, + periods, level + 2); + } else { + p = ngx_http_status_write_counter(p, c->counter->childs, + periods, level + 1); + } + } c = c->next; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 237fb7dc4f77ca2505016434a7c9d69c973aa55f..31bbe90ae227595406b3a77e1b2620031af918e4 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2409,6 +2409,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) *cf = pcf; #if (NGX_STATUS) + cscf->request_counter->label_for_childs.len = sizeof("locations info") - 1; + cscf->request_counter->label_for_childs.data = (u_char *)"locations info"; cscf->request_counter->name.len = sizeof("request_host_") - 1; cscf->request_counter->caption.len = sizeof("Request for host ") - 1; -- 1.6.2 From 3d4603541e325ba22b8fae15707b7e90bb50970e Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Tue, 19 May 2009 20:46:05 +0400 Subject: [PATCH 10/11] Split information about periods for a differnet block Cc: catap@catap.ru --- src/http/modules/ngx_http_status_txt_module.c | 144 ++++++++++++++----------- 1 files changed, 82 insertions(+), 62 deletions(-) diff --git a/src/http/modules/ngx_http_status_txt_module.c b/src/http/modules/ngx_http_status_txt_module.c index bf32423a9c96cbd54400ad888c095d1c984e1cb1..2752c30cfe523f23e02942de7d998c37ba32396e 100644 --- a/src/http/modules/ngx_http_status_txt_module.c +++ b/src/http/modules/ngx_http_status_txt_module.c @@ -11,6 +11,11 @@ typedef struct { + ngx_int_t num; + ngx_str_t value; +} ngx_http_status_txt_period_t; + +typedef struct { ngx_array_t *periods; } ngx_http_status_txt_loc_conf_t; @@ -71,31 +76,33 @@ static ngx_str_t last_configure_human_time; static ngx_int_t ngx_http_status_calcualte_len(ngx_status_list_t *c, - ngx_array_t *periods, ngx_uint_t level) + ngx_http_status_txt_period_t *period, ngx_uint_t level) { ngx_uint_t size = 0; while (c) { size += level * (sizeof(" ") - 1); - size += sizeof(": \n") - 1 + c->counter->caption.len - + NGX_INT_T_LEN; - - if (periods) { - size += sizeof("()") - 1 + NGX_INT_T_LEN; - size += periods->nelts * (sizeof(", ()") - 1 - + NGX_INT_T_LEN + NGX_INT_T_LEN); + size += sizeof(": ()\n") - 1 + c->counter->caption.len + + NGX_INT_T_LEN + NGX_INT_T_LEN; + + if (!level) { + if (period->num) { + size += sizeof(", for last seconds") - 1 + period->value.len; + } else { + size += sizeof(", momentary") - 1; + } } - if (c->counter->childs) { - if (c->counter->label_for_childs.len) { - size += (level + 1) * (sizeof(" ") - 1) + sizeof(":\n") - 1 - + c->counter->label_for_childs.len; - size += ngx_http_status_calcualte_len(c->counter->childs, - periods, level + 2); - } - size += ngx_http_status_calcualte_len(c->counter->childs, periods, - level + 1); - } + if (c->counter->childs) { + if (c->counter->label_for_childs.len) { + size += (level + 1) * (sizeof(" ") - 1) + sizeof(":\n") - 1 + + c->counter->label_for_childs.len; + size += ngx_http_status_calcualte_len(c->counter->childs, + period, level + 2); + } + size += ngx_http_status_calcualte_len(c->counter->childs, period, + level + 1); + } c = c->next; } @@ -106,46 +113,55 @@ ngx_http_status_calcualte_len(ngx_status_list_t *c, static u_char* ngx_http_status_write_counter(u_char *p, ngx_status_list_t *c, - ngx_array_t *periods, ngx_uint_t level) + ngx_http_status_txt_period_t *period, ngx_uint_t level) { ngx_int_t periodic_value; - ngx_uint_t i, j, period; + ngx_uint_t i; while (c) { for (i = level; i; i--) { *(p++) = ' '; } - p = ngx_sprintf(p, "%V: %uA", &c->counter->caption, - ngx_status_get_accumulate_value(c->counter)); - - if (periods) { - periodic_value = ngx_status_get_periodic_value(c->counter, 1); - p = ngx_sprintf(p, "(%uA)", periodic_value); - for (j = 0; j < periods->nelts; j++) { - period = ((ngx_int_t *)periods->elts)[j]; - periodic_value = - ngx_status_get_periodic_value(c->counter, period); - p = ngx_sprintf(p, ", %uA(%uA)", periodic_value, - periodic_value / period); + p = ngx_sprintf(p, "%V", &c->counter->caption); + + if (!level) { + if (period->num) { + p = ngx_sprintf(p, ", for last %V seconds", &period->value); + } else { + p = ngx_sprintf(p, ", momentary", &period->value); } } + periodic_value = ngx_status_get_periodic_value(c->counter, + period->num ? period->num : 1); + + if (period->num) { + p = ngx_sprintf(p, ": %uA(%uA)", + ngx_status_get_periodic_value(c->counter, + period->num), + periodic_value/period->num); + } else { + p = ngx_sprintf(p, ": %uA(%uA)", + ngx_status_get_accumulate_value(c->counter), + periodic_value); + } + *(p++) = '\n'; - if (c->counter->childs) { - if (c->counter->label_for_childs.len) { - for (i = level + 1; i; i--) { - *(p++) = ' '; - } - p = ngx_sprintf(p, "%V:\n", &c->counter->label_for_childs); - p = ngx_http_status_write_counter(p, c->counter->childs, - periods, level + 2); - } else { - p = ngx_http_status_write_counter(p, c->counter->childs, - periods, level + 1); - } - } + if (c->counter->childs) { + if (c->counter->label_for_childs.len) { + for (i = level + 1; i; i--) { + *(p++) = ' '; + } + p = ngx_sprintf(p, "%V:\n", &c->counter->label_for_childs); + p = ngx_http_status_write_counter(p, c->counter->childs, + period, level + 2); + } else { + p = ngx_http_status_write_counter(p, c->counter->childs, + period, level + 1); + } + } c = c->next; } @@ -159,7 +175,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) size_t size; ngx_int_t rc; ngx_buf_t *b; - ngx_uint_t i; + ngx_uint_t i, j; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr; @@ -170,6 +186,7 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) ngx_uint_t uptime, uptime_days, uptime_hours, uptime_minutes, uptime_seconds; + ngx_http_status_txt_period_t *period; ngx_http_status_txt_loc_conf_t *conf; if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { @@ -234,9 +251,13 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) continue; } - size += sizeof("\n") - 1; + for (j = 0; j < conf->periods->nelts; j++) { + period = conf->periods->elts; + + size += sizeof("\n") - 1; - size += ngx_http_status_calcualte_len(c, conf->periods, 0); + size += ngx_http_status_calcualte_len(c, &period[j], 0); + } } @@ -284,9 +305,13 @@ static ngx_int_t ngx_http_status_txt_handler(ngx_http_request_t *r) continue; } - b->last = ngx_sprintf(b->last, "\n"); + for (j = 0; j < conf->periods->nelts; j++) { + period = conf->periods->elts; - b->last = ngx_http_status_write_counter(b->last, c, conf->periods, 0); + b->last = ngx_sprintf(b->last, "\n"); + + b->last = ngx_http_status_write_counter(b->last, c, &period[j], 0); + } } r->headers_out.status = NGX_HTTP_OK; @@ -341,19 +366,17 @@ static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u_char *p = conf; ngx_tm_t tm; ngx_str_t *value; - ngx_uint_t *period, i; + ngx_uint_t i; ngx_array_t **periods; ngx_http_core_loc_conf_t *clcf; + ngx_http_status_txt_period_t *period; + periods = (ngx_array_t **) (p + cmd->offset); value = cf->args->elts; - if (ngx_strcasecmp(value[1].data, (u_char *) "off") == 0) { - return NGX_CONF_OK; - } - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_status_txt_handler; @@ -376,21 +399,18 @@ static char *ngx_http_status_txt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_abs(ngx_cached_time->gmtoff / 60), ngx_abs(ngx_cached_time->gmtoff % 60)); - if (ngx_strcasecmp(value[1].data, (u_char *) "on") == 0) { - return NGX_CONF_OK; - } - *periods = ngx_array_create(cf->pool, cf->args->nelts - 1, - sizeof(ngx_uint_t)); + sizeof(ngx_http_status_txt_period_t)); if (*periods == NULL) { return NGX_CONF_ERROR; } for (i = 1; i < cf->args->nelts; i++) { period = ngx_array_push(*periods); - *period = ngx_atoi(value[i].data, value[i].len); + period->value = value[i]; + period->num = ngx_atoi(period->value.data, period->value.len); - if ((ngx_int_t)*period == NGX_ERROR) { + if (period->num == NGX_ERROR) { return NGX_CONF_ERROR; } } -- 1.6.2 From a03223251c8c325826cbbc046ba6905e65dc0029 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Sat, 23 May 2009 19:48:40 +0400 Subject: [PATCH 11/11] Implement by codes information in status Cc: catap@catap.ru Add directive status_capture for capture a status information in header filter. This counter has add +1 only last of execute handler for this request --- src/http/ngx_http.c | 137 +++++++++++++++++++++++++ src/http/ngx_http.h | 5 +- src/http/ngx_http_core_module.c | 79 ++++++++++++++- src/http/ngx_http_core_module.h | 1 + src/http/ngx_http_header_filter_module.c | 162 ++++++------------------------ 5 files changed, 249 insertions(+), 135 deletions(-) diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index a9b4ee5c53abd5aa30c122fd2519e7cd4427643c..c32b43c3401bfba0045ca2cfda944234784b2b86 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -79,6 +79,85 @@ ngx_str_t ngx_http_html_default_types[] = { ngx_null_string }; +static ngx_str_t ngx_http_status[] = { + + ngx_string("200 OK"), + ngx_string("201 Created"), + ngx_null_string, /* "202 Accepted" */ + ngx_null_string, /* "203 Non-Authoritative Information" */ + ngx_string("204 No Content"), + ngx_null_string, /* "205 Reset Content" */ + ngx_string("206 Partial Content"), + + /* ngx_null_string, */ /* "207 Multi-Status" */ + +#define NGX_HTTP_LAST_LEVEL_200 207 +#define NGX_HTTP_LEVEL_200 (NGX_HTTP_LAST_LEVEL_200 - 200) + + /* { ngx_null_string, */ /* "300 Multiple Choices" */ + + ngx_string("301 Moved Permanently"), + ngx_string("302 Moved Temporarily"), + ngx_null_string, /* "303 See Other" */ + ngx_string("304 Not Modified"), + + /* ngx_null_string, */ /* "305 Use Proxy" */ + /* ngx_null_string, */ /* "306 unused" */ + /* ngx_null_string, */ /* "307 Temporary Redirect" */ + +#define NGX_HTTP_LAST_LEVEL_300 305 +#define NGX_HTTP_LEVEL_300 (NGX_HTTP_LAST_LEVEL_300 - 301) + + ngx_string("400 Bad Request"), + ngx_string("401 Unauthorized"), + ngx_string("402 Payment Required"), + ngx_string("403 Forbidden"), + ngx_string("404 Not Found"), + ngx_string("405 Not Allowed"), + ngx_string("406 Not Acceptable"), + ngx_null_string, /* "407 Proxy Authentication Required" */ + ngx_string("408 Request Time-out"), + ngx_string("409 Conflict"), + ngx_string("410 Gone"), + ngx_string("411 Length Required"), + ngx_string("412 Precondition Failed"), + ngx_string("413 Request Entity Too Large"), + ngx_null_string, /* "414 Request-URI Too Large", but we never send it + * because we treat such requests as the HTTP/0.9 + * requests and send only a body without a header + */ + ngx_string("415 Unsupported Media Type"), + ngx_string("416 Requested Range Not Satisfiable"), + + /* ngx_null_string, */ /* "417 Expectation Failed" */ + /* ngx_null_string, */ /* "418 unused" */ + /* ngx_null_string, */ /* "419 unused" */ + /* ngx_null_string, */ /* "420 unused" */ + /* ngx_null_string, */ /* "421 unused" */ + /* ngx_null_string, */ /* "422 Unprocessable Entity" */ + /* ngx_null_string, */ /* "423 Locked" */ + /* ngx_null_string, */ /* "424 Failed Dependency" */ + +#define NGX_HTTP_LAST_LEVEL_400 417 +#define NGX_HTTP_LEVEL_400 (NGX_HTTP_LAST_LEVEL_400 - 400) + + ngx_string("500 Internal Server Error"), + ngx_string("501 Method Not Implemented"), + ngx_string("502 Bad Gateway"), + ngx_string("503 Service Temporarily Unavailable"), + ngx_string("504 Gateway Time-out"), + + ngx_null_string, /* "505 HTTP Version Not Supported" */ + ngx_null_string, /* "506 Variant Also Negotiates" */ + ngx_string("507 Insufficient Storage"), + /* ngx_null_string, */ /* "508 unused" */ + /* ngx_null_string, */ /* "509 unused" */ + /* ngx_null_string, */ /* "510 Not Extended" */ + +#define NGX_HTTP_LAST_LEVEL_500 508 + +}; + static ngx_command_t ngx_http_commands[] = { @@ -116,6 +195,64 @@ ngx_module_t ngx_http_module = { }; +ngx_inline ngx_int_t +ngx_http_get_status_position(ngx_uint_t status) +{ + if (status >= NGX_HTTP_OK + && status < NGX_HTTP_LAST_LEVEL_200) { + /* 2XX */ + + status -= NGX_HTTP_OK; + + } else if (status >= NGX_HTTP_MOVED_PERMANENTLY + && status < NGX_HTTP_LAST_LEVEL_300) { + /* 3XX */ + + status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200; + + } else if (status >= NGX_HTTP_BAD_REQUEST + && status < NGX_HTTP_LAST_LEVEL_400) { + /* 4XX */ + status = status - NGX_HTTP_BAD_REQUEST + + NGX_HTTP_LEVEL_200 + + NGX_HTTP_LEVEL_300; + + } else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR + && status < NGX_HTTP_LAST_LEVEL_500) { + /* 5XX */ + status = status - NGX_HTTP_INTERNAL_SERVER_ERROR + + NGX_HTTP_LEVEL_200 + + NGX_HTTP_LEVEL_300 + + NGX_HTTP_LEVEL_400; + + } else { + return NGX_ERROR; + } + + return status; +} + + +ngx_inline ngx_str_t* +ngx_http_get_status(ngx_uint_t status) +{ + status = (ngx_uint_t)ngx_http_get_status_position(status); + + if ((ngx_int_t)status == NGX_ERROR) { + return NULL; + } + + return &ngx_http_status[status]; +} + + +ngx_inline ngx_int_t +ngx_http_status_len() +{ + return sizeof(ngx_http_status); +} + + static char * ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h index 9444b11319385e2d463313af4385f4ed2107685c..cb868a696ae4d69a8c4786b4bf6d86703ab357eb 100644 --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -50,6 +50,10 @@ struct ngx_http_log_ctx_s { ngx_http_request_t *current_request; }; +ngx_inline ngx_int_t ngx_http_get_status_position(ngx_uint_t status); +ngx_inline ngx_int_t ngx_http_status_len(); + +ngx_inline ngx_str_t* ngx_http_get_status(ngx_uint_t status); #define ngx_http_get_module_ctx(r, module) (r)->ctx[module.ctx_index] #define ngx_http_set_ctx(r, c, module) r->ctx[module.ctx_index] = c; @@ -130,7 +134,6 @@ extern ngx_module_t ngx_http_module; extern ngx_str_t ngx_http_html_default_types[]; - extern ngx_http_output_header_filter_pt ngx_http_top_header_filter; extern ngx_http_output_body_filter_pt ngx_http_top_body_filter; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 31bbe90ae227595406b3a77e1b2620031af918e4..f7d113d8ad0548d9e9e1b50080708139770b6106 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -73,6 +73,10 @@ static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); #endif +#if (NGX_STATUS) +static char *ngx_http_status_capture(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +#endif static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data); @@ -656,7 +660,18 @@ static ngx_command_t ngx_http_core_commands[] = { #endif - ngx_null_command +#if (NGX_STATUS) + + { ngx_string("status_capture"), + NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_status_capture, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + +#endif + + ngx_null_command }; @@ -2657,6 +2672,8 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) clcf->request_counter->name.len = sizeof("request_host__location_") - 1 + value[1].len; clcf->request_counter->caption.len = sizeof("Location ") - 1 + value[1].len; + clcf->request_counter->label_for_childs.len = sizeof("codes list") - 1; + clcf->request_counter->label_for_childs.data = (u_char *)"codes list"; if (cscf->server_name.len) { clcf->request_counter->name.len += cscf->server_name.len; @@ -4434,6 +4451,66 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) #endif +#if (NGX_STATUS) + +static char * +ngx_http_status_capture(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_int_t n, p; + ngx_str_t *value; + ngx_uint_t i; + ngx_str_t *status_line; + ngx_status_counter_t *counter; + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + value = cf->args->elts; + + clcf->status_counters = ngx_pcalloc(cf->pool, + sizeof(ngx_status_counter_t *) * ngx_http_status_len()); + + if (clcf->status_counters == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 1; i < cf->args->nelts; i++) { + + n = ngx_atoi(value[i].data, value[i].len); + if (n == NGX_ERROR) { + return NGX_CONF_ERROR; + } + + status_line = ngx_http_get_status(n); + + if (status_line == NULL) { + continue; + } + + p = ngx_http_get_status_position(n); + + counter = ngx_pcalloc(cf->pool, sizeof(ngx_status_counter_t)); + if (counter == NULL) { + return NGX_CONF_ERROR; + } + + counter->name = value[i]; + counter->caption = *status_line; + + if (ngx_status_add_child(cf->cycle, clcf->request_counter, + counter) != NGX_OK) { + return NGX_CONF_ERROR; + } + + clcf->status_counters[p] = counter; + } + + return NGX_CONF_OK; +} + +#endif + + static char * ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data) { diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index cfe2e642cea1a22062f5740a09ecfd14b2b23886..dab4f0d8d8e81f04a0fe1d37753b6c6f985e0203 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -390,6 +390,7 @@ struct ngx_http_core_loc_conf_s { #if (NGX_STATUS) ngx_status_counter_t *request_counter; + ngx_status_counter_t **status_counters; #endif #if 0 diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 332fceb8a0437ec3b3a07e9e58d93a713e14dc2b..f5024a2316cceebdf16bde87b4a7727a51627995 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -49,86 +49,6 @@ static char ngx_http_server_string[] = "Server: nginx" CRLF; static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; -static ngx_str_t ngx_http_status_lines[] = { - - ngx_string("200 OK"), - ngx_string("201 Created"), - ngx_null_string, /* "202 Accepted" */ - ngx_null_string, /* "203 Non-Authoritative Information" */ - ngx_string("204 No Content"), - ngx_null_string, /* "205 Reset Content" */ - ngx_string("206 Partial Content"), - - /* ngx_null_string, */ /* "207 Multi-Status" */ - -#define NGX_HTTP_LAST_LEVEL_200 207 -#define NGX_HTTP_LEVEL_200 (NGX_HTTP_LAST_LEVEL_200 - 200) - - /* ngx_null_string, */ /* "300 Multiple Choices" */ - - ngx_string("301 Moved Permanently"), - ngx_string("302 Moved Temporarily"), - ngx_null_string, /* "303 See Other" */ - ngx_string("304 Not Modified"), - - /* ngx_null_string, */ /* "305 Use Proxy" */ - /* ngx_null_string, */ /* "306 unused" */ - /* ngx_null_string, */ /* "307 Temporary Redirect" */ - -#define NGX_HTTP_LAST_LEVEL_300 305 -#define NGX_HTTP_LEVEL_300 (NGX_HTTP_LAST_LEVEL_300 - 301) - - ngx_string("400 Bad Request"), - ngx_string("401 Unauthorized"), - ngx_string("402 Payment Required"), - ngx_string("403 Forbidden"), - ngx_string("404 Not Found"), - ngx_string("405 Not Allowed"), - ngx_string("406 Not Acceptable"), - ngx_null_string, /* "407 Proxy Authentication Required" */ - ngx_string("408 Request Time-out"), - ngx_string("409 Conflict"), - ngx_string("410 Gone"), - ngx_string("411 Length Required"), - ngx_string("412 Precondition Failed"), - ngx_string("413 Request Entity Too Large"), - ngx_null_string, /* "414 Request-URI Too Large", but we never send it - * because we treat such requests as the HTTP/0.9 - * requests and send only a body without a header - */ - ngx_string("415 Unsupported Media Type"), - ngx_string("416 Requested Range Not Satisfiable"), - - /* ngx_null_string, */ /* "417 Expectation Failed" */ - /* ngx_null_string, */ /* "418 unused" */ - /* ngx_null_string, */ /* "419 unused" */ - /* ngx_null_string, */ /* "420 unused" */ - /* ngx_null_string, */ /* "421 unused" */ - /* ngx_null_string, */ /* "422 Unprocessable Entity" */ - /* ngx_null_string, */ /* "423 Locked" */ - /* ngx_null_string, */ /* "424 Failed Dependency" */ - -#define NGX_HTTP_LAST_LEVEL_400 417 -#define NGX_HTTP_LEVEL_400 (NGX_HTTP_LAST_LEVEL_400 - 400) - - ngx_string("500 Internal Server Error"), - ngx_string("501 Method Not Implemented"), - ngx_string("502 Bad Gateway"), - ngx_string("503 Service Temporarily Unavailable"), - ngx_string("504 Gateway Time-out"), - - ngx_null_string, /* "505 HTTP Version Not Supported" */ - ngx_null_string, /* "506 Variant Also Negotiates" */ - ngx_string("507 Insufficient Storage"), - /* ngx_null_string, */ /* "508 unused" */ - /* ngx_null_string, */ /* "509 unused" */ - /* ngx_null_string, */ /* "510 Not Extended" */ - -#define NGX_HTTP_LAST_LEVEL_500 508 - -}; - - ngx_http_header_out_t ngx_http_headers_out[] = { { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) }, { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) }, @@ -161,7 +81,7 @@ ngx_http_header_filter(ngx_http_request_t *r) size_t len; ngx_str_t host, *status_line; ngx_buf_t *b; - ngx_uint_t status, i, port; + ngx_uint_t i, port; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; @@ -172,6 +92,11 @@ ngx_http_header_filter(ngx_http_request_t *r) struct sockaddr_in6 *sin6; #endif u_char addr[NGX_SOCKADDR_STRLEN]; +#if (NGX_STATUS) + ngx_int_t status_position; + ngx_status_counter_t *counter; +#endif + r->header_sent = 1; @@ -203,23 +128,17 @@ ngx_http_header_filter(ngx_http_request_t *r) /* status line */ + status_line = ngx_http_get_status(r->headers_out.status); + if (r->headers_out.status_line.len) { - len += r->headers_out.status_line.len; status_line = &r->headers_out.status_line; -#if (NGX_SUPPRESS_WARN) - status = 0; -#endif } else { - status = r->headers_out.status; - - if (status >= NGX_HTTP_OK - && status < NGX_HTTP_LAST_LEVEL_200) - { - /* 2XX */ + if (status_line) { - if (status == NGX_HTTP_NO_CONTENT) { + switch (r->headers_out.status) { + case NGX_HTTP_NO_CONTENT: r->header_only = 1; r->headers_out.content_type.len = 0; r->headers_out.content_type.data = NULL; @@ -227,47 +146,11 @@ ngx_http_header_filter(ngx_http_request_t *r) r->headers_out.last_modified = NULL; r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; - } - - status -= NGX_HTTP_OK; - status_line = &ngx_http_status_lines[status]; - len += ngx_http_status_lines[status].len; - - } else if (status >= NGX_HTTP_MOVED_PERMANENTLY - && status < NGX_HTTP_LAST_LEVEL_300) - { - /* 3XX */ - - if (status == NGX_HTTP_NOT_MODIFIED) { + break; + case NGX_HTTP_NOT_MODIFIED: r->header_only = 1; - } - - status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200; - status_line = &ngx_http_status_lines[status]; - len += ngx_http_status_lines[status].len; - - } else if (status >= NGX_HTTP_BAD_REQUEST - && status < NGX_HTTP_LAST_LEVEL_400) - { - /* 4XX */ - status = status - NGX_HTTP_BAD_REQUEST - + NGX_HTTP_LEVEL_200 - + NGX_HTTP_LEVEL_300; - - status_line = &ngx_http_status_lines[status]; - len += ngx_http_status_lines[status].len; - - } else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR - && status < NGX_HTTP_LAST_LEVEL_500) - { - /* 5XX */ - status = status - NGX_HTTP_INTERNAL_SERVER_ERROR - + NGX_HTTP_LEVEL_200 - + NGX_HTTP_LEVEL_300 - + NGX_HTTP_LEVEL_400; - - status_line = &ngx_http_status_lines[status]; - len += ngx_http_status_lines[status].len; + break; + } } else { len += NGX_INT_T_LEN; @@ -275,8 +158,21 @@ ngx_http_header_filter(ngx_http_request_t *r) } } + len += status_line->len; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); +#if (NGX_STATUS) + if (status_line && clcf->status_counters) { + status_position = ngx_http_get_status_position(r->headers_out.status); + counter = clcf->status_counters[status_position]; + + if (counter) { + ngx_status_fetch_add(counter); + } + } +#endif + if (r->headers_out.server == NULL) { len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1: sizeof(ngx_http_server_string) - 1; @@ -437,7 +333,7 @@ ngx_http_header_filter(ngx_http_request_t *r) b->last = ngx_copy(b->last, status_line->data, status_line->len); } else { - b->last = ngx_sprintf(b->last, "%ui", status); + b->last = ngx_sprintf(b->last, "%ui", r->headers_out.status); } *b->last++ = CR; *b->last++ = LF; -- 1.6.2