Re: [PATCH v2 1/4] MEDIUM: stats: allow to select one field in `stats_fill_be_stats`

2021-01-26 Thread Christopher Faulet

Le 25/01/2021 à 17:29, William Dauchy a écrit :

prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
This patch follows what has already been done on frontend side.
 From this patch it should be possible to remove most of the duplicate
code on prometheuse side for the backend

A few things to note though:
- status and uweight field requires prior compute, so I moved that to a
   sort of helper `stats_fill_be_stats_computesrv`.
- all ST_F*TIME fields requires some minor compute, so I moved it at te
   beginning of the function under a condition.

Signed-off-by: William Dauchy 
---


The series is merged now. Thanks William !

--
Christopher Faulet



[PATCH v2 1/4] MEDIUM: stats: allow to select one field in `stats_fill_be_stats`

2021-01-25 Thread William Dauchy
prometheus approach requires to output all values for a given metric
name; meaning we iterate through all metrics, and then iterate in the
inner loop on all objects for this metric.
In order to allow more code reuse, adapt the stats API to be able to
select one field or fill them all otherwise.
This patch follows what has already been done on frontend side.
>From this patch it should be possible to remove most of the duplicate
code on prometheuse side for the backend

A few things to note though:
- status and uweight field requires prior compute, so I moved that to a
  sort of helper `stats_fill_be_stats_computesrv`.
- all ST_F*TIME fields requires some minor compute, so I moved it at te
  beginning of the function under a condition.

Signed-off-by: William Dauchy 
---
 include/haproxy/stats.h |   3 +-
 src/hlua_fcn.c  |   2 +-
 src/stats.c | 368 
 3 files changed, 266 insertions(+), 107 deletions(-)

diff --git a/include/haproxy/stats.h b/include/haproxy/stats.h
index 8210367ac..6c04f2761 100644
--- a/include/haproxy/stats.h
+++ b/include/haproxy/stats.h
@@ -52,7 +52,8 @@ int stats_fill_li_stats(struct proxy *px, struct listener *l, 
int flags,
 struct field *stats, int len);
 int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags,
 struct field *stats, int len);
-int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int 
len);
+int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int 
len,
+   enum stat_field *selected_field);
 
 void stats_io_handler(struct stream_interface *si);
 int stats_emit_raw_data_field(struct buffer *out, const struct field *f);
diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c
index aab864370..d13c5344f 100644
--- a/src/hlua_fcn.c
+++ b/src/hlua_fcn.c
@@ -1341,7 +1341,7 @@ int hlua_proxy_get_stats(lua_State *L)
 
px = hlua_check_proxy(L, 1);
if (px->cap & PR_CAP_BE)
-   stats_fill_be_stats(px, STAT_SHLGNDS, stats, STATS_LEN);
+   stats_fill_be_stats(px, STAT_SHLGNDS, stats, STATS_LEN, NULL);
else
stats_fill_fe_stats(px, stats, STATS_LEN, NULL);
lua_newtable(L);
diff --git a/src/stats.c b/src/stats.c
index dcb99f674..949b8f696 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -2260,130 +2260,288 @@ static int stats_dump_sv_stats(struct 
stream_interface *si, struct proxy *px, st
return stats_dump_one_line(stats, stats_count, appctx);
 }
 
-/* Fill  with the backend statistics.  is
- * preallocated array of length . The length of the array
- * must be at least ST_F_TOTAL_FIELDS. If this length is less
- * then this value, the function returns 0, otherwise, it
- * returns 1.  can take the value STAT_SHLGNDS.
+/* Helper to compute srv values for a given backend
  */
-int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int 
len)
+static void stats_fill_be_stats_computesrv(struct proxy *px, int *nbup, int 
*nbsrv, int *totuw)
 {
-   long long be_samples_counter;
-   unsigned int be_samples_window = TIME_STATS_SAMPLES;
-   struct buffer *out = get_trash_chunk();
+   int nbup_tmp, nbsrv_tmp, totuw_tmp;
const struct server *srv;
-   int nbup, nbsrv;
-   int totuw;
-   char *fld;
-
-   if (len < ST_F_TOTAL_FIELDS)
-   return 0;
 
-   totuw = 0;
-   nbup = nbsrv = 0;
+   nbup_tmp = nbsrv_tmp = totuw_tmp = 0;
for (srv = px->srv; srv; srv = srv->next) {
if (srv->cur_state != SRV_ST_STOPPED) {
-   nbup++;
+   nbup_tmp++;
if (srv_currently_usable(srv) &&
(!px->srv_act ^ !(srv->flags & SRV_F_BACKUP)))
-   totuw += srv->uweight;
+   totuw_tmp += srv->uweight;
}
-   nbsrv++;
+   nbsrv_tmp++;
}
 
HA_RWLOCK_RDLOCK(LBPRM_LOCK, &px->lbprm.lock);
if (!px->srv_act && px->lbprm.fbck)
-   totuw = px->lbprm.fbck->uweight;
+   totuw_tmp = 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));
-   stats[ST_F_QCUR] = mkf_u32(0, px->nbpend);
-   stats[ST_F_QMAX] = mkf_u32(FN_MAX, px->be_counters.nbpend_max);
-   stats[ST_F_SCUR] = mkf_u32(0, px->beconn);
-   stats[ST_F_SMAX] = mkf_u32(FN_MAX, px->be_counters.conn_max);
-   stats[ST_F_SLIM] = mkf_u32(FO_CONFIG|FN_LIMIT, px->fullconn);
-   stats[ST_F_STOT] = mkf_u64(FN_COUNTER, px->be_counters.cum_conn);
-   stats[ST_F_BIN]  = mkf_u64(FN_COUNTER, px