]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: add by HTTP version cumulated number of sessions and requests
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 18 Jan 2023 10:52:21 +0000 (11:52 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 3 Feb 2023 16:55:49 +0000 (17:55 +0100)
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.

include/haproxy/counters-t.h
include/haproxy/proxy.h
include/haproxy/stats-t.h
src/http_ana.c
src/log.c
src/mux_h1.c
src/mux_h2.c
src/mux_quic.c
src/stats.c

index 1ea68dd6c3b0b7b02129a2240188eb7676f9abef..849f0968389beda14a56e93e980b3e094ef81789 100644 (file)
@@ -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 */
index 01971531b7561bf0fa443711aae3ade4541ad184..27a7ae861e57dde88e102d5ae84969b0832b80f9 100644 (file)
@@ -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));
 }
index 9cc1d33a9f20f5b355f35bf2d84d8d7464fe348e..5a46d30dfaa993b122ac245e4ae0af7deb13d743 100644 (file)
@@ -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
index 4f1decdbbd4c7b5c77fcefad76adfc62f602e8f5..8cee6f91225cd425eb16a6d7cff586b83d80b779 100644 (file)
@@ -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) &&
index 3fbae30fc88178968f13ff6fd5d56e4031f1a4b1..fc4cdd9cbac97c70f55a40b8a1d7827c7486a41d 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -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);
 
index ce51f43a7091a159964dce6aa4b6fd92e07b9e61..1dea69937d26f2b1e31c4c878502b02171194aa1 100644 (file)
@@ -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)
index 4c5171a0bdc3dc857c37d9db58e4fce82ec979a6..bc82cb3f8ea008a98894a67d0bfc1cceedac83ec 100644 (file)
@@ -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);
 
index 1060635d241eb414f460629b64eb4575ed40d6f6..26006fb66789a7e605de33fbeff53bb4426530aa 100644 (file)
@@ -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);
 
index 5e3dfbe5c9dbe9880a313b5cf1b2936f3e96ccd0..4a1dca2f214a8b32b5b9c3726e0caabb870847fe 100644 (file)
@@ -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>&nbsp;&nbsp;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.