]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: introduce a more expressive stat definition method
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 28 Mar 2024 13:53:39 +0000 (14:53 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 26 Apr 2024 08:20:57 +0000 (10:20 +0200)
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.

include/haproxy/stats-t.h
include/haproxy/stats.h
src/h3_stats.c
src/mux_h1.c
src/mux_h2.c
src/quic_stats.c
src/resolvers.c
src/ssl_sock.c
src/stats.c

index 038746b0e60a7f94050ca55e813489e7cb3fcc3c..bfd98cf202c2dcbc1db4a1cf011ebdb8d4d5a052 100644 (file)
@@ -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 */
index 4f08ad1bd4896a13ef255165b0d9ed9aedf08001..dab16dadf525256bc29ddbc37161de755392ab0c 100644 (file)
@@ -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;
index 830aa88a3acea1db6e77f6d95f81dbaecbf458a6..3971e3750189a87461ee57b943e0c776507926c4 100644 (file)
@@ -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" },
index 9e3feb9f7d6ca82d1631cb7185efa6a8fd0e0a19..397f75a1293478981368f12a10f81b80b7403d95 100644 (file)
@@ -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",
index 47b1f14cf37519a61f9ac433f813ad445f11d229..a3ce0eb891f6dfffc9c9642bc9b5c70728d17bb5 100644 (file)
@@ -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",
index 80887c4fefec64e0b421a9e6bfbfb38da9409dba..9d9b34310f22c936e01b0bcb09bef3aa0175f4c6 100644 (file)
@@ -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",
index d68208555f1c60ab14d1b928a76735312afae098..0ee076800acc989349a54691ae8dea6797e360ac 100644 (file)
@@ -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" },
index 31885efe6fc15fdcf7dfa32212a08caf602c69eb..3288641ede492fe961ac1c2346660f6cbdd1992d 100644 (file)
@@ -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",
index 2502b9e09fa3d830214665da0a8a1e61b3fec406..6080b194abe4231dac5c576b38260d760c031342 100644 (file)
 #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])) {