From bd7151002437af1a034a9fdbb582b3cbef5a78d1 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 23 Oct 2020 22:44:30 +0200 Subject: [PATCH] MINOR: stats: report server's user-configured weight next to effective weight The "weight" column on the stats page is somewhat confusing when using slowstart becaue it reports the effective weight, without being really explicit about it. In some situations the user-configured weight is more relevant (especially with long slowstarts where it's important to know if the configured weight is correct). This adds a new uweight stat which reports a server's user-configured weight, and in a backend it receives the sum of all servers' uweights. In addition it adds the mention of "effective" in a few descriptions for the "weight" column (help and doc). As a result, the list of servers in a backend is now always scanned when dumping the stats. But this is not a problem given that these servers are already scanned anyway and for way heavier processing. --- doc/management.txt | 3 ++- include/haproxy/backend-t.h | 3 ++- include/haproxy/stats-t.h | 1 + src/stats.c | 34 +++++++++++++++++++++++----------- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index 3031420be..308e725d4 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1009,7 +1009,7 @@ Here is the list of static fields using the proxy statistics domain: server. The server value counts the number of times that server was switched away from. 17. status [LFBS]: status (UP/DOWN/NOLB/MAINT/MAINT(via)/MAINT(resolution)...) - 18. weight [..BS]: total weight (backend), server weight (server) + 18. weight [..BS]: total effective weight (backend), effective weight (server) 19. act [..BS]: number of active servers (backend), server is active (server) 20. bck [..BS]: number of backup servers (backend), server is backup (server) 21. chkfail [...S]: number of failed checks. (Only counts checks failed when @@ -1130,6 +1130,7 @@ Here is the list of static fields using the proxy statistics domain: 96. safe_conn_cur [...S]: current number of safe idle connections 97. used_conn_cur [...S]: current number of connections in use 98. need_conn_est [...S]: estimated needed number of connections + 99. uweight [..BS]: total user weight (backend), server user weight (server) For all other statistics domains, the presence or the order of the fields are not guaranteed. In this case, the header line should always be used to parse diff --git a/include/haproxy/backend-t.h b/include/haproxy/backend-t.h index bb8ec6f55..3e3024033 100644 --- a/include/haproxy/backend-t.h +++ b/include/haproxy/backend-t.h @@ -147,6 +147,7 @@ struct lbprm { int algo; /* load balancing algorithm and variants: BE_LB_* */ int tot_wact, tot_wbck; /* total effective weights of active and backup servers */ int tot_weight; /* total effective weight of servers participating to LB */ + int tot_uweight; /* total user weight of servers participating to LB (for reporting) */ int tot_used; /* total number of servers used for LB */ int wmult; /* ratio between user weight and effective weight */ int wdiv; /* ratio between effective weight and user weight */ @@ -156,8 +157,8 @@ struct lbprm { int arg_opt1; /* extra option 1 for the LB algo (algo-specific) */ int arg_opt2; /* extra option 2 for the LB algo (algo-specific) */ int arg_opt3; /* extra option 3 for the LB algo (algo-specific) */ - struct server *fbck; /* first backup server when !PR_O_USE_ALL_BK, or NULL */ __decl_thread(HA_RWLOCK_T lock); + struct server *fbck; /* first backup server when !PR_O_USE_ALL_BK, or NULL */ /* Call backs for some actions. Any of them may be NULL (thus should be ignored). */ void (*update_server_eweight)(struct server *); /* to be called after eweight change */ diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 8b69a0bf8..af9b9711d 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -434,6 +434,7 @@ enum stat_field { ST_F_SAFE_CONN_CUR, ST_F_USED_CONN_CUR, ST_F_NEED_CONN_EST, + ST_F_UWEIGHT, /* must always be the last one */ ST_F_TOTAL_FIELDS diff --git a/src/stats.c b/src/stats.c index a332e7cc7..82e2b1f6d 100644 --- a/src/stats.c +++ b/src/stats.c @@ -169,7 +169,7 @@ const struct name_desc stat_fields[ST_F_TOTAL_FIELDS] = { [ST_F_WRETR] = { .name = "wretr", .desc = "Total number of server connection retries since the worker process started" }, [ST_F_WREDIS] = { .name = "wredis", .desc = "Total number of server redispatches due to connection failures since the worker process started" }, [ST_F_STATUS] = { .name = "status", .desc = "Frontend/listen status: OPEN/WAITING/FULL/STOP; backend: UP/DOWN; server: last check status" }, - [ST_F_WEIGHT] = { .name = "weight", .desc = "Server weight, or sum of active servers' weights for a backend" }, + [ST_F_WEIGHT] = { .name = "weight", .desc = "Server's effective weight, or sum of active servers' effective weights for a backend" }, [ST_F_ACT] = { .name = "act", .desc = "Total number of active UP servers with a non-zero weight" }, [ST_F_BCK] = { .name = "bck", .desc = "Total number of backup UP servers with a non-zero weight" }, [ST_F_CHKFAIL] = { .name = "chkfail", .desc = "Total number of failed individual health checks per server/backend, since the worker process started" }, @@ -250,6 +250,7 @@ const struct name_desc stat_fields[ST_F_TOTAL_FIELDS] = { [ST_F_SAFE_CONN_CUR] = { .name = "safe_conn_cur", .desc = "Current number of safe idle connections"}, [ST_F_USED_CONN_CUR] = { .name = "used_conn_cur", .desc = "Current number of connections in use"}, [ST_F_NEED_CONN_EST] = { .name = "need_conn_est", .desc = "Estimated needed number of connections"}, + [ST_F_UWEIGHT] = { .name = "uweight", .desc = "Server's user weight, or sum of active servers' user weights for a backend" }, }; /* one line of info */ @@ -1327,12 +1328,12 @@ static int stats_dump_fields_html(struct buffer *out, chunk_appendf(out, ""); chunk_appendf(out, - /* weight */ - "%d" + /* weight / uweight */ + "%d/%d" /* act, bck */ "%s%s" "", - stats[ST_F_WEIGHT].u.u32, + stats[ST_F_WEIGHT].u.u32, stats[ST_F_UWEIGHT].u.u32, stats[ST_F_BCK].u.u32 ? "-" : "Y", stats[ST_F_BCK].u.u32 ? "Y" : "-"); @@ -1537,7 +1538,7 @@ static int stats_dump_fields_html(struct buffer *out, * if the backend has known working servers or if it has no server at * all (eg: for stats). Then we display the total weight, number of * active and backups. */ - "%s %s %d" + "%s %s %d/%d" "%d%d" "", U2H(stats[ST_F_DREQ].u.u64), U2H(stats[ST_F_DRESP].u.u64), @@ -1548,7 +1549,7 @@ static int stats_dump_fields_html(struct buffer *out, (long long)stats[ST_F_WRETR].u.u64, (long long)stats[ST_F_WREDIS].u.u64, human_time(stats[ST_F_LASTCHG].u.u32, 1), strcmp(field_str(stats, ST_F_STATUS), "DOWN") ? field_str(stats, ST_F_STATUS) : "DOWN", - stats[ST_F_WEIGHT].u.u32, + stats[ST_F_WEIGHT].u.u32, stats[ST_F_UWEIGHT].u.u32, stats[ST_F_ACT].u.u32, stats[ST_F_BCK].u.u32); chunk_appendf(out, @@ -1963,6 +1964,7 @@ int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags, stats[ST_F_STATUS] = mkf_str(FO_STATUS, fld_status); stats[ST_F_LASTCHG] = mkf_u32(FN_AGE, now.tv_sec - sv->last_change); stats[ST_F_WEIGHT] = mkf_u32(FN_AVG, (sv->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv); + stats[ST_F_UWEIGHT] = mkf_u32(FN_AVG, sv->uweight); stats[ST_F_ACT] = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 0 : 1); stats[ST_F_BCK] = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 1 : 0); @@ -2151,20 +2153,29 @@ int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int le struct buffer *out = get_trash_chunk(); const struct server *srv; int nbup, nbsrv; + int totuw; char *fld; if (len < ST_F_TOTAL_FIELDS) return 0; + totuw = 0; nbup = nbsrv = 0; - if (flags & (STAT_HIDE_MAINT|STAT_HIDE_DOWN)) { - for (srv = px->srv; srv; srv = srv->next) { - if (srv->cur_state != SRV_ST_STOPPED) - nbup++; - nbsrv++; + for (srv = px->srv; srv; srv = srv->next) { + if (srv->cur_state != SRV_ST_STOPPED) { + nbup++; + if (srv_currently_usable(srv) && + (!px->srv_act ^ !(srv->flags & SRV_F_BACKUP))) + totuw += srv->uweight; } + nbsrv++; } + HA_RWLOCK_RDLOCK(LBPRM_LOCK, &px->lbprm.lock); + if (!px->srv_act && px->lbprm.fbck) + totuw = px->lbprm.fbck->uweight; + HA_RWLOCK_RDUNLOCK(LBPRM_LOCK, &px->lbprm.lock); + stats[ST_F_PXNAME] = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id); stats[ST_F_SVNAME] = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, "BACKEND"); stats[ST_F_MODE] = mkf_str(FO_CONFIG|FS_SERVICE, proxy_mode_str(px->mode)); @@ -2194,6 +2205,7 @@ int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int le stats[ST_F_STATUS] = mkf_str(FO_STATUS, fld); stats[ST_F_WEIGHT] = mkf_u32(FN_AVG, (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv); + stats[ST_F_UWEIGHT] = mkf_u32(FN_AVG, totuw); stats[ST_F_ACT] = mkf_u32(0, px->srv_act); stats[ST_F_BCK] = mkf_u32(0, px->srv_bck); stats[ST_F_CHKDOWN] = mkf_u64(FN_COUNTER, px->down_trans);