]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: raw_sock: report global traffic statistics
authorWilly Tarreau <w@1wt.eu>
Thu, 23 May 2019 09:39:14 +0000 (11:39 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 23 May 2019 09:45:38 +0000 (11:45 +0200)
Many times we've been missing per-process traffic statistics. While it
didn't make sense in multi-process mode, with threads it does. Thus we
now have a counter of bytes emitted by raw_sock, and a freq counter for
these as well. However, freq_ctr are limited to 32 bits, and given that
loads of 300 Gbps have already been reached over a loopback using
splicing, we need to downscale this a bit. Here we're storing 1/32 of
the byte rate, which gives a theorical limit of 128 GB/s or ~1 Tbps,
which is more than enough. Let's have fun re-reading this sentence in
2029 :-)  The values can be read in "show info" output on the CLI.

include/types/global.h
include/types/stats.h
src/raw_sock.c
src/stats.c

index 2959da8dd9885a71a451fd6890412b433a4c4c5a..a87b40722f192d33a501bc4e8f14edb3b278e932 100644 (file)
@@ -115,6 +115,8 @@ struct global {
        struct freq_ctr ssl_be_keys_per_sec;
        struct freq_ctr comp_bps_in;    /* bytes per second, before http compression */
        struct freq_ctr comp_bps_out;   /* bytes per second, after http compression */
+       struct freq_ctr out_32bps;      /* #of 32-byte blocks emitted per second */
+       unsigned long long out_bytes;   /* total #of bytes emitted */
        int cps_lim, cps_max;
        int sps_lim, sps_max;
        int ssl_lim, ssl_max;
index 648b03241dfc0455b339ca3f47026f24552d6b28..5a7aa981347e9df62dbbeacc86743ac5c7fcacfb 100644 (file)
@@ -313,6 +313,8 @@ enum info_field {
        INF_DROPPED_LOGS,
        INF_BUSY_POLLING,
        INF_FAILED_RESOLUTIONS,
+       INF_TOTAL_BYTES_OUT,
+       INF_BYTES_OUT_RATE,
 
        /* must always be the last one */
        INF_TOTAL_FIELDS
index 1090dfc673dbf0f76bb93b0ddd543037b676b978..a83cc3fcb536e0b093bb01c979e77419cb64d458 100644 (file)
@@ -158,6 +158,14 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe,
 
  leave:
        conn_cond_update_sock_polling(conn);
+       if (retval > 0) {
+               /* we count the total bytes sent, and the send rate for 32-byte
+                * blocks. The reason for the latter is that freq_ctr are
+                * limited to 4GB and that it's not enough per second.
+                */
+               _HA_ATOMIC_ADD(&global.out_bytes, retval);
+               update_freq_ctr(&global.out_32bps, (retval + 16) / 32);
+       }
        return retval;
 
  out_read0:
@@ -386,6 +394,14 @@ static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const s
                conn->flags &= ~CO_FL_WAIT_L4_CONN;
 
        conn_cond_update_sock_polling(conn);
+       if (done > 0) {
+               /* we count the total bytes sent, and the send rate for 32-byte
+                * blocks. The reason for the latter is that freq_ctr are
+                * limited to 4GB and that it's not enough per second.
+                */
+               _HA_ATOMIC_ADD(&global.out_bytes, done);
+               update_freq_ctr(&global.out_32bps, (done + 16) / 32);
+       }
        return done;
 }
 
index 0fef81650502e6c9b55aa647868be1d01d533257..cba9ffcd53fa164149d2ac549cc2261d20778aa1 100644 (file)
@@ -152,6 +152,8 @@ const char *info_field_names[INF_TOTAL_FIELDS] = {
        [INF_DROPPED_LOGS]                   = "DroppedLogs",
        [INF_BUSY_POLLING]                   = "BusyPolling",
        [INF_FAILED_RESOLUTIONS]             = "FailedResolutions",
+       [INF_TOTAL_BYTES_OUT]                = "TotalBytesOut",
+       [INF_BYTES_OUT_RATE]                 = "BytesOutRate",
 };
 
 const char *stat_field_names[ST_F_TOTAL_FIELDS] = {
@@ -3656,6 +3658,8 @@ int stats_fill_info(struct field *info, int len)
        info[INF_DROPPED_LOGS]                   = mkf_u32(0, dropped_logs);
        info[INF_BUSY_POLLING]                   = mkf_u32(0, !!(global.tune.options & GTUNE_BUSY_POLLING));
        info[INF_FAILED_RESOLUTIONS]             = mkf_u32(0, dns_failed_resolutions);
+       info[INF_TOTAL_BYTES_OUT]                = mkf_u64(0, global.out_bytes);
+       info[INF_BYTES_OUT_RATE]                 = mkf_u64(FN_RATE, (unsigned long long)read_freq_ctr(&global.out_32bps) * 32);
 
        return 1;
 }