From 95bd0c5a76f7c2ed16a2364c483b3944651fc292 Mon Sep 17 00:00:00 2001 From: Eric Sabelhaus Date: Thu, 21 May 2015 14:03:22 -0400 Subject: [PATCH 1/4] working with LOTS of debug statements --- ngx_http_statsd.c | 1156 ++++++++++++++++++++++++--------------------- 1 file changed, 606 insertions(+), 550 deletions(-) diff --git a/ngx_http_statsd.c b/ngx_http_statsd.c index 7133e4b..f01aeef 100644 --- a/ngx_http_statsd.c +++ b/ngx_http_statsd.c @@ -13,17 +13,18 @@ #include #include -#define STATSD_DEFAULT_PORT 8125 +#define STATSD_DEFAULT_PORT 8125 -#define STATSD_TYPE_COUNTER 0x0001 +#define STATSD_TYPE_COUNTER 0x0001 #define STATSD_TYPE_TIMING 0x0002 +#define STATSD_TYPE_SET 0x0003 #define STATSD_MAX_STR 256 -#define ngx_conf_merge_ptr_value(conf, prev, default) \ - if (conf == NGX_CONF_UNSET_PTR) { \ - conf = (prev == NGX_CONF_UNSET_PTR) ? default : prev; \ - } +#define ngx_conf_merge_ptr_value(conf, prev, default) \ + if (conf == NGX_CONF_UNSET_PTR) { \ + conf = (prev == NGX_CONF_UNSET_PTR) ? default : prev; \ + } #if defined nginx_version && nginx_version >= 8021 typedef ngx_addr_t ngx_statsd_addr_t; @@ -32,32 +33,34 @@ typedef ngx_peer_addr_t ngx_statsd_addr_t; #endif typedef struct { - ngx_statsd_addr_t peer_addr; - ngx_udp_connection_t *udp_connection; - ngx_log_t *log; + ngx_statsd_addr_t peer_addr; + ngx_udp_connection_t *udp_connection; + ngx_log_t *log; } ngx_udp_endpoint_t; typedef struct { - ngx_array_t *endpoints; + ngx_array_t *endpoints; } ngx_http_statsd_main_conf_t; typedef struct { - ngx_uint_t type; + ngx_uint_t type; - ngx_str_t key; - ngx_uint_t metric; - ngx_flag_t valid; + ngx_str_t key; + ngx_uint_t metric; + ngx_str_t metric_str; + ngx_flag_t valid; - ngx_http_complex_value_t *ckey; - ngx_http_complex_value_t *cmetric; - ngx_http_complex_value_t *cvalid; + ngx_http_complex_value_t *ckey; + ngx_http_complex_value_t *cmetric; + ngx_http_complex_value_t *cmetric_str; + ngx_http_complex_value_t *cvalid; } ngx_statsd_stat_t; typedef struct { - int off; - ngx_udp_endpoint_t *endpoint; - ngx_uint_t sample_rate; - ngx_array_t *stats; + int off; + ngx_udp_endpoint_t *endpoint; + ngx_uint_t sample_rate; + ngx_array_t *stats; } ngx_http_statsd_conf_t; ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc); @@ -67,16 +70,18 @@ static ngx_int_t ngx_http_statsd_udp_send(ngx_udp_endpoint_t *l, u_char *buf, si static void *ngx_http_statsd_create_main_conf(ngx_conf_t *cf); static void *ngx_http_statsd_create_loc_conf(ngx_conf_t *cf); -static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, - void *child); +static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static char *ngx_http_statsd_set_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_statsd_add_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_uint_t type); static char *ngx_http_statsd_add_count(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_statsd_add_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_statsd_add_timing(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_str_t ngx_http_statsd_key_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v); static ngx_str_t ngx_http_statsd_key_value(ngx_str_t *str); +static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v); +static ngx_str_t ngx_http_statsd_set_value(ngx_str_t *str); static ngx_uint_t ngx_http_statsd_metric_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_uint_t v); static ngx_uint_t ngx_http_statsd_metric_value(ngx_str_t *str); static ngx_flag_t ngx_http_statsd_valid_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_flag_t v); @@ -86,41 +91,52 @@ uintptr_t ngx_escape_statsd_key(u_char *dst, u_char *src, size_t size); static ngx_int_t ngx_http_statsd_init(ngx_conf_t *cf); -static ngx_command_t ngx_http_statsd_commands[] = { - - { ngx_string("statsd_server"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_statsd_set_server, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("statsd_sample_rate"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_statsd_conf_t, sample_rate), - NULL }, - - { ngx_string("statsd_count"), - NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23, - ngx_http_statsd_add_count, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - { ngx_string("statsd_timing"), - NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23, - ngx_http_statsd_add_timing, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL }, - - ngx_null_command +static ngx_command_t ngx_http_statsd_commands[] = { + { + ngx_string("statsd_server"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_statsd_set_server, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL + }, + { + ngx_string("statsd_sample_rate"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_statsd_conf_t, sample_rate), + NULL + }, + { + ngx_string("statsd_count"), + NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23, + ngx_http_statsd_add_count, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL + }, + { + ngx_string("statsd_set"), + NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23, + ngx_http_statsd_add_set, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL + }, + { + ngx_string("statsd_timing"), + NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE23, + ngx_http_statsd_add_timing, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL + }, + ngx_null_command }; -static ngx_http_module_t ngx_http_statsd_module_ctx = { +static ngx_http_module_t ngx_http_statsd_module_ctx = { NULL, /* preconfiguration */ ngx_http_statsd_init, /* postconfiguration */ @@ -135,7 +151,7 @@ static ngx_http_module_t ngx_http_statsd_module_ctx = { }; -ngx_module_t ngx_http_statsd_module = { +ngx_module_t ngx_http_statsd_module = { NGX_MODULE_V1, &ngx_http_statsd_module_ctx, /* module context */ ngx_http_statsd_commands, /* module directives */ @@ -150,601 +166,641 @@ ngx_module_t ngx_http_statsd_module = { NGX_MODULE_V1_PADDING }; -static ngx_str_t -ngx_http_statsd_key_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) -{ - ngx_str_t val; - if (cv == NULL) { - return v; - } +static ngx_str_t ngx_http_statsd_key_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) { + fprintf(stderr, "ngx_http_statsd_key_get_value\n"); + ngx_str_t val; + if (cv == NULL) { + return v; + } - if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { - return (ngx_str_t) ngx_null_string; - }; + if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { + return (ngx_str_t) ngx_null_string; + }; - return ngx_http_statsd_key_value(&val); + return ngx_http_statsd_key_value(&val); }; -static ngx_str_t -ngx_http_statsd_key_value(ngx_str_t *value) -{ - return *value; +static ngx_str_t ngx_http_statsd_key_value(ngx_str_t *value) { + fprintf(stderr, "ngx_http_statsd_key_value\n"); + return *value; }; -static ngx_uint_t -ngx_http_statsd_metric_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_uint_t v) -{ - ngx_str_t val; - if (cv == NULL) { - return v; - } +static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) { + fprintf(stderr, "ngx_http_statsd_set_get_value\n"); + ngx_str_t val; + if (cv == NULL) { + return v; + } - if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { - return 0; - }; + if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { + return (ngx_str_t) ngx_null_string; + }; - return ngx_http_statsd_metric_value(&val); + return ngx_http_statsd_key_value(&val); }; -static ngx_uint_t -ngx_http_statsd_metric_value(ngx_str_t *value) -{ - ngx_int_t n, m; - - if (value->len == 1 && value->data[0] == '-') { - return (ngx_uint_t) -1; - }; - - /* Hack to convert milliseconds to a number. */ - if (value->len > 4 && value->data[value->len - 4] == '.') { - n = ngx_atoi(value->data, value->len - 4); - m = ngx_atoi(value->data + (value->len - 3), 3); - return (ngx_uint_t) ((n * 1000) + m); - - } else { - n = ngx_atoi(value->data, value->len); - if (n > 0) { - return (ngx_uint_t) n; - }; - }; - - return 0; + +static ngx_str_t ngx_http_statsd_set_value(ngx_str_t *value) { + fprintf(stderr, "ngx_http_statsd_set_value\n"); + return *value; }; -static ngx_flag_t -ngx_http_statsd_valid_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_flag_t v) -{ - ngx_str_t val; - if (cv == NULL) { - return v; - } +static ngx_uint_t ngx_http_statsd_metric_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_uint_t v) { + fprintf(stderr, "ngx_http_statsd_metric_get_value\n"); + ngx_str_t val; + if (cv == NULL) { + return v; + } - if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { - return 0; - }; + if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { + return 0; + }; - return ngx_http_statsd_valid_value(&val); + return ngx_http_statsd_metric_value(&val); }; -static ngx_flag_t -ngx_http_statsd_valid_value(ngx_str_t *value) -{ - return (ngx_flag_t) (value->len > 0 ? 1 : 0); -}; +static ngx_uint_t ngx_http_statsd_metric_value(ngx_str_t *value) { + fprintf(stderr, "ngx_http_statsd_metric_value\n"); + ngx_int_t n, m; -ngx_int_t -ngx_http_statsd_handler(ngx_http_request_t *r) -{ - u_char line[STATSD_MAX_STR], *p; - const char * metric_type; - ngx_http_statsd_conf_t *ulcf; - ngx_statsd_stat_t *stats; - ngx_statsd_stat_t stat; - ngx_uint_t c; - ngx_uint_t n; - ngx_str_t s; - ngx_flag_t b; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http statsd handler"); - - ulcf = ngx_http_get_module_loc_conf(r, ngx_http_statsd_module); - - if (ulcf->off == 1 || ulcf->endpoint == NULL) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: handler off"); - return NGX_OK; - } + if (value->len == 1 && value->data[0] == '-') { + return (ngx_uint_t) -1; + }; - // Use a random distribution to sample at sample rate. - if (ulcf->sample_rate < 100 && (uint) (ngx_random() % 100) >= ulcf->sample_rate) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: skipping sample"); - return NGX_OK; - } - - stats = ulcf->stats->elts; - for (c = 0; c < ulcf->stats->nelts; c++) { - - stat = stats[c]; - s = ngx_http_statsd_key_get_value(r, stat.ckey, stat.key); - ngx_escape_statsd_key(s.data, s.data, s.len); - - n = ngx_http_statsd_metric_get_value(r, stat.cmetric, stat.metric); - b = ngx_http_statsd_valid_get_value(r, stat.cvalid, stat.valid); - - if (b == 0 || s.len == 0 || n <= 0) { - // Do not log if not valid, key is invalid, or valud is lte 0. - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: no value to send"); - continue; - }; - - if (stat.type == STATSD_TYPE_COUNTER) { - metric_type = "c"; - } else if (stat.type == STATSD_TYPE_TIMING) { - metric_type = "ms"; - } else { - metric_type = NULL; - } - - if (metric_type) { - if (ulcf->sample_rate < 100) { - p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s|@0.%02d", &s, n, metric_type, ulcf->sample_rate); - } else { - p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s", &s, n, metric_type); - } - ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); - } - } + /* Hack to convert milliseconds to a number. */ + if (value->len > 4 && value->data[value->len - 4] == '.') { + n = ngx_atoi(value->data, value->len - 4); + m = ngx_atoi(value->data + (value->len - 3), 3); + return (ngx_uint_t) ((n * 1000) + m); - return NGX_OK; -} + } else { + n = ngx_atoi(value->data, value->len); + if (n > 0) { + return (ngx_uint_t) n; + }; + }; -static ngx_int_t ngx_statsd_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *endpoint) { - ngx_pool_cleanup_t *cln; - ngx_udp_connection_t *uc; + return 0; +}; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, - "statsd: initting endpoint"); +static ngx_flag_t ngx_http_statsd_valid_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_flag_t v) { + fprintf(stderr, "ngx_http_statsd_valid_get_value\n"); + ngx_str_t val; + if (cv == NULL) { + return v; + } - cln = ngx_pool_cleanup_add(cf->pool, 0); - if(cln == NULL) { - return NGX_ERROR; - } + if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { + return 0; + }; - cln->handler = ngx_statsd_updater_cleanup; - cln->data = endpoint; + return ngx_http_statsd_valid_value(&val); +}; - uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log); - if (uc == NULL) { - return NGX_ERROR; - } +static ngx_flag_t ngx_http_statsd_valid_value(ngx_str_t *value) { + fprintf(stderr, "ngx_http_statsd_valid_value\n"); + return (ngx_flag_t) (value->len > 0 ? 1 : 0); +}; - endpoint->udp_connection = uc; +ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { + fprintf(stderr, "ngx_http_statsd_handler:start\n"); + u_char line[STATSD_MAX_STR], *p; + const char *metric_type; + ngx_http_statsd_conf_t *ulcf; + ngx_statsd_stat_t *stats; + ngx_statsd_stat_t stat; + ngx_uint_t c; + ngx_uint_t n; + ngx_str_t set; + ngx_str_t s; + ngx_flag_t b; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http statsd handler"); + + ulcf = ngx_http_get_module_loc_conf(r, ngx_http_statsd_module); + + if (ulcf->off == 1 || ulcf->endpoint == NULL) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: handler off"); + return NGX_OK; + } - uc->sockaddr = endpoint->peer_addr.sockaddr; - uc->socklen = endpoint->peer_addr.socklen; - uc->server = endpoint->peer_addr.name; + // Use a random distribution to sample at sample rate. + if (ulcf->sample_rate < 100 && (uint) (ngx_random() % 100) >= ulcf->sample_rate) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: skipping sample"); + return NGX_OK; + } - endpoint->log = &cf->cycle->new_log; + stats = ulcf->stats->elts; - return NGX_OK; -} + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop\n"); + int i = 0; + for (c = 0; c < ulcf->stats->nelts; c++) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:%d\n", i++); -static void -ngx_statsd_updater_cleanup(void *data) -{ - ngx_udp_endpoint_t *e = data; + stat = stats[c]; + s = ngx_http_statsd_key_get_value(r, stat.ckey, stat.key); - ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, - "cleanup statsd_updater"); + ngx_escape_statsd_key(s.data, s.data, s.len); - if(e->udp_connection) { - if(e->udp_connection->connection) { - ngx_close_connection(e->udp_connection->connection); - } + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:before\n"); - ngx_free(e->udp_connection); - } -} + n = ngx_http_statsd_metric_get_value(r, stat.cmetric, stat.metric); -static void ngx_http_statsd_udp_dummy_handler(ngx_event_t *ev) -{ -} + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:middle\n"); -static ngx_int_t -ngx_http_statsd_udp_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len) -{ - ssize_t n; - ngx_udp_connection_t *uc; + b = ngx_http_statsd_valid_get_value(r, stat.cvalid, stat.valid); - uc = l->udp_connection; - if (uc->connection == NULL) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after\n"); - uc->log = *l->log; - uc->log.handler = NULL; - uc->log.data = NULL; - uc->log.action = "logging"; + set = ngx_http_statsd_set_get_value(r, stat.cmetric_str, stat.metric_str); - if(ngx_udp_connect(uc) != NGX_OK) { - if(uc->connection != NULL) { - ngx_free_connection(uc->connection); - uc->connection = NULL; - } + if (b == 0 || s.len == 0 || ( n <= 0 && set.len == 0 )) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:BAIL\n"); + // Do not log if not valid, key is invalid, or valud is lte 0. + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: no value to send"); + continue; + }; - return NGX_ERROR; + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:before_if_statement\n"); + + if (stat.type == STATSD_TYPE_COUNTER) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_counter\n"); + metric_type = "c"; + } else if (stat.type == STATSD_TYPE_TIMING) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_timing\n"); + metric_type = "ms"; + } else if (stat.type == STATSD_TYPE_SET) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_set\n"); + metric_type = "s"; + } else { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_null\n"); + metric_type = NULL; + } + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:start\n"); + + if (metric_type) { + if (stat.type == STATSD_TYPE_SET) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET\n"); + if (ulcf->sample_rate < 100) { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:sample_rate:before\n"); + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%s|s|@0.%02d", &s, set, ulcf->sample_rate); + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:sample_rate:after\n"); + } else { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:non_sample_rate:before\n"); + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|s", &s, set); + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:non_sample_rate:after\n"); } - - uc->connection->data = l; - uc->connection->read->handler = ngx_http_statsd_udp_dummy_handler; - uc->connection->read->resolver = 0; + ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); + } else { + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_OTHER\n"); + if (ulcf->sample_rate < 100) { + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s|@0.%02d", &s, n, metric_type, ulcf->sample_rate); + } else { + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s", &s, n, metric_type); + } + ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); + } } + fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:stop\n"); + } + fprintf(stderr, "ngx_http_statsd_handler:stop:for_loop\n"); - n = ngx_send(uc->connection, buf, len); - if (n == -1) { - return NGX_ERROR; - } + fprintf(stderr, "ngx_http_statsd_handler:stop\n"); - if ((size_t) n != (size_t) len) { -#if defined nginx_version && nginx_version >= 8032 - ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); -#else - ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); -#endif - return NGX_ERROR; - } - - return NGX_OK; + return NGX_OK; } -static void * -ngx_http_statsd_create_main_conf(ngx_conf_t *cf) -{ - ngx_http_statsd_main_conf_t *conf; +static ngx_int_t ngx_statsd_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *endpoint) { + fprintf(stderr, "ngx_statsd_init_endpoint\n"); + ngx_pool_cleanup_t *cln; + ngx_udp_connection_t *uc; - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_main_conf_t)); - if (conf == NULL) { - return NGX_CONF_ERROR; - } + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "statsd: initting endpoint"); - return conf; -} + cln = ngx_pool_cleanup_add(cf->pool, 0); + if(cln == NULL) { + return NGX_ERROR; + } -static void * -ngx_http_statsd_create_loc_conf(ngx_conf_t *cf) -{ - ngx_http_statsd_conf_t *conf; + cln->handler = ngx_statsd_updater_cleanup; + cln->data = endpoint; - conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_conf_t)); - if (conf == NULL) { - return NGX_CONF_ERROR; - } - conf->endpoint = NGX_CONF_UNSET_PTR; - conf->off = NGX_CONF_UNSET; - conf->sample_rate = NGX_CONF_UNSET_UINT; - conf->stats = NULL; + uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log); + if (uc == NULL) { + return NGX_ERROR; + } - return conf; -} + endpoint->udp_connection = uc; -static char * -ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_http_statsd_conf_t *prev = parent; - ngx_http_statsd_conf_t *conf = child; - ngx_statsd_stat_t *stat; - ngx_statsd_stat_t prev_stat; - ngx_statsd_stat_t *prev_stats; - ngx_uint_t i; - ngx_uint_t sz; - - ngx_conf_merge_ptr_value(conf->endpoint, prev->endpoint, NULL); - ngx_conf_merge_off_value(conf->off, prev->off, 1); - ngx_conf_merge_uint_value(conf->sample_rate, prev->sample_rate, 100); - - if (conf->stats == NULL) { - sz = (prev->stats != NULL ? prev->stats->nelts : 2); - conf->stats = ngx_array_create(cf->pool, sz, sizeof(ngx_statsd_stat_t)); - if (conf->stats == NULL) { - return NGX_CONF_ERROR; - } - } - if (prev->stats != NULL) { - prev_stats = prev->stats->elts; - for (i = 0; i < prev->stats->nelts; i++) { - stat = ngx_array_push(conf->stats); - ngx_memzero(stat, sizeof(ngx_statsd_stat_t)); - - prev_stat = prev_stats[i]; - - stat->type = prev_stat.type; - stat->key = prev_stat.key; - stat->metric = prev_stat.metric; - stat->ckey = prev_stat.ckey; - stat->cmetric = prev_stat.cmetric; - stat->valid = prev_stat.valid; - stat->cvalid = prev_stat.cvalid; - }; - }; + uc->sockaddr = endpoint->peer_addr.sockaddr; + uc->socklen = endpoint->peer_addr.socklen; + uc->server = endpoint->peer_addr.name; - return NGX_CONF_OK; + endpoint->log = &cf->cycle->new_log; + + return NGX_OK; } -static ngx_udp_endpoint_t * -ngx_http_statsd_add_endpoint(ngx_conf_t *cf, ngx_statsd_addr_t *peer_addr) -{ - ngx_http_statsd_main_conf_t *umcf; - ngx_udp_endpoint_t *endpoint; +static void ngx_statsd_updater_cleanup(void *data) { + fprintf(stderr, "ngx_statsd_updater_cleanup\n"); + ngx_udp_endpoint_t *e = data; - umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_statsd_module); + ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "cleanup statsd_updater"); - if(umcf->endpoints == NULL) { - umcf->endpoints = ngx_array_create(cf->pool, 2, sizeof(ngx_udp_endpoint_t)); - if (umcf->endpoints == NULL) { - return NULL; - } + if(e->udp_connection) { + if(e->udp_connection->connection) { + ngx_close_connection(e->udp_connection->connection); } + ngx_free(e->udp_connection); + } +} - endpoint = ngx_array_push(umcf->endpoints); - if (endpoint == NULL) { - return NULL; +static void ngx_http_statsd_udp_dummy_handler(ngx_event_t *ev) {} + +static ngx_int_t ngx_http_statsd_udp_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len) { + fprintf(stderr, "ngx_http_statsd_udp_send\n"); + ssize_t n; + ngx_udp_connection_t *uc; + + uc = l->udp_connection; + if (uc->connection == NULL) { + uc->log = *l->log; + uc->log.handler = NULL; + uc->log.data = NULL; + uc->log.action = "logging"; + + if(ngx_udp_connect(uc) != NGX_OK) { + if(uc->connection != NULL) { + ngx_free_connection(uc->connection); + uc->connection = NULL; + } + return NGX_ERROR; } - endpoint->peer_addr = *peer_addr; - - return endpoint; -} + uc->connection->data = l; + uc->connection->read->handler = ngx_http_statsd_udp_dummy_handler; + uc->connection->read->resolver = 0; + } -static char * -ngx_http_statsd_set_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_statsd_conf_t *ulcf = conf; - ngx_str_t *value; - ngx_url_t u; + n = ngx_send(uc->connection, buf, len); - value = cf->args->elts; + if (n == -1) { + return NGX_ERROR; + } - if (ngx_strcmp(value[1].data, "off") == 0) { - ulcf->off = 1; - return NGX_CONF_OK; - } - ulcf->off = 0; + if ((size_t) n != (size_t) len) { +#if defined nginx_version && nginx_version >= 8032 +ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); +#else +ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); +#endif - ngx_memzero(&u, sizeof(ngx_url_t)); + return NGX_ERROR; + } - u.url = value[1]; - u.default_port = STATSD_DEFAULT_PORT; - u.no_resolve = 0; + return NGX_OK; +} - if(ngx_parse_url(cf->pool, &u) != NGX_OK) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err); - return NGX_CONF_ERROR; - } +static void *ngx_http_statsd_create_main_conf(ngx_conf_t *cf) { + fprintf(stderr, "ngx_http_statsd_create_main_conf\n"); + ngx_http_statsd_main_conf_t *conf; - ulcf->endpoint = ngx_http_statsd_add_endpoint(cf, &u.addrs[0]); - if(ulcf->endpoint == NULL) { - return NGX_CONF_ERROR; - } + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_main_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } - return NGX_CONF_OK; + return conf; } -static char * -ngx_http_statsd_add_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_uint_t type) { - ngx_http_statsd_conf_t *ulcf = conf; - ngx_http_complex_value_t key_cv; - ngx_http_compile_complex_value_t key_ccv; - ngx_http_complex_value_t metric_cv; - ngx_http_compile_complex_value_t metric_ccv; - ngx_http_complex_value_t valid_cv; - ngx_http_compile_complex_value_t valid_ccv; - ngx_str_t *value; - ngx_statsd_stat_t *stat; - ngx_int_t n; - ngx_str_t s; - ngx_flag_t b; +static void *ngx_http_statsd_create_loc_conf(ngx_conf_t *cf) { + fprintf(stderr, "ngx_http_statsd_create_loc_conf\n"); + ngx_http_statsd_conf_t *conf; - value = cf->args->elts; + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + conf->endpoint = NGX_CONF_UNSET_PTR; + conf->off = NGX_CONF_UNSET; + conf->sample_rate = NGX_CONF_UNSET_UINT; + conf->stats = NULL; - if (ulcf->stats == NULL) { - ulcf->stats = ngx_array_create(cf->pool, 10, sizeof(ngx_statsd_stat_t)); - if (ulcf->stats == NULL) { - return NGX_CONF_ERROR; - } - } - - stat = ngx_array_push(ulcf->stats); - if (stat == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(stat, sizeof(ngx_statsd_stat_t)); - - stat->type = type; - stat->valid = 1; - - ngx_memzero(&key_ccv, sizeof(ngx_http_compile_complex_value_t)); - key_ccv.cf = cf; - key_ccv.value = &value[1]; - key_ccv.complex_value = &key_cv; - - if (ngx_http_compile_complex_value(&key_ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (key_cv.lengths == NULL) { - s = ngx_http_statsd_key_value(&value[1]); - /*if (n < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); - return NGX_CONF_ERROR; - };*/ - stat->key = (ngx_str_t) s; - } else { - stat->ckey = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); - if (stat->ckey == NULL) { - return NGX_CONF_ERROR; - } - *stat->ckey = key_cv; - } - - ngx_memzero(&metric_ccv, sizeof(ngx_http_compile_complex_value_t)); - metric_ccv.cf = cf; - metric_ccv.value = &value[2]; - metric_ccv.complex_value = &metric_cv; - - if (ngx_http_compile_complex_value(&metric_ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (metric_cv.lengths == NULL) { - n = ngx_http_statsd_metric_value(&value[2]); - if (n < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); - return NGX_CONF_ERROR; - }; - stat->metric = (ngx_uint_t) n; - } else { - stat->cmetric = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); - if (stat->cmetric == NULL) { - return NGX_CONF_ERROR; - } - *stat->cmetric = metric_cv; - } - - if (cf->args->nelts > 3) { - ngx_memzero(&valid_ccv, sizeof(ngx_http_compile_complex_value_t)); - valid_ccv.cf = cf; - valid_ccv.value = &value[3]; - valid_ccv.complex_value = &valid_cv; - - if (ngx_http_compile_complex_value(&valid_ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (valid_cv.lengths == NULL) { - b = ngx_http_statsd_valid_value(&value[3]); - if (b < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[3]); - return NGX_CONF_ERROR; - }; - stat->valid = (ngx_flag_t) b; - } else { - stat->cvalid = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); - if (stat->cvalid == NULL) { - return NGX_CONF_ERROR; - } - *stat->cvalid = valid_cv; - } - } - - return NGX_CONF_OK; + return conf; } -static char * -ngx_http_statsd_add_count(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_COUNTER); +static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { + fprintf(stderr, "ngx_http_statsd_merge_loc_conf:start\n"); + ngx_http_statsd_conf_t *prev = parent; + ngx_http_statsd_conf_t *conf = child; + ngx_statsd_stat_t *stat; + ngx_statsd_stat_t prev_stat; + ngx_statsd_stat_t *prev_stats; + ngx_uint_t i; + ngx_uint_t sz; + + ngx_conf_merge_ptr_value(conf->endpoint, prev->endpoint, NULL); + ngx_conf_merge_off_value(conf->off, prev->off, 1); + ngx_conf_merge_uint_value(conf->sample_rate, prev->sample_rate, 100); + + if (conf->stats == NULL) { + sz = (prev->stats != NULL ? prev->stats->nelts : 2); + conf->stats = ngx_array_create(cf->pool, sz, sizeof(ngx_statsd_stat_t)); + if (conf->stats == NULL) { + return NGX_CONF_ERROR; + } + } + fprintf(stderr, "ngx_http_statsd_merge_loc_conf:middle:merge_loop\n"); + if (prev->stats != NULL) { + prev_stats = prev->stats->elts; + for (i = 0; i < prev->stats->nelts; i++) { + stat = ngx_array_push(conf->stats); + ngx_memzero(stat, sizeof(ngx_statsd_stat_t)); + prev_stat = prev_stats[i]; + stat->type = prev_stat.type; + stat->key = prev_stat.key; + stat->metric = prev_stat.metric; + stat->metric_str = prev_stat.metric_str; + stat->ckey = prev_stat.ckey; + stat->cmetric = prev_stat.cmetric; + stat->cmetric_str = prev_stat.cmetric_str; + stat->valid = prev_stat.valid; + stat->cvalid = prev_stat.cvalid; + }; + }; + fprintf(stderr, "ngx_http_statsd_merge_loc_conf:stop\n"); + return NGX_CONF_OK; } -static char * -ngx_http_statsd_add_timing(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_TIMING); -} +static ngx_udp_endpoint_t *ngx_http_statsd_add_endpoint(ngx_conf_t *cf, ngx_statsd_addr_t *peer_addr) { + fprintf(stderr, "ngx_http_statsd_add_endpoint\n"); + ngx_http_statsd_main_conf_t *umcf; + ngx_udp_endpoint_t *endpoint; -static ngx_int_t -ngx_http_statsd_init(ngx_conf_t *cf) -{ - ngx_int_t rc; - ngx_uint_t i; - ngx_http_core_main_conf_t *cmcf; - ngx_http_statsd_main_conf_t *umcf; - ngx_http_handler_pt *h; - ngx_udp_endpoint_t *e; - - umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_statsd_module); - - if(umcf->endpoints != NULL) { - e = umcf->endpoints->elts; - for(i = 0;i < umcf->endpoints->nelts;i++) { - rc = ngx_statsd_init_endpoint(cf, e + i); - - if(rc != NGX_OK) { - return NGX_ERROR; - } - } + umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_statsd_module); - cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + if(umcf->endpoints == NULL) { + umcf->endpoints = ngx_array_create(cf->pool, 2, sizeof(ngx_udp_endpoint_t)); + if (umcf->endpoints == NULL) { + return NULL; + } + } - h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); - if (h == NULL) { - return NGX_ERROR; - } + endpoint = ngx_array_push(umcf->endpoints); - *h = ngx_http_statsd_handler; - } + if (endpoint == NULL) { + return NULL; + } - return NGX_OK; + endpoint->peer_addr = *peer_addr; + + return endpoint; } -uintptr_t -ngx_escape_statsd_key(u_char *dst, u_char *src, size_t size) -{ - ngx_uint_t n; - uint32_t *escape; +static char *ngx_http_statsd_set_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + fprintf(stderr, "ngx_http_statsd_set_server\n"); + ngx_http_statsd_conf_t *ulcf = conf; + ngx_str_t *value; + ngx_url_t u; + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + ulcf->off = 1; + return NGX_CONF_OK; + } + ulcf->off = 0; + + ngx_memzero(&u, sizeof(ngx_url_t)); - /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ + u.url = value[1]; + u.default_port = STATSD_DEFAULT_PORT; + u.no_resolve = 0; - static uint32_t statsd_key[] = { - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + if(ngx_parse_url(cf->pool, &u) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err); + return NGX_CONF_ERROR; + } - /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0xfc00bfff, /* 1111 1100 0000 0000 1011 1111 1111 1111 */ + ulcf->endpoint = ngx_http_statsd_add_endpoint(cf, &u.addrs[0]); - /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */ + if(ulcf->endpoint == NULL) { + return NGX_CONF_ERROR; + } - /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0xf8000001, /* 1111 1000 0000 0000 0000 0000 0000 0001 */ + return NGX_CONF_OK; +} + +static char *ngx_http_statsd_add_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_uint_t type) { + fprintf(stderr, "ngx_http_statsd_add_stat\n"); + ngx_http_statsd_conf_t *ulcf = conf; + ngx_http_complex_value_t key_cv; + ngx_http_compile_complex_value_t key_ccv; + ngx_http_complex_value_t metric_cv; + ngx_http_compile_complex_value_t metric_ccv; + ngx_http_complex_value_t valid_cv; + ngx_http_compile_complex_value_t valid_ccv; + ngx_str_t *value; + ngx_statsd_stat_t *stat; + ngx_int_t n; + ngx_str_t n_str; + ngx_str_t s; + ngx_flag_t b; + + value = cf->args->elts; - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + if (ulcf->stats == NULL) { + ulcf->stats = ngx_array_create(cf->pool, 10, sizeof(ngx_statsd_stat_t)); + if (ulcf->stats == NULL) { + return NGX_CONF_ERROR; + } + } + + stat = ngx_array_push(ulcf->stats); + if (stat == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(stat, sizeof(ngx_statsd_stat_t)); + + stat->type = type; + stat->valid = 1; + + ngx_memzero(&key_ccv, sizeof(ngx_http_compile_complex_value_t)); + key_ccv.cf = cf; + key_ccv.value = &value[1]; + key_ccv.complex_value = &key_cv; + + if (ngx_http_compile_complex_value(&key_ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (key_cv.lengths == NULL) { + s = ngx_http_statsd_key_value(&value[1]); + /*if (n < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; + };*/ + stat->key = (ngx_str_t) s; + } else { + stat->ckey = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (stat->ckey == NULL) { + return NGX_CONF_ERROR; + } + *stat->ckey = key_cv; + } + + ngx_memzero(&metric_ccv, sizeof(ngx_http_compile_complex_value_t)); + metric_ccv.cf = cf; + metric_ccv.value = &value[2]; + metric_ccv.complex_value = &metric_cv; + + if (ngx_http_compile_complex_value(&metric_ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (metric_cv.lengths == NULL) { + n = ngx_http_statsd_metric_value(&value[2]); + n_str = ngx_http_statsd_set_value(&value[2]); + if (n < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[2]); + return NGX_CONF_ERROR; }; + stat->metric = (ngx_uint_t) n; + stat->metric_str = (ngx_str_t) n_str; + } else { + stat->cmetric = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + stat->cmetric_str = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (stat->cmetric == NULL) { + return NGX_CONF_ERROR; + } + *stat->cmetric = metric_cv; + *stat->cmetric_str = metric_cv; + } + + if (cf->args->nelts > 3) { + ngx_memzero(&valid_ccv, sizeof(ngx_http_compile_complex_value_t)); + valid_ccv.cf = cf; + valid_ccv.value = &value[3]; + valid_ccv.complex_value = &valid_cv; + + if (ngx_http_compile_complex_value(&valid_ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } - static uint32_t *map[] = - { statsd_key }; + if (valid_cv.lengths == NULL) { + b = ngx_http_statsd_valid_value(&value[3]); + if (b < 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[3]); + return NGX_CONF_ERROR; + }; + stat->valid = (ngx_flag_t) b; + } else { + stat->cvalid = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (stat->cvalid == NULL) { + return NGX_CONF_ERROR; + } + *stat->cvalid = valid_cv; + } + } + return NGX_CONF_OK; +} - escape = map[0]; +static char *ngx_http_statsd_add_count(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + fprintf(stderr, "ngx_http_statsd_add_count\n"); + return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_COUNTER); +} - if (dst == NULL) { +static char *ngx_http_statsd_add_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + fprintf(stderr, "ngx_http_statsd_add_set\n"); + return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_SET); +} - /* find the number of the characters to be escaped */ +static char *ngx_http_statsd_add_timing(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + fprintf(stderr, "ngx_http_statsd_add_timing\n"); + return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_TIMING); +} - n = 0; +static ngx_int_t ngx_http_statsd_init(ngx_conf_t *cf) { + fprintf(stderr, "ngx_http_statsd_init\n"); + ngx_int_t rc; + ngx_uint_t i; + ngx_http_core_main_conf_t *cmcf; + ngx_http_statsd_main_conf_t *umcf; + ngx_http_handler_pt *h; + ngx_udp_endpoint_t *e; + + umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_statsd_module); + + if(umcf->endpoints != NULL) { + e = umcf->endpoints->elts; + for(i = 0;i < umcf->endpoints->nelts;i++) { + rc = ngx_statsd_init_endpoint(cf, e + i); + if(rc != NGX_OK) { + return NGX_ERROR; + } + } - while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { - n++; - } - src++; - size--; - } + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - return (uintptr_t) n; + h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; } - while (size) { - if (escape[*src >> 5] & (1 << (*src & 0x1f))) { - *dst++ = '_'; - src++; + *h = ngx_http_statsd_handler; + } - } else { - *dst++ = *src++; - } - size--; + return NGX_OK; +} + +uintptr_t ngx_escape_statsd_key(u_char *dst, u_char *src, size_t size) { + fprintf(stderr, "ngx_escape_statsd_key\n"); + ngx_uint_t n; + uint32_t *escape; + /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ + static uint32_t statsd_key[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0xfc00bfff, /* 1111 1100 0000 0000 1011 1111 1111 1111 */ + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */ + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xf8000001, /* 1111 1000 0000 0000 0000 0000 0000 0001 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + + static uint32_t *map[] = { statsd_key }; + + escape = map[0]; + + if (dst == NULL) { + /* find the number of the characters to be escaped */ + n = 0; + while (size) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + n++; + } + src++; + size--; + } + return (uintptr_t) n; + } + + while (size) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + *dst++ = '_'; + src++; + } else { + *dst++ = *src++; } + size--; + } - return (uintptr_t) dst; + return (uintptr_t) dst; } From 02f64701a3e27814ed6e88fd2862054432c75900 Mon Sep 17 00:00:00 2001 From: Eric Sabelhaus Date: Thu, 21 May 2015 14:09:52 -0400 Subject: [PATCH 2/4] remove debug statements --- ngx_http_statsd.c | 65 +++++------------------------------------------ 1 file changed, 6 insertions(+), 59 deletions(-) diff --git a/ngx_http_statsd.c b/ngx_http_statsd.c index f01aeef..5e9d639 100644 --- a/ngx_http_statsd.c +++ b/ngx_http_statsd.c @@ -167,7 +167,6 @@ ngx_module_t ngx_http_statsd_module = { }; static ngx_str_t ngx_http_statsd_key_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) { - fprintf(stderr, "ngx_http_statsd_key_get_value\n"); ngx_str_t val; if (cv == NULL) { return v; @@ -181,12 +180,10 @@ static ngx_str_t ngx_http_statsd_key_get_value(ngx_http_request_t *r, ngx_http_c }; static ngx_str_t ngx_http_statsd_key_value(ngx_str_t *value) { - fprintf(stderr, "ngx_http_statsd_key_value\n"); return *value; }; static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) { - fprintf(stderr, "ngx_http_statsd_set_get_value\n"); ngx_str_t val; if (cv == NULL) { return v; @@ -201,12 +198,10 @@ static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_c static ngx_str_t ngx_http_statsd_set_value(ngx_str_t *value) { - fprintf(stderr, "ngx_http_statsd_set_value\n"); return *value; }; static ngx_uint_t ngx_http_statsd_metric_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_uint_t v) { - fprintf(stderr, "ngx_http_statsd_metric_get_value\n"); ngx_str_t val; if (cv == NULL) { return v; @@ -220,7 +215,6 @@ static ngx_uint_t ngx_http_statsd_metric_get_value(ngx_http_request_t *r, ngx_ht }; static ngx_uint_t ngx_http_statsd_metric_value(ngx_str_t *value) { - fprintf(stderr, "ngx_http_statsd_metric_value\n"); ngx_int_t n, m; if (value->len == 1 && value->data[0] == '-') { @@ -231,8 +225,8 @@ static ngx_uint_t ngx_http_statsd_metric_value(ngx_str_t *value) { if (value->len > 4 && value->data[value->len - 4] == '.') { n = ngx_atoi(value->data, value->len - 4); m = ngx_atoi(value->data + (value->len - 3), 3); - return (ngx_uint_t) ((n * 1000) + m); + return (ngx_uint_t) ((n * 1000) + m); } else { n = ngx_atoi(value->data, value->len); if (n > 0) { @@ -244,7 +238,6 @@ static ngx_uint_t ngx_http_statsd_metric_value(ngx_str_t *value) { }; static ngx_flag_t ngx_http_statsd_valid_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_flag_t v) { - fprintf(stderr, "ngx_http_statsd_valid_get_value\n"); ngx_str_t val; if (cv == NULL) { return v; @@ -258,12 +251,10 @@ static ngx_flag_t ngx_http_statsd_valid_get_value(ngx_http_request_t *r, ngx_htt }; static ngx_flag_t ngx_http_statsd_valid_value(ngx_str_t *value) { - fprintf(stderr, "ngx_http_statsd_valid_value\n"); return (ngx_flag_t) (value->len > 0 ? 1 : 0); }; ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { - fprintf(stderr, "ngx_http_statsd_handler:start\n"); u_char line[STATSD_MAX_STR], *p; const char *metric_type; ngx_http_statsd_conf_t *ulcf; @@ -292,67 +283,42 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { stats = ulcf->stats->elts; - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop\n"); - int i = 0; for (c = 0; c < ulcf->stats->nelts; c++) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:%d\n", i++); stat = stats[c]; s = ngx_http_statsd_key_get_value(r, stat.ckey, stat.key); - ngx_escape_statsd_key(s.data, s.data, s.len); - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:before\n"); - n = ngx_http_statsd_metric_get_value(r, stat.cmetric, stat.metric); - - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:middle\n"); - b = ngx_http_statsd_valid_get_value(r, stat.cvalid, stat.valid); - - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after\n"); - set = ngx_http_statsd_set_get_value(r, stat.cmetric_str, stat.metric_str); if (b == 0 || s.len == 0 || ( n <= 0 && set.len == 0 )) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:BAIL\n"); // Do not log if not valid, key is invalid, or valud is lte 0. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: no value to send"); continue; }; - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:before_if_statement\n"); if (stat.type == STATSD_TYPE_COUNTER) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_counter\n"); - metric_type = "c"; + metric_type = "c"; } else if (stat.type == STATSD_TYPE_TIMING) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_timing\n"); - metric_type = "ms"; + metric_type = "ms"; } else if (stat.type == STATSD_TYPE_SET) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_set\n"); - metric_type = "s"; + metric_type = "s"; } else { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:type_null\n"); - metric_type = NULL; + metric_type = NULL; } - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:start\n"); if (metric_type) { if (stat.type == STATSD_TYPE_SET) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET\n"); if (ulcf->sample_rate < 100) { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:sample_rate:before\n"); p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%s|s|@0.%02d", &s, set, ulcf->sample_rate); - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:sample_rate:after\n"); } else { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:non_sample_rate:before\n"); p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|s", &s, set); - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_SET:non_sample_rate:after\n"); } ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); } else { - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:TYPE_OTHER\n"); if (ulcf->sample_rate < 100) { p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s|@0.%02d", &s, n, metric_type, ulcf->sample_rate); } else { @@ -361,18 +327,14 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); } } - fprintf(stderr, "ngx_http_statsd_handler:start:for_loop:after_type_set:stop\n"); - } - fprintf(stderr, "ngx_http_statsd_handler:stop:for_loop\n"); + } - fprintf(stderr, "ngx_http_statsd_handler:stop\n"); return NGX_OK; } static ngx_int_t ngx_statsd_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *endpoint) { - fprintf(stderr, "ngx_statsd_init_endpoint\n"); ngx_pool_cleanup_t *cln; ngx_udp_connection_t *uc; @@ -403,7 +365,6 @@ static ngx_int_t ngx_statsd_init_endpoint(ngx_conf_t *cf, ngx_udp_endpoint_t *en } static void ngx_statsd_updater_cleanup(void *data) { - fprintf(stderr, "ngx_statsd_updater_cleanup\n"); ngx_udp_endpoint_t *e = data; ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "cleanup statsd_updater"); @@ -419,7 +380,6 @@ static void ngx_statsd_updater_cleanup(void *data) { static void ngx_http_statsd_udp_dummy_handler(ngx_event_t *ev) {} static ngx_int_t ngx_http_statsd_udp_send(ngx_udp_endpoint_t *l, u_char *buf, size_t len) { - fprintf(stderr, "ngx_http_statsd_udp_send\n"); ssize_t n; ngx_udp_connection_t *uc; @@ -463,7 +423,6 @@ ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); } static void *ngx_http_statsd_create_main_conf(ngx_conf_t *cf) { - fprintf(stderr, "ngx_http_statsd_create_main_conf\n"); ngx_http_statsd_main_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_main_conf_t)); @@ -475,7 +434,6 @@ static void *ngx_http_statsd_create_main_conf(ngx_conf_t *cf) { } static void *ngx_http_statsd_create_loc_conf(ngx_conf_t *cf) { - fprintf(stderr, "ngx_http_statsd_create_loc_conf\n"); ngx_http_statsd_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_statsd_conf_t)); @@ -491,7 +449,6 @@ static void *ngx_http_statsd_create_loc_conf(ngx_conf_t *cf) { } static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { - fprintf(stderr, "ngx_http_statsd_merge_loc_conf:start\n"); ngx_http_statsd_conf_t *prev = parent; ngx_http_statsd_conf_t *conf = child; ngx_statsd_stat_t *stat; @@ -511,7 +468,6 @@ static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void * return NGX_CONF_ERROR; } } - fprintf(stderr, "ngx_http_statsd_merge_loc_conf:middle:merge_loop\n"); if (prev->stats != NULL) { prev_stats = prev->stats->elts; for (i = 0; i < prev->stats->nelts; i++) { @@ -529,12 +485,10 @@ static char *ngx_http_statsd_merge_loc_conf(ngx_conf_t *cf, void *parent, void * stat->cvalid = prev_stat.cvalid; }; }; - fprintf(stderr, "ngx_http_statsd_merge_loc_conf:stop\n"); return NGX_CONF_OK; } static ngx_udp_endpoint_t *ngx_http_statsd_add_endpoint(ngx_conf_t *cf, ngx_statsd_addr_t *peer_addr) { - fprintf(stderr, "ngx_http_statsd_add_endpoint\n"); ngx_http_statsd_main_conf_t *umcf; ngx_udp_endpoint_t *endpoint; @@ -559,7 +513,6 @@ static ngx_udp_endpoint_t *ngx_http_statsd_add_endpoint(ngx_conf_t *cf, ngx_stat } static char *ngx_http_statsd_set_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - fprintf(stderr, "ngx_http_statsd_set_server\n"); ngx_http_statsd_conf_t *ulcf = conf; ngx_str_t *value; ngx_url_t u; @@ -593,7 +546,6 @@ static char *ngx_http_statsd_set_server(ngx_conf_t *cf, ngx_command_t *cmd, void } static char *ngx_http_statsd_add_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_uint_t type) { - fprintf(stderr, "ngx_http_statsd_add_stat\n"); ngx_http_statsd_conf_t *ulcf = conf; ngx_http_complex_value_t key_cv; ngx_http_compile_complex_value_t key_ccv; @@ -709,22 +661,18 @@ static char *ngx_http_statsd_add_stat(ngx_conf_t *cf, ngx_command_t *cmd, void * } static char *ngx_http_statsd_add_count(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - fprintf(stderr, "ngx_http_statsd_add_count\n"); return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_COUNTER); } static char *ngx_http_statsd_add_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - fprintf(stderr, "ngx_http_statsd_add_set\n"); return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_SET); } static char *ngx_http_statsd_add_timing(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - fprintf(stderr, "ngx_http_statsd_add_timing\n"); return ngx_http_statsd_add_stat(cf, cmd, conf, STATSD_TYPE_TIMING); } static ngx_int_t ngx_http_statsd_init(ngx_conf_t *cf) { - fprintf(stderr, "ngx_http_statsd_init\n"); ngx_int_t rc; ngx_uint_t i; ngx_http_core_main_conf_t *cmcf; @@ -757,7 +705,6 @@ static ngx_int_t ngx_http_statsd_init(ngx_conf_t *cf) { } uintptr_t ngx_escape_statsd_key(u_char *dst, u_char *src, size_t size) { - fprintf(stderr, "ngx_escape_statsd_key\n"); ngx_uint_t n; uint32_t *escape; /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ From 2fe3e344d8f03a03c3b1357fb5fe4aeb14e4f797 Mon Sep 17 00:00:00 2001 From: Eric Sabelhaus Date: Thu, 21 May 2015 14:19:12 -0400 Subject: [PATCH 3/4] trying to fix stuff --- ngx_http_statsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ngx_http_statsd.c b/ngx_http_statsd.c index 5e9d639..159f9c7 100644 --- a/ngx_http_statsd.c +++ b/ngx_http_statsd.c @@ -313,9 +313,9 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { if (metric_type) { if (stat.type == STATSD_TYPE_SET) { if (ulcf->sample_rate < 100) { - p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%s|s|@0.%02d", &s, set, ulcf->sample_rate); + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%V|s|@0.%02d", &s, &set, ulcf->sample_rate); } else { - p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|s", &s, set); + p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%V|s", &s, &set); } ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); } else { From 461b83f9b7439f731b31b9da12af67678cb359c8 Mon Sep 17 00:00:00 2001 From: Eric Sabelhaus Date: Thu, 21 May 2015 15:00:24 -0400 Subject: [PATCH 4/4] Cleaned up a little bit, added comments, updated readme --- README.mkd => README.md | 17 +++++++++++------ ngx_http_statsd.c | 9 ++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) rename README.mkd => README.md (80%) diff --git a/README.mkd b/README.md similarity index 80% rename from README.mkd rename to README.md index 222865a..649897b 100644 --- a/README.mkd +++ b/README.md @@ -6,24 +6,29 @@ An nginx module for sending statistics to statsd. This is how to use the nginx-statsd module: http { - + # Set the server that you want to send stats to. statsd_server your.statsd.server.com; # Randomly sample 10% of requests so that you do not overwhelm your statsd server. - # Defaults to sending all statsd (100%). + # Defaults to sending all statsd (100%). statsd_sample_rate 10; # 10% of requests server { listen 80; server_name www.your.domain.com; - - # Increment "your_product.requests" by 1 whenever any request hits this server. + + # Increment "your_product.requests" by 1 whenever any request hits this server. statsd_count "your_product.requests" 1; + # send set to statsd to count unique visitors, the metric should be a dynamic property + # Here I use the $remote_addr variable from nginx to register the request from a unique IP + # Argument must be a String + statsd_set "your_unique_metric" "$remote_addr"; + location / { - + # Increment the key by 1 when this location is hit. statsd_count "your_product.pages.index_requests" 1; @@ -37,7 +42,7 @@ This is how to use the nginx-statsd module: # Increment a key based on the value of a custom header. Only sends the value if # the custom header exists in the upstream response. - statsd_count "your_product.custom_$upstream_http_x_some_custom_header" 1 + statsd_count "your_product.custom_$upstream_http_x_some_custom_header" 1 "$upstream_http_x_some_custom_header"; proxy_pass http://some.other.domain.com; diff --git a/ngx_http_statsd.c b/ngx_http_statsd.c index 159f9c7..33c434c 100644 --- a/ngx_http_statsd.c +++ b/ngx_http_statsd.c @@ -7,7 +7,7 @@ * details. * * Copyright (C) 2010 Valery Kholodkov -*/ + */ #include #include #include @@ -183,6 +183,7 @@ static ngx_str_t ngx_http_statsd_key_value(ngx_str_t *value) { return *value; }; +// added to provide string value of set metric static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_complex_value_t *cv, ngx_str_t v) { ngx_str_t val; if (cv == NULL) { @@ -196,7 +197,7 @@ static ngx_str_t ngx_http_statsd_set_get_value(ngx_http_request_t *r, ngx_http_c return ngx_http_statsd_key_value(&val); }; - +// added to provide string value of set metric static ngx_str_t ngx_http_statsd_set_value(ngx_str_t *value) { return *value; }; @@ -294,7 +295,7 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { set = ngx_http_statsd_set_get_value(r, stat.cmetric_str, stat.metric_str); if (b == 0 || s.len == 0 || ( n <= 0 && set.len == 0 )) { - // Do not log if not valid, key is invalid, or valud is lte 0. + // Do not log if not valid, key is invalid, or value is less than 0. ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "statsd: no value to send"); continue; }; @@ -312,6 +313,7 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { if (metric_type) { if (stat.type == STATSD_TYPE_SET) { + // handle a set if (ulcf->sample_rate < 100) { p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%V|s|@0.%02d", &s, &set, ulcf->sample_rate); } else { @@ -319,6 +321,7 @@ ngx_int_t ngx_http_statsd_handler(ngx_http_request_t *r) { } ngx_http_statsd_udp_send(ulcf->endpoint, line, p - line); } else { + // handle all other requests if (ulcf->sample_rate < 100) { p = ngx_snprintf(line, STATSD_MAX_STR, "%V:%d|%s|@0.%02d", &s, n, metric_type, ulcf->sample_rate); } else {