Skip to content

Commit c382342

Browse files
authored
Merge pull request #317 from wpjunior/feat/measure-status-codes
Add support to measure status_codes
2 parents 1485f3f + f6ac339 commit c382342

11 files changed

+304
-47
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,41 @@ http {
18871887
}
18881888
```
18891889

1890+
### vhost_traffic_status_measure_status_codes
1891+
1892+
Allows tracking of specific HTTP status codes or all status codes in the Vhost Traffic Status module.
1893+
1894+
1895+
| - | - |
1896+
| --- | --- |
1897+
| **Syntax** | vhost_traffic_status_measure_status_codes [all] [status_code1] [status_code2] ... |
1898+
| **Default** | off |
1899+
| **Context** | http |
1900+
1901+
1902+
1903+
#### Parameters
1904+
- `status_code1, status_code2, ...`: Specific HTTP status codes to track (100-599)
1905+
- `all`: Track all HTTP status codes
1906+
1907+
#### Examples
1908+
1909+
Track specific status codes:
1910+
```nginx
1911+
vhost_traffic_status_measure_status_codes 200 404 500;
1912+
```
1913+
1914+
Track all status codes:
1915+
```nginx
1916+
vhost_traffic_status_measure_status_codes all;
1917+
```
1918+
1919+
#### Description
1920+
- By default, no specific status code tracking is enabled
1921+
- Status codes must be in ascending order
1922+
- Only valid HTTP status codes between 100 and 599 are accepted
1923+
- When using `all`, every status code will be tracked
1924+
18901925
## Releases
18911926

18921927
To cut a release, create a changelog entry PR with [git-chglog](https://github.com/git-chglog/git-chglog)

src/ngx_http_vhost_traffic_status_display_json.c

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,13 @@ ngx_http_vhost_traffic_status_display_set_server_node(
5959
{
6060
u_char *p, *c;
6161
ngx_int_t rc;
62+
ngx_uint_t i;
6263
ngx_str_t tmp, dst;
64+
ngx_uint_t *status_codes;
6365
ngx_http_vhost_traffic_status_loc_conf_t *vtscf;
66+
ngx_http_vhost_traffic_status_ctx_t *ctx;
6467

68+
ctx = ngx_http_get_module_main_conf(r, ngx_http_vhost_traffic_status_module);
6569
vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module);
6670

6771
tmp = *key;
@@ -91,17 +95,42 @@ ngx_http_vhost_traffic_status_display_set_server_node(
9195
"display_set_server_node::escape_json_pool() failed");
9296
}
9397

94-
#if (NGX_HTTP_CACHE)
9598
ngx_http_vhost_traffic_status_display_encode_uri(r, &dst);
96-
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER,
97-
&dst, vtsn->stat_request_counter,
98-
vtsn->stat_in_bytes,
99-
vtsn->stat_out_bytes,
100-
vtsn->stat_1xx_counter,
101-
vtsn->stat_2xx_counter,
102-
vtsn->stat_3xx_counter,
103-
vtsn->stat_4xx_counter,
104-
vtsn->stat_5xx_counter,
99+
100+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_START,
101+
&dst, vtsn->stat_request_counter,
102+
vtsn->stat_in_bytes,
103+
vtsn->stat_out_bytes);
104+
105+
if (ctx->measure_status_codes != NULL && vtsn->stat_status_code_counter != NULL) {
106+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE_START);
107+
108+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_OTHER_STATUS_CODE,
109+
vtsn->stat_status_code_counter[0]);
110+
111+
status_codes = (ngx_uint_t *) ctx->measure_status_codes->elts;
112+
113+
for (i = 0; i < ctx->measure_status_codes->nelts; i++) {
114+
if (vtsn->stat_status_code_counter[i+1] == 0 && ctx->measure_all_status_codes) {
115+
continue;
116+
}
117+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE,
118+
status_codes[i], vtsn->stat_status_code_counter[i+1]);
119+
}
120+
121+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE_END);
122+
}
123+
124+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_MIDDLE,
125+
vtsn->stat_1xx_counter,
126+
vtsn->stat_2xx_counter,
127+
vtsn->stat_3xx_counter,
128+
vtsn->stat_4xx_counter,
129+
vtsn->stat_5xx_counter);
130+
131+
132+
#if (NGX_HTTP_CACHE)
133+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_END,
105134
vtsn->stat_cache_miss_counter,
106135
vtsn->stat_cache_bypass_counter,
107136
vtsn->stat_cache_expired_counter,
@@ -141,16 +170,7 @@ ngx_http_vhost_traffic_status_display_set_server_node(
141170
vtsn->stat_cache_scarce_counter_oc,
142171
vtsn->stat_request_time_counter_oc);
143172
#else
144-
ngx_http_vhost_traffic_status_display_encode_uri(r, &dst);
145-
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER,
146-
&dst, vtsn->stat_request_counter,
147-
vtsn->stat_in_bytes,
148-
vtsn->stat_out_bytes,
149-
vtsn->stat_1xx_counter,
150-
vtsn->stat_2xx_counter,
151-
vtsn->stat_3xx_counter,
152-
vtsn->stat_4xx_counter,
153-
vtsn->stat_5xx_counter,
173+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_END,
154174
vtsn->stat_request_time_counter,
155175
ngx_http_vhost_traffic_status_node_time_queue_average(
156176
&vtsn->stat_request_times, vtscf->average_method,
@@ -217,6 +237,12 @@ ngx_http_vhost_traffic_status_display_set_server(ngx_http_request_t *r,
217237
&vtscf->stats.stat_request_times,
218238
&vtsn->stat_request_times, vtscf->average_period);
219239

240+
if (ctx->measure_status_codes != NULL && vtsn->stat_status_code_counter != NULL) {
241+
ngx_http_vhost_traffic_status_status_code_merge(
242+
vtscf->stats.stat_status_code_counter,
243+
vtsn->stat_status_code_counter, ctx->measure_status_codes->nelts+1);
244+
}
245+
220246
vtscf->stats.stat_request_counter_oc += vtsn->stat_request_counter_oc;
221247
vtscf->stats.stat_in_bytes_oc += vtsn->stat_in_bytes_oc;
222248
vtscf->stats.stat_out_bytes_oc += vtsn->stat_out_bytes_oc;
@@ -855,6 +881,11 @@ ngx_http_vhost_traffic_status_display_set(ngx_http_request_t *r,
855881
ngx_memzero(&vtscf->stats, sizeof(vtscf->stats));
856882
ngx_http_vhost_traffic_status_node_time_queue_init(&vtscf->stats.stat_request_times);
857883

884+
if (ctx->measure_status_codes != NULL) {
885+
vtscf->stats.stat_status_code_counter = ngx_pcalloc(r->pool, sizeof(ngx_atomic_t) * (ctx->measure_status_codes->nelts +1));
886+
vtscf->stats.stat_status_code_length = ctx->measure_status_codes->nelts;
887+
}
888+
858889
/* main & connections */
859890
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_S);
860891

src/ngx_http_vhost_traffic_status_display_json.h

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,20 @@
4040

4141
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_S "\"serverZones\":{"
4242

43-
#if (NGX_HTTP_CACHE)
44-
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER "\"%V\":{" \
43+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_START "\"%V\":{" \
4544
"\"requestCounter\":%uA," \
4645
"\"inBytes\":%uA," \
47-
"\"outBytes\":%uA," \
48-
"\"responses\":{" \
46+
"\"outBytes\":%uA,"
47+
48+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_MIDDLE "\"responses\":{" \
4949
"\"1xx\":%uA," \
5050
"\"2xx\":%uA," \
5151
"\"3xx\":%uA," \
5252
"\"4xx\":%uA," \
53-
"\"5xx\":%uA," \
54-
"\"miss\":%uA," \
53+
"\"5xx\":%uA"
54+
55+
#if (NGX_HTTP_CACHE)
56+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_END ",\"miss\":%uA," \
5557
"\"bypass\":%uA," \
5658
"\"expired\":%uA," \
5759
"\"stale\":%uA," \
@@ -92,17 +94,7 @@
9294
"}" \
9395
"},"
9496
#else
95-
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER "\"%V\":{" \
96-
"\"requestCounter\":%uA," \
97-
"\"inBytes\":%uA," \
98-
"\"outBytes\":%uA," \
99-
"\"responses\":{" \
100-
"\"1xx\":%uA," \
101-
"\"2xx\":%uA," \
102-
"\"3xx\":%uA," \
103-
"\"4xx\":%uA," \
104-
"\"5xx\":%uA" \
105-
"}," \
97+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_END "}," \
10698
"\"requestMsecCounter\":%uA," \
10799
"\"requestMsec\":%M," \
108100
"\"requestMsecs\":{" \
@@ -128,6 +120,11 @@
128120
"},"
129121
#endif
130122

123+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE_START "\"statusCodes\":{"
124+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE ",\"%uA\":%uA"
125+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_OTHER_STATUS_CODE "\"other\":%uA"
126+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_SERVER_STATUS_CODE_END "}, "
127+
131128
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_FILTER_S "\"filterZones\":{"
132129

133130
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_UPSTREAM_S "\"upstreamZones\":{"

src/ngx_http_vhost_traffic_status_display_prometheus.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ ngx_http_vhost_traffic_status_display_prometheus_set_server_node(
5454
ngx_str_t server;
5555
ngx_uint_t i, n;
5656
ngx_http_vhost_traffic_status_loc_conf_t *vtscf;
57+
ngx_http_vhost_traffic_status_ctx_t *ctx;
5758
ngx_http_vhost_traffic_status_node_histogram_bucket_t *b;
5859

60+
ctx = ngx_http_get_module_main_conf(r, ngx_http_vhost_traffic_status_module);
5961
vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module);
6062

6163
server = *key;
@@ -75,6 +77,23 @@ ngx_http_vhost_traffic_status_display_prometheus_set_server_node(
7577
&vtsn->stat_request_times, vtscf->average_method,
7678
vtscf->average_period) / 1000);
7779

80+
81+
if (ctx->measure_status_codes != NULL && vtsn->stat_status_code_counter != NULL) {
82+
ngx_uint_t *status_codes = (ngx_uint_t *) ctx->measure_status_codes->elts;
83+
84+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_PROMETHEUS_FMT_SERVER_OTHER_STATUS_CODE,
85+
&server, vtsn->stat_status_code_counter[0]);
86+
87+
for (i = 0; i < ctx->measure_status_codes->nelts; i++) {
88+
if (vtsn->stat_status_code_counter[i+1] == 0 && ctx->measure_all_status_codes) {
89+
continue;
90+
}
91+
92+
buf = ngx_sprintf(buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_PROMETHEUS_FMT_SERVER_STATUS_CODE,
93+
&server, status_codes[i], vtsn->stat_status_code_counter[i+1]);
94+
}
95+
}
96+
7897
/* histogram */
7998
b = &vtsn->stat_request_buckets;
8099

@@ -157,6 +176,11 @@ ngx_http_vhost_traffic_status_display_prometheus_set_server(ngx_http_request_t *
157176
&vtscf->stats.stat_request_times,
158177
&vtsn->stat_request_times, vtscf->average_period);
159178

179+
if (ctx->measure_status_codes != NULL && vtsn->stat_status_code_counter != NULL) {
180+
ngx_http_vhost_traffic_status_status_code_merge(vtscf->stats.stat_status_code_counter,
181+
vtsn->stat_status_code_counter, ctx->measure_status_codes->nelts+1);
182+
}
183+
160184
#if (NGX_HTTP_CACHE)
161185
vtscf->stats.stat_cache_miss_counter +=
162186
vtsn->stat_cache_miss_counter;
@@ -497,6 +521,11 @@ ngx_http_vhost_traffic_status_display_prometheus_set(ngx_http_request_t *r,
497521
ngx_memzero(&vtscf->stats, sizeof(vtscf->stats));
498522
ngx_http_vhost_traffic_status_node_time_queue_init(&vtscf->stats.stat_request_times);
499523

524+
if (ctx->measure_status_codes != NULL) {
525+
vtscf->stats.stat_status_code_counter = ngx_pcalloc(r->pool, sizeof(ngx_atomic_t) * (ctx->measure_status_codes->nelts+1));
526+
vtscf->stats.stat_status_code_length = ctx->measure_status_codes->nelts;
527+
}
528+
500529
/* main & connections */
501530
buf = ngx_http_vhost_traffic_status_display_prometheus_set_main(r, buf);
502531

src/ngx_http_vhost_traffic_status_display_prometheus.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
"# TYPE nginx_vts_server_bytes_total counter\n" \
3636
"# HELP nginx_vts_server_requests_total The requests counter\n" \
3737
"# TYPE nginx_vts_server_requests_total counter\n" \
38+
"# HELP nginx_vts_status_code_requests_total The requests counter by status code \n" \
39+
"# TYPE nginx_vts_status_code_requests_total counter\n" \
3840
"# HELP nginx_vts_server_request_seconds_total The request processing " \
3941
"time in seconds\n" \
4042
"# TYPE nginx_vts_server_request_seconds_total counter\n" \
@@ -56,6 +58,12 @@
5658
"nginx_vts_server_request_seconds_total{host=\"%V\"} %.3f\n" \
5759
"nginx_vts_server_request_seconds{host=\"%V\"} %.3f\n"
5860

61+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_PROMETHEUS_FMT_SERVER_OTHER_STATUS_CODE \
62+
"nginx_vts_status_code_requests_total{host=\"%V\",code=\"other\"} %uA\n"
63+
64+
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_PROMETHEUS_FMT_SERVER_STATUS_CODE \
65+
"nginx_vts_status_code_requests_total{host=\"%V\",code=\"%d\"} %uA\n"
66+
5967
#define NGX_HTTP_VHOST_TRAFFIC_STATUS_PROMETHEUS_FMT_SERVER_HISTOGRAM_BUCKET \
6068
"nginx_vts_server_request_duration_seconds_bucket{host=\"%V\"," \
6169
"le=\"%.3f\"} %uA\n"

src/ngx_http_vhost_traffic_status_module.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ static void ngx_http_vhost_traffic_status_rbtree_insert_value(
2121
ngx_rbtree_node_t *sentinel);
2222
static ngx_int_t ngx_http_vhost_traffic_status_init_zone(
2323
ngx_shm_zone_t *shm_zone, void *data);
24+
static char *ngx_http_vhost_traffic_status_measure_status_codes(ngx_conf_t *cf,
25+
ngx_command_t *cmd, void *conf);
2426
static char *ngx_http_vhost_traffic_status_zone(ngx_conf_t *cf,
2527
ngx_command_t *cmd, void *conf);
2628
static char *ngx_http_vhost_traffic_status_dump(ngx_conf_t *cf,
@@ -148,6 +150,13 @@ static ngx_command_t ngx_http_vhost_traffic_status_commands[] = {
148150
0,
149151
NULL },
150152

153+
{ ngx_string("vhost_traffic_status_measure_status_codes"),
154+
NGX_HTTP_MAIN_CONF|NGX_CONF_NOARGS|NGX_CONF_1MORE,
155+
ngx_http_vhost_traffic_status_measure_status_codes,
156+
0,
157+
0,
158+
NULL },
159+
151160
{ ngx_string("vhost_traffic_status_dump"),
152161
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
153162
ngx_http_vhost_traffic_status_dump,
@@ -475,6 +484,69 @@ ngx_http_vhost_traffic_status_init_zone(ngx_shm_zone_t *shm_zone, void *data)
475484
}
476485

477486

487+
static char *
488+
ngx_http_vhost_traffic_status_measure_status_codes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
489+
{
490+
ngx_http_vhost_traffic_status_ctx_t *ctx;
491+
ngx_str_t *value;
492+
ngx_int_t n;
493+
ngx_int_t previous_n;
494+
ngx_uint_t i;
495+
ngx_int_t *status_code;
496+
497+
ctx = ngx_http_conf_get_module_main_conf(cf, ngx_http_vhost_traffic_status_module);
498+
if (ctx == NULL) {
499+
return NGX_CONF_ERROR;
500+
}
501+
502+
ctx->measure_status_codes = ngx_array_create(cf->pool, 1, sizeof(ngx_int_t));
503+
previous_n = 0;
504+
value = cf->args->elts;
505+
506+
/* arguments process */
507+
if (ngx_strncmp(value[1].data, "all", 3) == 0) {
508+
for (n = 100; n < 600; n++) {
509+
status_code = ngx_array_push(ctx->measure_status_codes);
510+
if (status_code == NULL) {
511+
return NGX_CONF_ERROR;
512+
}
513+
*status_code = n;
514+
}
515+
ctx->measure_all_status_codes = 1;
516+
return NGX_OK;
517+
}
518+
for (i = 1; i < cf->args->nelts; i++) {
519+
n = ngx_atoi(value[i].data, value[i].len);
520+
if (n == NGX_ERROR || n == 0) {
521+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]);
522+
return NGX_CONF_ERROR;
523+
}
524+
525+
if (n < previous_n) {
526+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "status codes must be ordered");
527+
return NGX_CONF_ERROR;
528+
}
529+
530+
if (n < 100 || n > 599) {
531+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid status_code \"%V\"", &value[i]);
532+
return NGX_CONF_ERROR;
533+
}
534+
535+
status_code = ngx_array_push(ctx->measure_status_codes);
536+
if (status_code == NULL) {
537+
return NGX_CONF_ERROR;
538+
}
539+
540+
*status_code = n;
541+
previous_n = n;
542+
}
543+
544+
ctx->measure_all_status_codes = 0;
545+
546+
return NGX_CONF_OK;
547+
}
548+
549+
478550
static char *
479551
ngx_http_vhost_traffic_status_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
480552
{

src/ngx_http_vhost_traffic_status_module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ typedef struct {
265265
ngx_str_t dump_file;
266266
ngx_msec_t dump_period;
267267
ngx_event_t dump_event;
268+
269+
ngx_flag_t measure_all_status_codes;
270+
ngx_array_t *measure_status_codes;
268271
} ngx_http_vhost_traffic_status_ctx_t;
269272

270273

0 commit comments

Comments
 (0)