From: Willy Tarreau Date: Thu, 23 May 2019 09:39:14 +0000 (+0200) Subject: MINOR: raw_sock: report global traffic statistics X-Git-Tag: v2.0-dev5~89 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cf0e4517;p=thirdparty%2Fhaproxy.git MINOR: raw_sock: report global traffic statistics 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. --- diff --git a/include/types/global.h b/include/types/global.h index 2959da8dd9..a87b40722f 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -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; diff --git a/include/types/stats.h b/include/types/stats.h index 648b03241d..5a7aa98134 100644 --- a/include/types/stats.h +++ b/include/types/stats.h @@ -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 diff --git a/src/raw_sock.c b/src/raw_sock.c index 1090dfc673..a83cc3fcb5 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -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; } diff --git a/src/stats.c b/src/stats.c index 0fef816505..cba9ffcd53 100644 --- a/src/stats.c +++ b/src/stats.c @@ -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; }