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().
This commit is contained in:
Amaury Denoyelle 2024-04-24 11:09:06 +02:00
parent 83731c8048
commit 34ae7755b3
7 changed files with 110 additions and 0 deletions

View 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 */

View 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 */

View 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 {

View 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);

View File

@ -118,6 +118,7 @@
#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;

View 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);
}

View 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)
{