MINOR: stats: introduce a more expressive stat definition method
Previously, statistics were simply defined as a list of name_desc, as for example "stat_cols_px" for proxy stats. No notion of type was fixed for each stat definition. This correspondance was done individually inside stats_fill_*_line() functions. This renders the process to define new statistics tedious. Implement a more expressive stat definition method via a new API. A new type "struct stat_col" for stat column to replace name_desc usage is defined. It contains a field to store the stat nature and format. A <cap> field is also defined to be able to define a proxy stat only for certain type of objects. This new type is also further extended to include counter offsets. This allows to define a method to automatically generate a stat value field from a "struct stat_col". This will be the subject of a future commit. New type "struct stat_col" is fully compatible full name_desc. This allows to gradually convert stats definition. The focus will be first for proxies counters to implement statistics preservation on reload.
This commit is contained in:
parent
861370a6d4
commit
65624876f2
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <haproxy/quic_stats-t.h>
|
||||
#include <haproxy/stats.h>
|
||||
|
||||
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",
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -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",
|
||||
|
|
57
src/stats.c
57
src/stats.c
|
@ -68,6 +68,35 @@
|
|||
#include <haproxy/uri_auth-t.h>
|
||||
#include <haproxy/version.h>
|
||||
|
||||
/* 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 <col> to old-style <name> 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])) {
|
||||
|
|
Loading…
Reference in New Issue