diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 038746b0e6..bfd98cf202 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -337,6 +337,20 @@ enum stat_idx_info { ST_I_INF_MAX }; +/* Represent an exposed statistic. */ +struct stat_col { + const char *name; /* short name, used notably in CSV headers */ + const char *desc; /* user-friendly description */ + + uint32_t type; /* combination of field_nature and field_format */ + uint8_t cap; /* mask of stats_domain_px_cap to restrain metrics to an object types subset */ + + /* used only for generic metrics */ + struct { + int offset[2]; /* offset in counters */ + } metric; +}; + /* Stats columns for CSV output. For any column added here, please add the text * representation in the metrics_px array. Please only append at the end, @@ -494,7 +508,7 @@ struct stats_module { /* functor used to generate the stats module using counters provided through data parameter */ int (*fill_stats)(void *data, struct field *, unsigned int *); - struct name_desc *stats; /* name/description of stats provided by the module */ + struct stat_col *stats; /* statistics provided by the module */ void *counters; /* initial values of allocated counters */ size_t counters_off[COUNTERS_OFF_END]; /* list of offsets of allocated counters in various objects */ size_t stats_count; /* count of stats provided */ diff --git a/include/haproxy/stats.h b/include/haproxy/stats.h index 4f08ad1bd4..dab16dadf5 100644 --- a/include/haproxy/stats.h +++ b/include/haproxy/stats.h @@ -38,7 +38,7 @@ struct stconn; /* These two structs contains all column names and descriptions according to * the the number of entries in "enum stat_idx_px" and "enum stat_idx_info" */ -extern const struct name_desc stat_cols_px[]; +extern const struct stat_col stat_cols_px[]; extern const struct name_desc stat_cols_info[]; extern const char *stat_status_codes[]; extern struct applet http_stats_applet; diff --git a/src/h3_stats.c b/src/h3_stats.c index 830aa88a3a..3971e37501 100644 --- a/src/h3_stats.c +++ b/src/h3_stats.c @@ -35,7 +35,7 @@ enum { H3_STATS_COUNT /* must be the last */ }; -static struct name_desc h3_stats[] = { +static struct stat_col h3_stats[] = { /* h3 frame type counters */ [H3_ST_DATA] = { .name = "h3_data", .desc = "Total number of DATA frames received" }, diff --git a/src/mux_h1.c b/src/mux_h1.c index 9e3feb9f7d..397f75a129 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -227,7 +227,7 @@ enum { }; -static struct name_desc h1_stats[] = { +static struct stat_col h1_stats[] = { [H1_ST_OPEN_CONN] = { .name = "h1_open_connections", .desc = "Count of currently open connections" }, [H1_ST_OPEN_STREAM] = { .name = "h1_open_streams", diff --git a/src/mux_h2.c b/src/mux_h2.c index 47b1f14cf3..a3ce0eb891 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -306,7 +306,7 @@ enum { H2_STATS_COUNT /* must be the last member of the enum */ }; -static struct name_desc h2_stats[] = { +static struct stat_col h2_stats[] = { [H2_ST_HEADERS_RCVD] = { .name = "h2_headers_rcvd", .desc = "Total number of received HEADERS frames" }, [H2_ST_DATA_RCVD] = { .name = "h2_data_rcvd", diff --git a/src/quic_stats.c b/src/quic_stats.c index 80887c4fef..9d9b34310f 100644 --- a/src/quic_stats.c +++ b/src/quic_stats.c @@ -2,7 +2,7 @@ #include #include -static struct name_desc quic_stats[] = { +static struct stat_col quic_stats[] = { [QUIC_ST_RXBUF_FULL] = { .name = "quic_rxbuf_full", .desc = "Total number of cancelled reception due to full receiver buffer" }, [QUIC_ST_DROPPED_PACKET] = { .name = "quic_dropped_pkt", diff --git a/src/resolvers.c b/src/resolvers.c index d68208555f..0ee076800a 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -96,7 +96,7 @@ enum { RSLV_STAT_END, }; -static struct name_desc resolv_stats[] = { +static struct stat_col resolv_stats[] = { [RSLV_STAT_ID] = { .name = "id", .desc = "ID" }, [RSLV_STAT_PID] = { .name = "pid", .desc = "Parent ID" }, [RSLV_STAT_SENT] = { .name = "sent", .desc = "Sent" }, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 31885efe6f..3288641ede 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -159,7 +159,7 @@ enum { SSL_ST_STATS_COUNT /* must be the last member of the enum */ }; -static struct name_desc ssl_stats[] = { +static struct stat_col ssl_stats[] = { [SSL_ST_SESS] = { .name = "ssl_sess", .desc = "Total number of ssl sessions established" }, [SSL_ST_REUSED_SESS] = { .name = "ssl_reused_sess", diff --git a/src/stats.c b/src/stats.c index 2502b9e09f..6080b194ab 100644 --- a/src/stats.c +++ b/src/stats.c @@ -68,6 +68,35 @@ #include #include +/* Define a new metric for both frontend and backend sides. */ +#define ME_NEW_PX(name_f, nature, format, offset_f, cap_f, desc_f) \ + { .name = (name_f), .desc = (desc_f), .type = (nature)|(format), \ + .metric.offset[0] = offsetof(struct fe_counters, offset_f), \ + .metric.offset[1] = offsetof(struct be_counters, offset_f), \ + .cap = (cap_f), \ + } + +/* Define a new metric for frontend side only. */ +#define ME_NEW_FE(name_f, nature, format, offset_f, cap_f, desc_f) \ + { .name = (name_f), .desc = (desc_f), .type = (nature)|(format), \ + .metric.offset[0] = offsetof(struct fe_counters, offset_f), \ + .cap = (cap_f), \ + } + +/* Define a new metric for backend side only. */ +#define ME_NEW_BE(name_f, nature, format, offset_f, cap_f, desc_f) \ + { .name = (name_f), .desc = (desc_f), .type = (nature)|(format), \ + .metric.offset[1] = offsetof(struct be_counters, offset_f), \ + .cap = (cap_f), \ + } + +/* Convert stat_col to old-style as name_desc. */ +static void stcol2ndesc(struct name_desc *name, const struct stat_col *col) +{ + name->name = col->name; + name->desc = col->desc; +} + /* status codes available for the stats admin page (strictly 4 chars length) */ const char *stat_status_codes[STAT_STATUS_SIZE] = { @@ -167,7 +196,7 @@ const struct name_desc stat_cols_info[ST_I_INF_MAX] = { /* one line of info */ THREAD_LOCAL struct field stat_line_info[ST_I_INF_MAX]; -const struct name_desc stat_cols_px[ST_I_PX_MAX] = { +const struct stat_col stat_cols_px[ST_I_PX_MAX] = { [ST_I_PX_PXNAME] = { .name = "pxname", .desc = "Proxy name" }, [ST_I_PX_SVNAME] = { .name = "svname", .desc = "Server name" }, [ST_I_PX_QCUR] = { .name = "qcur", .desc = "Number of current queued connections" }, @@ -2823,7 +2852,7 @@ void stats_register_module(struct stats_module *m) static int allocate_stats_px_postcheck(void) { struct stats_module *mod; - size_t i = ST_I_PX_MAX; + size_t i = ST_I_PX_MAX, offset; int err_code = 0; struct proxy *px; @@ -2836,14 +2865,15 @@ static int allocate_stats_px_postcheck(void) return err_code; } - memcpy(stat_cols[STATS_DOMAIN_PROXY], stat_cols_px, - ST_I_PX_MAX * sizeof(struct name_desc)); + for (i = 0; i < ST_I_PX_MAX; ++i) + stcol2ndesc(&stat_cols[STATS_DOMAIN_PROXY][i], &stat_cols_px[i]); list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) { - memcpy(stat_cols[STATS_DOMAIN_PROXY] + i, - mod->stats, - mod->stats_count * sizeof(struct name_desc)); - i += mod->stats_count; + for (offset = i, i = 0; i < mod->stats_count; ++i) { + stcol2ndesc(&stat_cols[STATS_DOMAIN_PROXY][offset + i], + &mod->stats[i]); + } + i += offset; } for (px = proxies_list; px; px = px->next) { @@ -2864,7 +2894,7 @@ REGISTER_CONFIG_POSTPARSER("allocate-stats-px", allocate_stats_px_postcheck); static int allocate_stats_rslv_postcheck(void) { struct stats_module *mod; - size_t i = 0; + size_t i = 0, offset; int err_code = 0; stat_cols[STATS_DOMAIN_RESOLVERS] = malloc(stat_cols_len[STATS_DOMAIN_RESOLVERS] * sizeof(struct name_desc)); @@ -2875,10 +2905,11 @@ static int allocate_stats_rslv_postcheck(void) } list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_RESOLVERS], list) { - memcpy(stat_cols[STATS_DOMAIN_RESOLVERS] + i, - mod->stats, - mod->stats_count * sizeof(struct name_desc)); - i += mod->stats_count; + for (offset = i, i = 0; i < mod->stats_count; ++i) { + stcol2ndesc(&stat_cols[STATS_DOMAIN_RESOLVERS][offset + i], + &mod->stats[i]); + } + i += offset; } if (!resolv_allocate_counters(&stats_module_list[STATS_DOMAIN_RESOLVERS])) {