ngx_http_stub_status_module.c revision e18a033b
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12
13static ngx_int_t ngx_http_stub_status_handler(ngx_http_request_t *r);
14static ngx_int_t ngx_http_stub_status_variable(ngx_http_request_t *r,
15    ngx_http_variable_value_t *v, uintptr_t data);
16static ngx_int_t ngx_http_stub_status_add_variables(ngx_conf_t *cf);
17static char *ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd,
18    void *conf);
19
20
21static ngx_command_t  ngx_http_status_commands[] = {
22
23    { ngx_string("stub_status"),
24      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
25      ngx_http_set_stub_status,
26      0,
27      0,
28      NULL },
29
30      ngx_null_command
31};
32
33
34static ngx_http_module_t  ngx_http_stub_status_module_ctx = {
35    ngx_http_stub_status_add_variables,    /* preconfiguration */
36    NULL,                                  /* postconfiguration */
37
38    NULL,                                  /* create main configuration */
39    NULL,                                  /* init main configuration */
40
41    NULL,                                  /* create server configuration */
42    NULL,                                  /* merge server configuration */
43
44    NULL,                                  /* create location configuration */
45    NULL                                   /* merge location configuration */
46};
47
48
49ngx_module_t  ngx_http_stub_status_module = {
50    NGX_MODULE_V1,
51    &ngx_http_stub_status_module_ctx,      /* module context */
52    ngx_http_status_commands,              /* module directives */
53    NGX_HTTP_MODULE,                       /* module type */
54    NULL,                                  /* init master */
55    NULL,                                  /* init module */
56    NULL,                                  /* init process */
57    NULL,                                  /* init thread */
58    NULL,                                  /* exit thread */
59    NULL,                                  /* exit process */
60    NULL,                                  /* exit master */
61    NGX_MODULE_V1_PADDING
62};
63
64
65static ngx_http_variable_t  ngx_http_stub_status_vars[] = {
66
67    { ngx_string("connections_active"), NULL, ngx_http_stub_status_variable,
68      0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
69
70    { ngx_string("connections_reading"), NULL, ngx_http_stub_status_variable,
71      1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
72
73    { ngx_string("connections_writing"), NULL, ngx_http_stub_status_variable,
74      2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
75
76    { ngx_string("connections_waiting"), NULL, ngx_http_stub_status_variable,
77      3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
78
79    { ngx_null_string, NULL, NULL, 0, 0, 0 }
80};
81
82
83static ngx_int_t
84ngx_http_stub_status_handler(ngx_http_request_t *r)
85{
86    size_t             size;
87    ngx_int_t          rc;
88    ngx_buf_t         *b;
89    ngx_chain_t        out;
90    ngx_atomic_int_t   ap, hn, ac, rq, rd, wr, wa;
91
92    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
93        return NGX_HTTP_NOT_ALLOWED;
94    }
95
96    rc = ngx_http_discard_request_body(r);
97
98    if (rc != NGX_OK) {
99        return rc;
100    }
101
102    r->headers_out.content_type_len = sizeof("text/plain") - 1;
103    ngx_str_set(&r->headers_out.content_type, "text/plain");
104    r->headers_out.content_type_lowcase = NULL;
105
106    if (r->method == NGX_HTTP_HEAD) {
107        r->headers_out.status = NGX_HTTP_OK;
108
109        rc = ngx_http_send_header(r);
110
111        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
112            return rc;
113        }
114    }
115
116    size = sizeof("Active connections:  \n") + NGX_ATOMIC_T_LEN
117           + sizeof("server accepts handled requests\n") - 1
118           + 6 + 3 * NGX_ATOMIC_T_LEN
119           + sizeof("Reading:  Writing:  Waiting:  \n") + 3 * NGX_ATOMIC_T_LEN;
120
121    b = ngx_create_temp_buf(r->pool, size);
122    if (b == NULL) {
123        return NGX_HTTP_INTERNAL_SERVER_ERROR;
124    }
125
126    out.buf = b;
127    out.next = NULL;
128
129    ap = *ngx_stat_accepted;
130    hn = *ngx_stat_handled;
131    ac = *ngx_stat_active;
132    rq = *ngx_stat_requests;
133    rd = *ngx_stat_reading;
134    wr = *ngx_stat_writing;
135    wa = *ngx_stat_waiting;
136
137    b->last = ngx_sprintf(b->last, "Active connections: %uA \n", ac);
138
139    b->last = ngx_cpymem(b->last, "server accepts handled requests\n",
140                         sizeof("server accepts handled requests\n") - 1);
141
142    b->last = ngx_sprintf(b->last, " %uA %uA %uA \n", ap, hn, rq);
143
144    b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA \n",
145                          rd, wr, wa);
146
147    r->headers_out.status = NGX_HTTP_OK;
148    r->headers_out.content_length_n = b->last - b->pos;
149
150    b->last_buf = (r == r->main) ? 1 : 0;
151    b->last_in_chain = 1;
152
153    rc = ngx_http_send_header(r);
154
155    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
156        return rc;
157    }
158
159    return ngx_http_output_filter(r, &out);
160}
161
162
163static ngx_int_t
164ngx_http_stub_status_variable(ngx_http_request_t *r,
165    ngx_http_variable_value_t *v, uintptr_t data)
166{
167    u_char            *p;
168    ngx_atomic_int_t   value;
169
170    p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
171    if (p == NULL) {
172        return NGX_ERROR;
173    }
174
175    switch (data) {
176    case 0:
177        value = *ngx_stat_active;
178        break;
179
180    case 1:
181        value = *ngx_stat_reading;
182        break;
183
184    case 2:
185        value = *ngx_stat_writing;
186        break;
187
188    case 3:
189        value = *ngx_stat_waiting;
190        break;
191
192    /* suppress warning */
193    default:
194        value = 0;
195        break;
196    }
197
198    v->len = ngx_sprintf(p, "%uA", value) - p;
199    v->valid = 1;
200    v->no_cacheable = 0;
201    v->not_found = 0;
202    v->data = p;
203
204    return NGX_OK;
205}
206
207
208static ngx_int_t
209ngx_http_stub_status_add_variables(ngx_conf_t *cf)
210{
211    ngx_http_variable_t  *var, *v;
212
213    for (v = ngx_http_stub_status_vars; v->name.len; v++) {
214        var = ngx_http_add_variable(cf, &v->name, v->flags);
215        if (var == NULL) {
216            return NGX_ERROR;
217        }
218
219        var->get_handler = v->get_handler;
220        var->data = v->data;
221    }
222
223    return NGX_OK;
224}
225
226
227static char *
228ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
229{
230    ngx_http_core_loc_conf_t  *clcf;
231
232    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
233    clcf->handler = ngx_http_stub_status_handler;
234
235    return NGX_CONF_OK;
236}
237