MINOR: stats: add by HTTP version cumulated number of sessions and requests
Add cum_sess_ver[] new array of counters to count the number of cumulated HTTP sessions by version (h1, h2 or h3). Implement proxy_inc_fe_cum_sess_ver_ctr() to increment these counter. This function is called each a HTTP mux is correctly initialized. The QUIC must before verify the application operations for the mux is for h3 before calling proxy_inc_fe_cum_sess_ver_ctr(). ST_F_SESS_OTHER stat field for the cumulated of sessions others than HTTP sessions is deduced from ->cum_sess_ver counter (for all the session, not only HTTP sessions) from which the HTTP sessions counters are substracted. Add cum_req[] new array of counters to count the number of cumulated HTTP requests by version and others than HTTP requests. This new member replace ->cum_req. Modify proxy_inc_fe_req_ctr() which increments these counters to pass an HTTP version, 0 special values meaning "other than an HTTP request". This is the case for instance for syslog.c from which proxy_inc_fe_req_ctr() is called with 0 as version parameter. ST_F_REQ_TOT stat field compputing for the cumulated number of requests is modified to count the sum of all the cum_req[] counters. As this patch is useful for QUIC, it must be backported to 2.7.
This commit is contained in:
parent
1ea5f410ff
commit
9969adbcdc
@ -28,6 +28,7 @@ struct fe_counters {
|
||||
unsigned int conn_max; /* max # of active sessions */
|
||||
long long cum_conn; /* cumulated number of received connections */
|
||||
long long cum_sess; /* cumulated number of accepted connections */
|
||||
long long cum_sess_ver[3]; /* cumulated number of h1/h2/h3 sessions */
|
||||
|
||||
unsigned int cps_max; /* maximum of new connections received per second */
|
||||
unsigned int sps_max; /* maximum of new connections accepted per second (sessions) */
|
||||
@ -53,7 +54,7 @@ struct fe_counters {
|
||||
|
||||
union {
|
||||
struct {
|
||||
long long cum_req; /* cumulated number of processed HTTP requests */
|
||||
long long cum_req[4]; /* cumulated number of processed other/h1/h2/h3 requests */
|
||||
long long comp_rsp; /* number of compressed responses */
|
||||
unsigned int rps_max; /* maximum of new HTTP requests second observed */
|
||||
long long rsp[6]; /* http response codes */
|
||||
|
@ -143,6 +143,21 @@ static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe)
|
||||
update_freq_ctr(&fe->fe_sess_per_sec, 1));
|
||||
}
|
||||
|
||||
/* increase the number of cumulated HTTP sessions on the designated frontend.
|
||||
* <http_ver> must be the HTTP version for such requests.
|
||||
*/
|
||||
static inline void proxy_inc_fe_cum_sess_ver_ctr(struct listener *l, struct proxy *fe,
|
||||
unsigned int http_ver)
|
||||
{
|
||||
if (http_ver == 0 ||
|
||||
http_ver > sizeof(fe->fe_counters.cum_sess_ver) / sizeof(*fe->fe_counters.cum_sess_ver))
|
||||
return;
|
||||
|
||||
_HA_ATOMIC_INC(&fe->fe_counters.cum_sess_ver[http_ver - 1]);
|
||||
if (l && l->counters)
|
||||
_HA_ATOMIC_INC(&l->counters->cum_sess_ver[http_ver - 1]);
|
||||
}
|
||||
|
||||
/* increase the number of cumulated connections on the designated backend */
|
||||
static inline void proxy_inc_be_ctr(struct proxy *be)
|
||||
{
|
||||
@ -151,12 +166,19 @@ static inline void proxy_inc_be_ctr(struct proxy *be)
|
||||
update_freq_ctr(&be->be_sess_per_sec, 1));
|
||||
}
|
||||
|
||||
/* increase the number of cumulated requests on the designated frontend */
|
||||
static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe)
|
||||
/* increase the number of cumulated requests on the designated frontend.
|
||||
* <http_ver> must be the HTTP version for HTTP request. 0 may be provided
|
||||
* for others requests.
|
||||
*/
|
||||
static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe,
|
||||
unsigned int http_ver)
|
||||
{
|
||||
_HA_ATOMIC_INC(&fe->fe_counters.p.http.cum_req);
|
||||
if (http_ver >= sizeof(fe->fe_counters.p.http.cum_req) / sizeof(*fe->fe_counters.p.http.cum_req))
|
||||
return;
|
||||
|
||||
_HA_ATOMIC_INC(&fe->fe_counters.p.http.cum_req[http_ver]);
|
||||
if (l && l->counters)
|
||||
_HA_ATOMIC_INC(&l->counters->p.http.cum_req);
|
||||
_HA_ATOMIC_INC(&l->counters->p.http.cum_req[http_ver]);
|
||||
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.p.http.rps_max,
|
||||
update_freq_ctr(&fe->fe_req_per_sec, 1));
|
||||
}
|
||||
|
@ -459,6 +459,14 @@ enum stat_field {
|
||||
ST_F_AGG_SRV_CHECK_STATUS,
|
||||
ST_F_AGG_CHECK_STATUS,
|
||||
ST_F_SRID,
|
||||
ST_F_SESS_OTHER,
|
||||
ST_F_H1SESS,
|
||||
ST_F_H2SESS,
|
||||
ST_F_H3SESS,
|
||||
ST_F_REQ_OTHER,
|
||||
ST_F_H1REQ,
|
||||
ST_F_H2REQ,
|
||||
ST_F_H3REQ,
|
||||
|
||||
/* must always be the last one */
|
||||
ST_F_TOTAL_FIELDS
|
||||
|
@ -94,6 +94,8 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
struct http_msg *msg = &txn->req;
|
||||
struct htx *htx;
|
||||
struct htx_sl *sl;
|
||||
char http_ver;
|
||||
int len;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn, msg);
|
||||
|
||||
@ -127,11 +129,22 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
}
|
||||
|
||||
htx = htxbuf(&req->buf);
|
||||
sl = http_get_stline(htx);
|
||||
len = HTX_SL_REQ_VLEN(sl);
|
||||
if (len < 6) {
|
||||
http_ver = 0;
|
||||
}
|
||||
else {
|
||||
char *ptr;
|
||||
|
||||
ptr = HTX_SL_REQ_VPTR(sl);
|
||||
http_ver = ptr[5] - '0';
|
||||
}
|
||||
|
||||
/* Parsing errors are caught here */
|
||||
if (htx->flags & (HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR)) {
|
||||
stream_inc_http_req_ctr(s);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, http_ver);
|
||||
if (htx->flags & HTX_FL_PARSING_ERROR) {
|
||||
stream_inc_http_err_ctr(s);
|
||||
goto return_bad_req;
|
||||
@ -145,13 +158,12 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
|
||||
msg->msg_state = HTTP_MSG_BODY;
|
||||
stream_inc_http_req_ctr(s);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe); /* one more valid request for this FE */
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, http_ver); /* one more valid request for this FE */
|
||||
|
||||
/* kill the pending keep-alive timeout */
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
|
||||
BUG_ON(htx_get_first_type(htx) != HTX_BLK_REQ_SL);
|
||||
sl = http_get_stline(htx);
|
||||
|
||||
/* 0: we might have to print this header in debug mode */
|
||||
if (unlikely((global.mode & MODE_DEBUG) &&
|
||||
|
@ -3546,7 +3546,7 @@ void syslog_fd_handler(int fd)
|
||||
|
||||
/* update counters */
|
||||
_HA_ATOMIC_INC(&cum_log_messages);
|
||||
proxy_inc_fe_req_ctr(l, l->bind_conf->frontend);
|
||||
proxy_inc_fe_req_ctr(l, l->bind_conf->frontend, 0);
|
||||
|
||||
parse_log_message(buf->area, buf->data, &level, &facility, metadata, &message, &size);
|
||||
|
||||
@ -3653,7 +3653,7 @@ static void syslog_io_handler(struct appctx *appctx)
|
||||
|
||||
/* update counters */
|
||||
_HA_ATOMIC_INC(&cum_log_messages);
|
||||
proxy_inc_fe_req_ctr(l, frontend);
|
||||
proxy_inc_fe_req_ctr(l, frontend, 0);
|
||||
|
||||
parse_log_message(buf->area, buf->data, &level, &facility, metadata, &message, &size);
|
||||
|
||||
|
10
src/mux_h1.c
10
src/mux_h1.c
@ -978,6 +978,8 @@ static int h1_init(struct connection *conn, struct proxy *proxy, struct session
|
||||
else if (h1_recv_allowed(h1c))
|
||||
h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
|
||||
|
||||
if (!conn_is_back(conn))
|
||||
proxy_inc_fe_cum_sess_ver_ctr(sess->listener, proxy, 1);
|
||||
HA_ATOMIC_INC(&h1c->px_counters->open_conns);
|
||||
HA_ATOMIC_INC(&h1c->px_counters->total_conns);
|
||||
|
||||
@ -2655,7 +2657,7 @@ static int h1_handle_internal_err(struct h1c *h1c)
|
||||
int ret = 0;
|
||||
|
||||
session_inc_http_req_ctr(sess);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, 1);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.p.http.rsp[5]);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.internal_errors);
|
||||
if (sess->listener && sess->listener->counters)
|
||||
@ -2685,7 +2687,7 @@ static int h1_handle_parsing_error(struct h1c *h1c)
|
||||
|
||||
session_inc_http_req_ctr(sess);
|
||||
session_inc_http_err_ctr(sess);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, 1);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.p.http.rsp[4]);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req);
|
||||
if (sess->listener && sess->listener->counters)
|
||||
@ -2717,7 +2719,7 @@ static int h1_handle_not_impl_err(struct h1c *h1c)
|
||||
}
|
||||
|
||||
session_inc_http_req_ctr(sess);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, 1);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.p.http.rsp[4]);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req);
|
||||
if (sess->listener && sess->listener->counters)
|
||||
@ -2747,7 +2749,7 @@ static int h1_handle_req_tout(struct h1c *h1c)
|
||||
}
|
||||
|
||||
session_inc_http_req_ctr(sess);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe);
|
||||
proxy_inc_fe_req_ctr(sess->listener, sess->fe, 1);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.p.http.rsp[4]);
|
||||
_HA_ATOMIC_INC(&sess->fe->fe_counters.failed_req);
|
||||
if (sess->listener && sess->listener->counters)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <haproxy/log.h>
|
||||
#include <haproxy/mux_h2-t.h>
|
||||
#include <haproxy/net_helper.h>
|
||||
#include <haproxy/proxy.h>
|
||||
#include <haproxy/session-t.h>
|
||||
#include <haproxy/stats.h>
|
||||
#include <haproxy/stconn.h>
|
||||
@ -1038,6 +1039,7 @@ static int h2_init(struct connection *conn, struct proxy *prx, struct session *s
|
||||
goto fail_stream;
|
||||
}
|
||||
|
||||
proxy_inc_fe_cum_sess_ver_ctr(sess->listener, prx, 2);
|
||||
HA_ATOMIC_INC(&h2c->px_counters->open_conns);
|
||||
HA_ATOMIC_INC(&h2c->px_counters->total_conns);
|
||||
|
||||
|
@ -5,9 +5,11 @@
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/connection.h>
|
||||
#include <haproxy/dynbuf.h>
|
||||
#include <haproxy/h3.h>
|
||||
#include <haproxy/list.h>
|
||||
#include <haproxy/ncbuf.h>
|
||||
#include <haproxy/pool.h>
|
||||
#include <haproxy/proxy.h>
|
||||
#include <haproxy/qmux_http.h>
|
||||
#include <haproxy/qmux_trace.h>
|
||||
#include <haproxy/quic_conn.h>
|
||||
@ -2208,6 +2210,9 @@ static int qc_init(struct connection *conn, struct proxy *prx,
|
||||
goto fail_install_app_ops;
|
||||
}
|
||||
|
||||
if (qcc->app_ops == &h3_ops)
|
||||
proxy_inc_fe_cum_sess_ver_ctr(sess->listener, prx, 3);
|
||||
|
||||
/* init read cycle */
|
||||
tasklet_wakeup(qcc->wait_event.tasklet);
|
||||
|
||||
|
90
src/stats.c
90
src/stats.c
@ -263,6 +263,14 @@ const struct name_desc stat_fields[ST_F_TOTAL_FIELDS] = {
|
||||
[ST_F_AGG_SRV_STATUS ] = { .name = "agg_server_status", .desc = "Backend's aggregated gauge of servers' status" },
|
||||
[ST_F_AGG_CHECK_STATUS] = { .name = "agg_check_status", .desc = "Backend's aggregated gauge of servers' state check status" },
|
||||
[ST_F_SRID] = { .name = "srid", .desc = "Server id revision, to prevent server id reuse mixups" },
|
||||
[ST_F_SESS_OTHER] = { .name = "sess_other", .desc = "Total number of sessions other than HTTP since process started" },
|
||||
[ST_F_H1SESS] = { .name = "h1sess", .desc = "Total number of HTTP/1 sessions since process started" },
|
||||
[ST_F_H2SESS] = { .name = "h2sess", .desc = "Total number of HTTP/2 sessions since process started" },
|
||||
[ST_F_H3SESS] = { .name = "h3sess", .desc = "Total number of HTTP/3 sessions since process started" },
|
||||
[ST_F_REQ_OTHER] = { .name = "req_other", .desc = "Total number of sessions other than HTTP processed by this object since the worker process started" },
|
||||
[ST_F_H1REQ] = { .name = "h1req", .desc = "Total number of HTTP/1 sessions processed by this object since the worker process started" },
|
||||
[ST_F_H2REQ] = { .name = "h2req", .desc = "Total number of hTTP/2 sessions processed by this object since the worker process started" },
|
||||
[ST_F_H3REQ] = { .name = "h3req", .desc = "Total number of HTTP/3 sessions processed by this object since the worker process started" },
|
||||
};
|
||||
|
||||
/* one line of info */
|
||||
@ -917,7 +925,27 @@ static int stats_dump_fields_html(struct buffer *out,
|
||||
/* http response (via hover): 1xx, 2xx, 3xx, 4xx, 5xx, other */
|
||||
if (strcmp(field_str(stats, ST_F_MODE), "http") == 0) {
|
||||
chunk_appendf(out,
|
||||
"<tr><th>- HTTP/1 sessions:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP/2 sessions:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP/3 sessions:</th><td>%s</td></tr>"
|
||||
"<tr><th>- other sessions:</th><td>%s</td></tr>"
|
||||
"<tr><th>Cum. HTTP requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP/1 requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP/2 requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP/3 requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>- other requests:</th><td>%s</td></tr>"
|
||||
"",
|
||||
U2H(stats[ST_F_H1SESS].u.u64),
|
||||
U2H(stats[ST_F_H2SESS].u.u64),
|
||||
U2H(stats[ST_F_H3SESS].u.u64),
|
||||
U2H(stats[ST_F_SESS_OTHER].u.u64),
|
||||
U2H(stats[ST_F_REQ_TOT].u.u64),
|
||||
U2H(stats[ST_F_H1REQ].u.u64),
|
||||
U2H(stats[ST_F_H2REQ].u.u64),
|
||||
U2H(stats[ST_F_H3REQ].u.u64),
|
||||
U2H(stats[ST_F_REQ_OTHER].u.u64));
|
||||
|
||||
chunk_appendf(out,
|
||||
"<tr><th>- HTTP 1xx responses:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP 2xx responses:</th><td>%s</td></tr>"
|
||||
"<tr><th> Compressed 2xx:</th><td>%s</td><td>(%d%%)</td></tr>"
|
||||
@ -925,13 +953,7 @@ static int stats_dump_fields_html(struct buffer *out,
|
||||
"<tr><th>- HTTP 4xx responses:</th><td>%s</td></tr>"
|
||||
"<tr><th>- HTTP 5xx responses:</th><td>%s</td></tr>"
|
||||
"<tr><th>- other responses:</th><td>%s</td></tr>"
|
||||
"<tr><th>Intercepted requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>Cache lookups:</th><td>%s</td></tr>"
|
||||
"<tr><th>Cache hits:</th><td>%s</td><td>(%d%%)</td></tr>"
|
||||
"<tr><th>Failed hdr rewrites:</th><td>%s</td></tr>"
|
||||
"<tr><th>Internal errors:</th><td>%s</td></tr>"
|
||||
"",
|
||||
U2H(stats[ST_F_REQ_TOT].u.u64),
|
||||
U2H(stats[ST_F_HRSP_1XX].u.u64),
|
||||
U2H(stats[ST_F_HRSP_2XX].u.u64),
|
||||
U2H(stats[ST_F_COMP_RSP].u.u64),
|
||||
@ -940,7 +962,15 @@ static int stats_dump_fields_html(struct buffer *out,
|
||||
U2H(stats[ST_F_HRSP_3XX].u.u64),
|
||||
U2H(stats[ST_F_HRSP_4XX].u.u64),
|
||||
U2H(stats[ST_F_HRSP_5XX].u.u64),
|
||||
U2H(stats[ST_F_HRSP_OTHER].u.u64),
|
||||
U2H(stats[ST_F_HRSP_OTHER].u.u64));
|
||||
|
||||
chunk_appendf(out,
|
||||
"<tr><th>Intercepted requests:</th><td>%s</td></tr>"
|
||||
"<tr><th>Cache lookups:</th><td>%s</td></tr>"
|
||||
"<tr><th>Cache hits:</th><td>%s</td><td>(%d%%)</td></tr>"
|
||||
"<tr><th>Failed hdr rewrites:</th><td>%s</td></tr>"
|
||||
"<tr><th>Internal errors:</th><td>%s</td></tr>"
|
||||
"",
|
||||
U2H(stats[ST_F_INTERCEPTED].u.u64),
|
||||
U2H(stats[ST_F_CACHE_LOOKUPS].u.u64),
|
||||
U2H(stats[ST_F_CACHE_HITS].u.u64),
|
||||
@ -1805,9 +1835,18 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len,
|
||||
case ST_F_REQ_RATE_MAX:
|
||||
metric = mkf_u32(FN_MAX, px->fe_counters.p.http.rps_max);
|
||||
break;
|
||||
case ST_F_REQ_TOT:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.p.http.cum_req);
|
||||
case ST_F_REQ_TOT: {
|
||||
int i;
|
||||
uint64_t total_req;
|
||||
size_t nb_reqs =
|
||||
sizeof(px->fe_counters.p.http.cum_req) / sizeof(*px->fe_counters.p.http.cum_req);
|
||||
|
||||
total_req = 0;
|
||||
for (i = 0; i < nb_reqs; i++)
|
||||
total_req += px->fe_counters.p.http.cum_req[i];
|
||||
metric = mkf_u64(FN_COUNTER, total_req);
|
||||
break;
|
||||
}
|
||||
case ST_F_COMP_IN:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.comp_in);
|
||||
break;
|
||||
@ -1829,6 +1868,39 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len,
|
||||
case ST_F_CONN_TOT:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.cum_conn);
|
||||
break;
|
||||
case ST_F_SESS_OTHER: {
|
||||
int i;
|
||||
uint64_t total_sess;
|
||||
size_t nb_sess =
|
||||
sizeof(px->fe_counters.cum_sess_ver) / sizeof(*px->fe_counters.cum_sess_ver);
|
||||
|
||||
total_sess = px->fe_counters.cum_sess;
|
||||
for (i = 0; i < nb_sess; i++)
|
||||
total_sess -= px->fe_counters.cum_sess_ver[i];
|
||||
metric = mkf_u64(FN_COUNTER, total_sess);
|
||||
break;
|
||||
}
|
||||
case ST_F_H1SESS:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.cum_sess_ver[0]);
|
||||
break;
|
||||
case ST_F_H2SESS:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.cum_sess_ver[1]);
|
||||
break;
|
||||
case ST_F_H3SESS:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.cum_sess_ver[2]);
|
||||
break;
|
||||
case ST_F_REQ_OTHER:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.p.http.cum_req[0]);
|
||||
break;
|
||||
case ST_F_H1REQ:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.p.http.cum_req[1]);
|
||||
break;
|
||||
case ST_F_H2REQ:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.p.http.cum_req[2]);
|
||||
break;
|
||||
case ST_F_H3REQ:
|
||||
metric = mkf_u64(FN_COUNTER, px->fe_counters.p.http.cum_req[3]);
|
||||
break;
|
||||
default:
|
||||
/* not used for frontends. If a specific metric
|
||||
* is requested, return an error. Otherwise continue.
|
||||
|
Loading…
Reference in New Issue
Block a user