From: Amaury Denoyelle Date: Wed, 24 Apr 2024 09:09:06 +0000 (+0200) Subject: MINOR: stats: apply stats-file on process startup X-Git-Tag: v3.0-dev9~32 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34ae7755b36c3d23ed529d2fea2da2084fe2d41e;p=thirdparty%2Fhaproxy.git MINOR: stats: apply stats-file on process startup 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(). --- diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 92d2c6bc11..05eae30bc8 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -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 */ diff --git a/include/haproxy/stats-file.h b/include/haproxy/stats-file.h index 90634870f7..9a4161ca27 100644 --- a/include/haproxy/stats-file.h +++ b/include/haproxy/stats-file.h @@ -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 */ diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 320dfb1ef2..204401a84d 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -22,6 +22,7 @@ #ifndef _HAPROXY_STATS_T_H #define _HAPROXY_STATS_T_H +#include #include #include @@ -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 { diff --git a/include/haproxy/stats.h b/include/haproxy/stats.h index d1ab6b3a70..90141a331d 100644 --- a/include/haproxy/stats.h +++ b/include/haproxy/stats.h @@ -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); diff --git a/src/haproxy.c b/src/haproxy.c index a5fa6dfcd1..411cd100ed 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/stats-file.c b/src/stats-file.c index f3e0db934d..f1e154e820 100644 --- a/src/stats-file.c +++ b/src/stats-file.c @@ -1,8 +1,15 @@ #include +#include +#include +#include + +#include #include #include #include +#include +#include #include #include #include @@ -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); +} diff --git a/src/stats.c b/src/stats.c index 1280a1eeac..e555162944 100644 --- a/src/stats.c +++ b/src/stats.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -336,6 +337,36 @@ struct list stats_module_list[STATS_DOMAIN_COUNT] = { THREAD_LOCAL void *trash_counters; +/* Insert into all stat columns from 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) {