]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: promex: Add a registration mechanism to support modules
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 30 Jan 2024 06:34:54 +0000 (07:34 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 2 Feb 2024 08:11:24 +0000 (09:11 +0100)
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.

Makefile
addons/promex/include/promex/promex.h [new file with mode: 0644]
addons/promex/service-prometheus.c

index 26993ee1c6b6e177fa78e76a6514e29357d3cf44..f1b870b0ed7fb8033545db6f544bf22891889f80 100644 (file)
--- 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 (file)
index 0000000..1104195
--- /dev/null
@@ -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 <cfaulet@haproxy.com>
+ *
+ * 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 <import/ist.h>
+
+#include <haproxy/api-t.h>
+#include <haproxy/list-t.h>
+
+
+/* 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:
+ */
index 89dc805032bab01370e515084bebff310fc0d24c..1fb21a392c98b04b86a61c2b96b150d4fd72cc63 100644 (file)
@@ -39,6 +39,8 @@
 #include <haproxy/tools.h>
 #include <haproxy/version.h>
 
+#include <promex/promex.h>
+
 /* 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)
 {