#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) */
#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
/* Generate if possible a metric value from <col>. <cap> 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 <counters>.
+ * type. <stat_file> must be set when dumping stats-file. Metric value will be
+ * extracted from <counters>.
*
- * 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:
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:
* 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;
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);
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) {
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);
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);
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);