diff --git a/addons/promex/service-prometheus.c b/addons/promex/service-prometheus.c index 82427e2dce..4e0bc68e10 100644 --- a/addons/promex/service-prometheus.c +++ b/addons/promex/service-prometheus.c @@ -659,7 +659,7 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx) if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_FE)) goto next_px; - if (!stats_fill_fe_line(px, stats, ST_I_PX_MAX, &(ctx->field_num))) + if (!stats_fill_fe_line(px, 0, stats, ST_I_PX_MAX, &(ctx->field_num))) return -1; switch (ctx->field_num) { diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 61ac86d4c8..320dfb1ef2 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -29,7 +29,7 @@ #define STAT_F_FMT_HTML 0x00000001 /* dump the stats in HTML format */ #define STAT_F_FMT_TYPED 0x00000002 /* use the typed output format */ #define STAT_F_FMT_JSON 0x00000004 /* dump the stats in JSON format */ -#define STAT_F_HIDE_DOWN 0x00000008 /* hide 'down' servers in the stats page */ +#define STAT_F_FMT_FILE 0x00000008 /* dump stats-file */ #define STAT_F_NO_REFRESH 0x00000010 /* do not automatically refresh the stats page */ #define STAT_F_ADMIN 0x00000020 /* indicate a stats admin level */ #define STAT_F_CHUNKED 0x00000040 /* use chunked encoding (HTTP/1.1) */ @@ -44,11 +44,12 @@ #define STAT_F_HIDE_MAINT 0x00004000 /* hide maint/disabled servers */ #define STAT_F_CONVDONE 0x00008000 /* conf: rules conversion done */ #define STAT_F_USE_FLOAT 0x00010000 /* use floats where possible in the outputs */ +#define STAT_F_HIDE_DOWN 0x00020000 /* hide 'down' servers in the stats page */ #define STAT_F_BOUND 0x00800000 /* bound statistics to selected proxies/types/services */ #define STAT_F_STARTED 0x01000000 /* some output has occurred */ -#define STAT_F_FMT_MASK 0x00000007 +#define STAT_F_FMT_MASK 0x0000000f #define STATS_TYPE_FE 0 #define STATS_TYPE_BE 1 diff --git a/include/haproxy/stats.h b/include/haproxy/stats.h index e364824db9..d1ab6b3a70 100644 --- a/include/haproxy/stats.h +++ b/include/haproxy/stats.h @@ -55,7 +55,7 @@ const char *stats_scope_ptr(struct appctx *appctx); int stats_dump_one_line(const struct field *line, size_t stats_count, struct appctx *appctx); int stats_fill_info(struct field *info, int len, uint flags); -int stats_fill_fe_line(struct proxy *px, struct field *line, int len, +int stats_fill_fe_line(struct proxy *px, int flags, struct field *line, int len, enum stat_idx_px *index); int stats_fill_li_line(struct proxy *px, struct listener *l, int flags, struct field *line, int len, enum stat_idx_px *index); diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 52db1af5ec..0340ce1f3c 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -2054,7 +2054,7 @@ int hlua_proxy_get_stats(lua_State *L) if (px->cap & PR_CAP_BE) stats_fill_be_line(px, STAT_F_SHLGNDS, stats, STATS_LEN, NULL); else - stats_fill_fe_line(px, stats, STATS_LEN, NULL); + stats_fill_fe_line(px, 0, stats, STATS_LEN, NULL); lua_newtable(L); for (i=0; i. must be set to one of * STATS_PX_CAP_* values to check if the metric is available for this object - * type. Metric value will be extracted from . + * type. must be set when dumping stats-file. Metric value will be + * extracted from . * - * Returns a field value or an empty one if cap not compatible. + * Returns a field metric. */ static struct field me_generate_field(const struct stat_col *col, enum stat_idx_px idx, enum obj_type *objt, - const void *counters, uint8_t cap) + const void *counters, uint8_t cap, + int stat_file) { struct field value; void *counter = NULL; + int wrong_side = 0; + + /* Only generic stat column must be used as input. */ + BUG_ON(!stcol_is_generic(col)); switch (cap) { case STATS_PX_CAP_FE: case STATS_PX_CAP_LI: counter = (char *)counters + col->metric.offset[0]; + wrong_side = !(col->cap & (STATS_PX_CAP_FE|STATS_PX_CAP_LI)); break; case STATS_PX_CAP_BE: case STATS_PX_CAP_SRV: counter = (char *)counters + col->metric.offset[1]; + wrong_side = !(col->cap & (STATS_PX_CAP_BE|STATS_PX_CAP_SRV)); break; default: @@ -720,13 +728,18 @@ static struct field me_generate_field(const struct stat_col *col, ABORT_NOW(); } - /* Check if metric is defined for this side. */ - if (!(col->cap & cap)) - return (struct field){ .type = FF_EMPTY }; - - /* Check if metric should be hidden in output. */ - if (stcol_hide(idx, objt)) - return (struct field){ .type = FF_EMPTY }; + if (stat_file) { + /* stats-file emits separately frontend and backend stats. + * Skip metric if not defined for any object on the cap side. + */ + if (wrong_side) + return (struct field){ .type = FF_EMPTY }; + } + else { + /* Ensure metric is defined for the current cap. */ + if (!(col->cap & cap) || stcol_hide(idx, objt)) + return (struct field){ .type = FF_EMPTY }; + } switch (stcol_format(col)) { case FF_U64: @@ -746,7 +759,7 @@ static struct field me_generate_field(const struct stat_col *col, * this value, or if the selected field is not implemented for frontends, the * function returns 0, otherwise, it returns 1. */ -int stats_fill_fe_line(struct proxy *px, struct field *line, int len, +int stats_fill_fe_line(struct proxy *px, int flags, struct field *line, int len, enum stat_idx_px *index) { enum stat_idx_px i = index ? *index : 0; @@ -760,9 +773,10 @@ int stats_fill_fe_line(struct proxy *px, struct field *line, int len, if (stcol_is_generic(col)) { field = me_generate_field(col, i, &px->obj_type, - &px->fe_counters, STATS_PX_CAP_FE); + &px->fe_counters, STATS_PX_CAP_FE, + flags & STAT_F_FMT_FILE); } - else { + else if (!(flags & STAT_F_FMT_FILE)) { switch (i) { case ST_I_PX_PXNAME: field = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id); @@ -889,7 +903,7 @@ static int stats_dump_fe_line(struct stconn *sc, struct proxy *px) memset(line, 0, sizeof(struct field) * stat_cols_len[STATS_DOMAIN_PROXY]); - if (!stats_fill_fe_line(px, line, ST_I_PX_MAX, NULL)) + if (!stats_fill_fe_line(px, ctx->flags, line, ST_I_PX_MAX, NULL)) return 0; list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) { @@ -935,9 +949,10 @@ int stats_fill_li_line(struct proxy *px, struct listener *l, int flags, if (stcol_is_generic(col)) { field = me_generate_field(col, i, &l->obj_type, - l->counters, STATS_PX_CAP_LI); + l->counters, STATS_PX_CAP_LI, + flags & STAT_F_FMT_FILE); } - else { + else if (!(flags & STAT_F_FMT_FILE)) { switch (i) { case ST_I_PX_PXNAME: field = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id); @@ -1184,9 +1199,10 @@ int stats_fill_sv_line(struct proxy *px, struct server *sv, int flags, if (stcol_is_generic(col)) { field = me_generate_field(col, i, &sv->obj_type, - &sv->counters, STATS_PX_CAP_SRV); + &sv->counters, STATS_PX_CAP_SRV, + flags & STAT_F_FMT_FILE); } - else { + else if (!(flags & STAT_F_FMT_FILE)) { switch (i) { case ST_I_PX_PXNAME: field = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id); @@ -1570,9 +1586,10 @@ int stats_fill_be_line(struct proxy *px, int flags, struct field *line, int len, if (stcol_is_generic(col)) { field = me_generate_field(col, i, &px->obj_type, - &px->be_counters, STATS_PX_CAP_BE); + &px->be_counters, STATS_PX_CAP_BE, + flags & STAT_F_FMT_FILE); } - else { + else if (!(flags & STAT_F_FMT_FILE)) { switch (i) { case ST_I_PX_PXNAME: field = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id);