]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: apply stats-file on process startup
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 24 Apr 2024 09:09:06 +0000 (11:09 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 26 Apr 2024 09:29:25 +0000 (11:29 +0200)
This commit is the first one of a serie to implement preloading of
haproxy counters via stats-file parsing.

This patch defines a basic apply_stats_file() function. It implements
reading line by line of a stats-file without any parsing for the moment.
It is called automatically on process startup via init().

include/haproxy/global-t.h
include/haproxy/stats-file.h
include/haproxy/stats-t.h
include/haproxy/stats.h
src/haproxy.c
src/stats-file.c
src/stats.c

index 92d2c6bc1116a62f7e2ade10f8d829e4f9353265..05eae30bc8d88aeb033aa7dbdf2ac15fd65699b7 100644 (file)
@@ -155,6 +155,7 @@ struct global {
        char *log_send_hostname;   /* set hostname in syslog header */
        char *server_state_base;   /* path to a directory where server state files can be found */
        char *server_state_file;   /* path to the file where server states are loaded from */
+       char *stats_file;          /* path to stats-file */
        unsigned char cluster_secret[16]; /* 128 bits of an SHA1 digest of a secret defined as ASCII string */
        struct {
                int maxpollevents; /* max number of poll events at once */
index 90634870f78aa0720cfe65ad1fdb45415f1f4dc2..9a4161ca27083cbaa1df89781e4546d794045ead 100644 (file)
@@ -12,4 +12,12 @@ int stats_dump_fields_file(struct buffer *out,
 
 void stats_dump_file_header(int type, struct buffer *out);
 
+/* Maximun number of parsed stat column in a header line.
+ * Directly based on ST_I_PX_MAX, with value doubled to obtain compatibility
+ * between haproxy adjacent versions.
+ */
+#define STAT_FILE_MAX_COL_COUNT    (ST_I_PX_MAX*2)
+
+void apply_stats_file(void);
+
 #endif /* _HAPROXY_STATS_FILE_H */
index 320dfb1ef21d488ab9567ad44f73993816d2ee23..204401a84d66215679be01d4b72eac14915ecfb8 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef _HAPROXY_STATS_T_H
 #define _HAPROXY_STATS_T_H
 
+#include <import/ebtree-t.h>
 #include <haproxy/api-t.h>
 #include <haproxy/buf-t.h>
 
@@ -479,6 +480,12 @@ enum stat_idx_px {
        ST_I_PX_MAX
 };
 
+/* Node for name-indexed stat tree from generate_stat_tree(). */
+struct stcol_node {
+       const struct stat_col *col;
+       struct ebmb_node name;
+};
+
 struct field {
        uint32_t type;
        union {
index d1ab6b3a70fec417b7367288b497533df453a348..90141a331d4ca745e0b00480f5e49da9c9bae0b6 100644 (file)
@@ -47,6 +47,8 @@ extern THREAD_LOCAL struct field stat_line_info[];
 extern THREAD_LOCAL struct field *stat_lines[];
 extern struct name_desc *stat_cols[STATS_DOMAIN_COUNT];
 
+int generate_stat_tree(struct eb_root *st_tree, const struct stat_col cols[]);
+
 struct htx;
 int stats_putchk(struct appctx *appctx, struct buffer *buf, struct htx *htx);
 
index a5fa6dfcd16bcbd1ca58d81ec3e5e499de0cb554..411cd100eda549c7e997993e3509247342e6b7a8 100644 (file)
 #include <haproxy/sock.h>
 #include <haproxy/sock_inet.h>
 #include <haproxy/ssl_sock.h>
+#include <haproxy/stats-file.h>
 #include <haproxy/stats-t.h>
 #include <haproxy/stream.h>
 #include <haproxy/task.h>
@@ -2365,6 +2366,9 @@ static void init(int argc, char **argv)
        /* Apply server states */
        apply_server_state();
 
+       /* Preload internal counters. */
+       apply_stats_file();
+
        for (px = proxies_list; px; px = px->next)
                srv_compute_all_admin_states(px);
 
@@ -2943,6 +2947,7 @@ void deinit(void)
        ha_free(&localpeer);
        ha_free(&global.server_state_base);
        ha_free(&global.server_state_file);
+       ha_free(&global.stats_file);
        task_destroy(idle_conn_task);
        idle_conn_task = NULL;
 
index f3e0db934d22b7a1af39e16d3420067e68d3ce3b..f1e154e820a4688af60d28a4cca97e67d1391e33 100644 (file)
@@ -1,8 +1,15 @@
 #include <haproxy/stats-file.h>
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <import/ebmbtree.h>
 #include <haproxy/api.h>
 #include <haproxy/buf.h>
 #include <haproxy/chunk.h>
+#include <haproxy/errors.h>
+#include <haproxy/global.h>
 #include <haproxy/guid-t.h>
 #include <haproxy/list.h>
 #include <haproxy/listener-t.h>
@@ -90,3 +97,52 @@ void stats_dump_file_header(int type, struct buffer *out)
 
        chunk_strcat(out, "\n");
 }
+
+/* Parse a stats-file and preload haproxy internal counters. */
+void apply_stats_file(void)
+{
+       struct eb_root st_tree = EB_ROOT;
+       FILE *file;
+       char *line = NULL;
+       ssize_t len;
+       size_t alloc_len;
+       int linenum;
+
+       if (!global.stats_file)
+               return;
+
+       file = fopen(global.stats_file, "r");
+       if (!file) {
+               ha_warning("config: Can't load stats file: cannot open file.\n");
+               return;
+       }
+
+       /* Generate stat columns map indexed by name. */
+       if (generate_stat_tree(&st_tree, stat_cols_px)) {
+               ha_warning("config: Can't load stats file: not enough memory.\n");
+               goto out;
+       }
+
+       linenum = 0;
+       while (1) {
+               len = getline(&line, &alloc_len, file);
+               if (len < 0)
+                       break;
+
+               ++linenum;
+               if (!len || (len == 1 && line[0] == '\n'))
+                       continue;
+       }
+
+ out:
+       while (!eb_is_empty(&st_tree)) {
+               struct ebmb_node *node = ebmb_first(&st_tree);
+               struct stcol_node *snode = ebmb_entry(node, struct stcol_node, name);
+
+               ebmb_delete(node);
+               ha_free(&snode);
+       }
+
+       ha_free(&line);
+       fclose(file);
+}
index 1280a1eeac3a2c3d6f1e91281b26d30932ee363e..e5551629445f79b1d79cb22e8179c4efa84c8fb5 100644 (file)
@@ -23,6 +23,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <import/ebsttree.h>
 #include <haproxy/api.h>
 #include <haproxy/activity.h>
 #include <haproxy/applet.h>
@@ -336,6 +337,36 @@ struct list stats_module_list[STATS_DOMAIN_COUNT] = {
 
 THREAD_LOCAL void *trash_counters;
 
+/* Insert into <st_tree> all stat columns from <cols> indexed by their name. */
+int generate_stat_tree(struct eb_root *st_tree, const struct stat_col cols[])
+{
+       const struct stat_col *col;
+       struct stcol_node *node;
+       size_t len;
+       int i;
+
+       for (i = 0; i < ST_I_PX_MAX; ++i) {
+               col = &cols[i];
+               if (stcol_nature(col) == FN_COUNTER) {
+                       len = strlen(col->name);
+                       node = malloc(sizeof(struct stcol_node) + len + 1);
+                       if (!node)
+                               goto err;
+
+                       node->col = col;
+                       memcpy(node->name.key, col->name, len);
+                       node->name.key[len] = '\0';
+
+                       ebst_insert(st_tree, &node->name);
+               }
+       }
+
+       return 0;
+
+ err:
+       return 1;
+}
+
 
 int stats_putchk(struct appctx *appctx, struct buffer *buf, struct htx *htx)
 {