1 /*
2 * Copyright (c) 2024 Mustafa Abdullah Kus, Sparse Technology
3 * Copyright (c) 2024 Nordic Semiconductor
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_PROMETHEUS_COLLECTOR_H_
9 #define ZEPHYR_INCLUDE_PROMETHEUS_COLLECTOR_H_
10
11 /**
12 * @file
13 *
14 * @brief Prometheus collector APIs.
15 *
16 * @defgroup prometheus Prometheus API
17 * @since 4.0
18 * @version 0.1.0
19 * @ingroup networking
20 * @{
21 */
22
23 #include <zephyr/kernel.h>
24 #include <zephyr/sys/iterable_sections.h>
25 #include <zephyr/net/prometheus/metric.h>
26
27 #include <stddef.h>
28
29 struct prometheus_collector;
30
31 /**
32 * @typedef prometheus_scrape_cb_t
33 * @brief Callback used to scrape a collector for a specific metric.
34 *
35 * @param collector A valid pointer on the collector to scrape
36 * @param metric A valid pointer on the metric to scrape
37 * @param user_data A valid pointer to a user data or NULL
38 *
39 * @return 0 if successful, otherwise a negative error code.
40 */
41 typedef int (*prometheus_scrape_cb_t)(struct prometheus_collector *collector,
42 struct prometheus_metric *metric,
43 void *user_data);
44
45 /**
46 * @brief Prometheus collector definition
47 *
48 * This structure defines a Prometheus collector.
49 */
50 struct prometheus_collector {
51 /** Name of the collector */
52 const char *name;
53 /** Array of metrics associated with the collector */
54 sys_slist_t metrics;
55 /** Mutex to protect the metrics list manipulation */
56 struct k_mutex lock;
57 /** User callback function. If set, then the metric data is fetched
58 * via the function callback.
59 */
60 prometheus_scrape_cb_t user_cb;
61 /** User data */
62 void *user_data;
63 };
64
65 /**
66 * @brief Prometheus Collector definition.
67 *
68 * This macro defines a Collector.
69 *
70 * @param _name The collector's name.
71 * @param ... Optional user callback function. If set, this function is called
72 * when the collector is scraped. The function should be of type
73 * prometheus_scrape_cb_t.
74 * Optional user data to pass to the user callback function.
75 */
76 #define PROMETHEUS_COLLECTOR_DEFINE(_name, ...) \
77 STRUCT_SECTION_ITERABLE(prometheus_collector, _name) = { \
78 .name = STRINGIFY(_name), \
79 .metrics = SYS_SLIST_STATIC_INIT(&_name.metrics), \
80 .lock = Z_MUTEX_INITIALIZER(_name.lock), \
81 .user_cb = COND_CODE_0( \
82 NUM_VA_ARGS_LESS_1( \
83 LIST_DROP_EMPTY(__VA_ARGS__, _)), \
84 (NULL), \
85 (GET_ARG_N(1, __VA_ARGS__))), \
86 .user_data = COND_CODE_0( \
87 NUM_VA_ARGS_LESS_1(__VA_ARGS__), (NULL), \
88 (GET_ARG_N(1, \
89 GET_ARGS_LESS_N(1, __VA_ARGS__)))), \
90 }
91
92 /**
93 * @brief Register a metric with a Prometheus collector
94 *
95 * Registers the specified metric with the given collector.
96 *
97 * @param collector Pointer to the collector to register the metric with.
98 * @param metric Pointer to the metric to register.
99 *
100 * @return 0 if successful, otherwise a negative error code.
101 * @retval -EINVAL Invalid arguments.
102 * @retval -ENOMEM Not enough memory to register the metric.
103 */
104 int prometheus_collector_register_metric(struct prometheus_collector *collector,
105 struct prometheus_metric *metric);
106
107 /**
108 * @brief Get a metric from a Prometheus collector
109 *
110 * Retrieves the metric with the specified name from the given collector.
111 *
112 * @param collector Pointer to the collector to retrieve the metric from.
113 * @param name Name of the metric to retrieve.
114 * @return Pointer to the retrieved metric, or NULL if not found.
115 */
116 const void *prometheus_collector_get_metric(struct prometheus_collector *collector,
117 const char *name);
118
119 /** @cond INTERNAL_HIDDEN */
120
121 enum prometheus_walk_state {
122 PROMETHEUS_WALK_START,
123 PROMETHEUS_WALK_CONTINUE,
124 PROMETHEUS_WALK_STOP,
125 };
126
127 struct prometheus_collector_walk_context {
128 struct prometheus_collector *collector;
129 struct prometheus_metric *metric;
130 struct prometheus_metric *tmp;
131 enum prometheus_walk_state state;
132 };
133
134 /** @endcond */
135
136 /**
137 * @brief Walk through all metrics in a Prometheus collector and format them
138 * into a buffer.
139 *
140 * @param ctx Pointer to the walker context.
141 * @param buffer Pointer to the buffer to store the formatted metrics.
142 * @param buffer_size Size of the buffer.
143 * @return 0 if successful and we went through all metrics, -EAGAIN if we
144 * need to call this function again, any other negative error code
145 * means an error occurred.
146 */
147 int prometheus_collector_walk_metrics(struct prometheus_collector_walk_context *ctx,
148 uint8_t *buffer, size_t buffer_size);
149
150 /**
151 * @brief Initialize the walker context to walk through all metrics.
152 *
153 * @param ctx Pointer to the walker context.
154 * @param collector Pointer to the collector to walk through.
155 *
156 * @return 0 if successful, otherwise a negative error code.
157 */
prometheus_collector_walk_init(struct prometheus_collector_walk_context * ctx,struct prometheus_collector * collector)158 static inline int prometheus_collector_walk_init(struct prometheus_collector_walk_context *ctx,
159 struct prometheus_collector *collector)
160 {
161 if (collector == NULL) {
162 return -EINVAL;
163 }
164
165 ctx->collector = collector;
166 ctx->state = PROMETHEUS_WALK_START;
167 ctx->metric = NULL;
168 ctx->tmp = NULL;
169
170 return 0;
171 }
172
173 /**
174 * @}
175 */
176
177 #endif /* ZEPHYR_INCLUDE_PROMETHEUS_COLLECTOR_H_ */
178