From: Christopher Faulet Date: Tue, 30 Jan 2024 06:34:54 +0000 (+0100) Subject: MEDIUM: promex: Add a registration mechanism to support modules X-Git-Tag: v3.0-dev3~102 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=eb2128723aabdc94f0a59a087229e5c674336b2e;p=thirdparty%2Fhaproxy.git MEDIUM: promex: Add a registration mechanism to support modules In this patch we add a registration mechanism for modules. To do so, a module must defined the "promex_module" structure. The dump itself will be based on 2 contexts. One for all the dump and another one for each metric time-series. These contexts are used as restart points when the dump is interrupted. Modules must also implement 6 callback functions: * start_metric_dump(): It is an optional callback function. If defined, it is responsible to initialize the dump context use as the first restart point. * stop_metric_dump(): It is an optional callback function. If defined, it is responsible to deinit the dump context. * metric_info(): This one is mandatory. It returns the info about the metric: name, type and flags and descrition. * start_ts(): This one is mandatory, it initializes the context for a time series for a given metric. This context is the second restart point. * next_ts(): This one is mandatory. It interates on time series for a given metrics. It is also responsible to handle end of a time series and deinit the context. * fill_ts(): It fills info on the time series for a given metric : the labels and the value. In addition, a module must set its name and declare the number of metrics is exposed. --- diff --git a/Makefile b/Makefile index 26993ee1c6..f1b870b0ed 100644 --- a/Makefile +++ b/Makefile @@ -663,6 +663,7 @@ endif # USE_LUA ifneq ($(USE_PROMEX),) OPTIONS_OBJS += addons/promex/service-prometheus.o + PROMEX_CFLAGS = -Iaddons/promex/include endif ifneq ($(USE_DEVICEATLAS),) diff --git a/addons/promex/include/promex/promex.h b/addons/promex/include/promex/promex.h new file mode 100644 index 0000000000..110419532c --- /dev/null +++ b/addons/promex/include/promex/promex.h @@ -0,0 +1,104 @@ +/* + * include/promex/promex.h + * This file contains definitions, macros and inline functions dedicated to + * the prometheus exporter for HAProxy. + * + * Copyright 2024 Christopher Faulet + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, version 2.1 + * exclusively. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _PROMEX_PROMEX_H +#define _PROMEX_PROMEX_H + +#include + +#include +#include + + +/* The max number of labels per metric */ +#define PROMEX_MAX_LABELS 8 + +/* Promtheus metric type (gauge or counter) */ +enum promex_mt_type { + PROMEX_MT_GAUGE = 1, + PROMEX_MT_COUNTER = 2, +}; + +/* Describe a prometheus metric */ +struct promex_metric { + struct ist n; /* The metric name */ + enum promex_mt_type type; /* The metric type (gauge or counter) */ + unsigned int flags; /* PROMEX_FL_* flags */ +}; + +/* Describe a prometheus metric label. It is just a key/value pair */ +struct promex_label { + struct ist name; + struct ist value; +}; + +/* Entity used to expose custom metrics on HAProxy. + * + * * start_metric_dump(): It is an optional callback function. If defined, it + * is responsible to initialize the dump context use + * as the first restart point. + * + * * stop_metric_dump(): It is an optional callback function. If defined, it + * is responsible to deinit the dump context. + * + * * metric_info(): This one is mandatory. It returns the info about the + * metric: name, type and flags and descrition. + * + * * start_ts(): This one is mandatory, it initializes the context for a time + * series for a given metric. This context is the second + * restart point. + * + * * next_ts(): This one is mandatory. It interates on time series for a + * given metrics. It is also responsible to handle end of a + * time series and deinit the context. + * + * * fill_ts(): It fills info on the time series for a given metric : the + * labels and the value. + */ +struct promex_module { + struct list list; + struct ist name; /* The promex module name */ + int (*metric_info)(unsigned int id, /* Return info for the given id */ + struct promex_metric *metric, + struct ist *desc); + void *(*start_metrics_dump)(); /* Start a dump (may be NULL) */ + void (*stop_metrics_dump)(void *ctx); /* Stop a dump (may be NULL) */ + void *(*start_ts)(void *ctx, unsigned int id); /* Start a time series for the given metric */ + void *(*next_ts)(void *ctx, void *ts_ctx, unsigned int id); /* move to the next time series for the given metric */ + int (*fill_ts)(void *ctx, void *ts_ctx, unsigned int id, /* fill the time series for the given metric */ + struct promex_label *labels, struct field *field); + + size_t nb_metrics; /* # of metrics */ +}; + +extern struct list promex_module_list; + +void promex_register_module(struct promex_module *m); + +#endif /* _PROMEX_PROMEX_H */ + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + */ diff --git a/addons/promex/service-prometheus.c b/addons/promex/service-prometheus.c index 89dc805032..1fb21a392c 100644 --- a/addons/promex/service-prometheus.c +++ b/addons/promex/service-prometheus.c @@ -39,6 +39,8 @@ #include #include +#include + /* Prometheus exporter applet states (appctx->st0) */ enum { PROMEX_ST_INIT = 0, /* initialized */ @@ -90,12 +92,6 @@ struct promex_ctx { int obj_state; /* current state among PROMEX_{FRONT|BACK|SRV|LI}_STATE_* */ }; -/* Promtheus metric type (gauge or counter) */ -enum promex_mt_type { - PROMEX_MT_GAUGE = 1, - PROMEX_MT_COUNTER = 2, -}; - /* The max length for metrics name. It is a hard limit but it should be * enough. */ @@ -107,22 +103,6 @@ enum promex_mt_type { */ #define PROMEX_MAX_METRIC_LENGTH 512 -/* The max number of labels per metric */ -#define PROMEX_MAX_LABELS 8 - -/* Describe a prometheus metric */ -struct promex_metric { - const struct ist n; /* The metric name */ - enum promex_mt_type type; /* The metric type (gauge or counter) */ - unsigned int flags; /* PROMEX_FL_* flags */ -}; - -/* Describe a prometheus metric label. It is just a key/value pair */ -struct promex_label { - struct ist name; - struct ist value; -}; - /* Global metrics */ const struct promex_metric promex_global_metrics[INF_TOTAL_FIELDS] = { //[INF_NAME] ignored @@ -410,6 +390,14 @@ const struct ist promex_srv_st[PROMEX_SRV_STATE_COUNT] = { [PROMEX_SRV_STATE_NOLB] = IST("NOLB"), }; +struct list promex_module_list = LIST_HEAD_INIT(promex_module_list); + + +void promex_register_module(struct promex_module *m) +{ + LIST_APPEND(&promex_module_list, &m->list); +} + /* Return the server status. */ enum promex_srv_state promex_srv_status(struct server *sv) {