Skip to content

Commit c7989b5

Browse files
jukkarnashif
authored andcommitted
net: prometheus: Add more parameters to metric macros
Add collector parameter to metric creation macros so that it is possible to bind the metric to collector already at built time. Also add optional user_data to metric macro calls so that user can add optional data there. This will be used by network statistics Prometheus support in subsequent commits. Signed-off-by: Jukka Rissanen <[email protected]>
1 parent fdae68a commit c7989b5

File tree

13 files changed

+117
-17
lines changed

13 files changed

+117
-17
lines changed

include/zephyr/net/prometheus/collector.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@
2626

2727
#include <stddef.h>
2828

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+
2945
/**
3046
* @brief Prometheus collector definition
3147
*
@@ -38,6 +54,12 @@ struct prometheus_collector {
3854
sys_slist_t metrics;
3955
/** Mutex to protect the metrics list manipulation */
4056
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;
4163
};
4264

4365
/**
@@ -46,12 +68,25 @@ struct prometheus_collector {
4668
* This macro defines a Collector.
4769
*
4870
* @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.
4975
*/
50-
#define PROMETHEUS_COLLECTOR_DEFINE(_name) \
76+
#define PROMETHEUS_COLLECTOR_DEFINE(_name, ...) \
5177
STRUCT_SECTION_ITERABLE(prometheus_collector, _name) = { \
5278
.name = STRINGIFY(_name), \
5379
.metrics = SYS_SLIST_STATIC_INIT(&_name.metrics), \
5480
.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__)))), \
5590
}
5691

5792
/**

include/zephyr/net/prometheus/counter.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ struct prometheus_counter {
3333
struct prometheus_metric base;
3434
/** Value of the Prometheus counter metric */
3535
uint64_t value;
36+
/** User data */
37+
void *user_data;
3638
};
3739

3840
/**
@@ -44,22 +46,30 @@ struct prometheus_counter {
4446
* @param _name The counter metric name
4547
* @param _desc Counter description
4648
* @param _label Label for the metric. Additional labels can be added at runtime.
49+
* @param _collector Collector to map this metric. Can be set to NULL if it not yet known.
50+
* @param ... Optional user data specific to this metric instance.
4751
*
4852
* Example usage:
4953
* @code{.c}
5054
*
5155
* PROMETHEUS_COUNTER_DEFINE(http_request_counter, "HTTP request counter",
52-
* ({ .key = "http_request", .value = "request_count" }));
56+
* ({ .key = "http_request", .value = "request_count" }),
57+
* NULL);
5358
* @endcode
5459
*/
55-
#define PROMETHEUS_COUNTER_DEFINE(_name, _desc, _label) \
60+
#define PROMETHEUS_COUNTER_DEFINE(_name, _desc, _label, _collector, ...) \
5661
STRUCT_SECTION_ITERABLE(prometheus_counter, _name) = { \
5762
.base.name = STRINGIFY(_name), \
5863
.base.type = PROMETHEUS_COUNTER, \
5964
.base.description = _desc, \
6065
.base.labels[0] = __DEBRACKET _label, \
6166
.base.num_labels = 1, \
67+
.base.collector = _collector, \
6268
.value = 0ULL, \
69+
.user_data = COND_CODE_0( \
70+
NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
71+
(NULL), \
72+
(GET_ARG_N(1, __VA_ARGS__))), \
6373
}
6474

6575
/**

include/zephyr/net/prometheus/gauge.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct prometheus_gauge {
3131
struct prometheus_metric base;
3232
/** Value of the Prometheus gauge metric */
3333
double value;
34+
/** User data */
35+
void *user_data;
3436
};
3537

3638
/**
@@ -42,23 +44,31 @@ struct prometheus_gauge {
4244
* @param _name The gauge metric name.
4345
* @param _desc Gauge description
4446
* @param _label Label for the metric. Additional labels can be added at runtime.
47+
* @param _collector Collector to map this metric. Can be set to NULL if it not yet known.
48+
* @param ... Optional user data specific to this metric instance.
4549
*
4650
* Example usage:
4751
* @code{.c}
4852
*
4953
* PROMETHEUS_GAUGE_DEFINE(http_request_gauge, "HTTP request gauge",
50-
* ({ .key = "http_request", .value = "request_count" }));
54+
* ({ .key = "http_request", .value = "request_count" }),
55+
* NULL);
5156
*
5257
* @endcode
5358
*/
54-
#define PROMETHEUS_GAUGE_DEFINE(_name, _desc, _label) \
59+
#define PROMETHEUS_GAUGE_DEFINE(_name, _desc, _label, _collector, ...) \
5560
STRUCT_SECTION_ITERABLE(prometheus_gauge, _name) = { \
5661
.base.name = STRINGIFY(_name), \
5762
.base.type = PROMETHEUS_GAUGE, \
5863
.base.description = _desc, \
5964
.base.labels[0] = __DEBRACKET _label, \
6065
.base.num_labels = 1, \
66+
.base.collector = _collector, \
6167
.value = 0.0, \
68+
.user_data = COND_CODE_0( \
69+
NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
70+
(NULL), \
71+
(GET_ARG_N(1, __VA_ARGS__))), \
6272
}
6373

6474
/**

include/zephyr/net/prometheus/histogram.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ struct prometheus_histogram {
5151
double sum;
5252
/** Total count of observations in the histogram */
5353
unsigned long count;
54+
/** User data */
55+
void *user_data;
5456
};
5557

5658
/**
@@ -62,26 +64,34 @@ struct prometheus_histogram {
6264
* @param _name The histogram metric name.
6365
* @param _desc Histogram description
6466
* @param _label Label for the metric. Additional labels can be added at runtime.
67+
* @param _collector Collector to map this metric. Can be set to NULL if it not yet known.
68+
* @param ... Optional user data specific to this metric instance.
6569
*
6670
* Example usage:
6771
* @code{.c}
6872
*
6973
* PROMETHEUS_HISTOGRAM_DEFINE(http_request_histogram, "HTTP request histogram",
70-
* ({ .key = "request_latency", .value = "request_latency_seconds" }));
74+
* ({ .key = "request_latency", .value = "request_latency_seconds" }),
75+
* NULL);
7176
*
7277
* @endcode
7378
*/
74-
#define PROMETHEUS_HISTOGRAM_DEFINE(_name, _desc, _label) \
79+
#define PROMETHEUS_HISTOGRAM_DEFINE(_name, _desc, _label, _collector, ...) \
7580
STRUCT_SECTION_ITERABLE(prometheus_histogram, _name) = { \
7681
.base.name = STRINGIFY(_name), \
7782
.base.type = PROMETHEUS_HISTOGRAM, \
7883
.base.description = _desc, \
7984
.base.labels[0] = __DEBRACKET _label, \
8085
.base.num_labels = 1, \
86+
.base.collector = _collector, \
8187
.buckets = NULL, \
8288
.num_buckets = 0, \
8389
.sum = 0.0, \
8490
.count = 0U, \
91+
.user_data = COND_CODE_0( \
92+
NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
93+
(NULL), \
94+
(GET_ARG_N(1, __VA_ARGS__))), \
8595
}
8696

8797
/**

include/zephyr/net/prometheus/metric.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ struct prometheus_metric {
4949
sys_snode_t node;
5050
/** Back pointer to the collector that this metric belongs to */
5151
struct prometheus_collector *collector;
52+
/** Back pointer to the actual metric (counter, gauge, etc.).
53+
* This is just a temporary solution, ultimate goal is to place
54+
* this generic metrict struct into the actual metric struct.
55+
*/
56+
void *metric;
5257
/** Type of the Prometheus metric. */
5358
enum prometheus_metric_type type;
5459
/** Name of the Prometheus metric. */
@@ -59,6 +64,8 @@ struct prometheus_metric {
5964
struct prometheus_label labels[MAX_PROMETHEUS_LABELS_PER_METRIC];
6065
/** Number of labels associated with the Prometheus metric. */
6166
int num_labels;
67+
/** User defined data */
68+
void *user_data;
6269
/* Add any other necessary fields */
6370
};
6471

include/zephyr/net/prometheus/summary.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct prometheus_summary_quantile {
3232
double quantile;
3333
/** Value of the quantile */
3434
double value;
35+
/** User data */
36+
void *user_data;
3537
};
3638

3739
/**
@@ -51,6 +53,8 @@ struct prometheus_summary {
5153
double sum;
5254
/** Total count of observations in the summary metric */
5355
unsigned long count;
56+
/** User data */
57+
void *user_data;
5458
};
5559

5660
/**
@@ -62,29 +66,36 @@ struct prometheus_summary {
6266
* @param _name The summary metric name.
6367
* @param _desc Summary description
6468
* @param _label Label for the metric. Additional labels can be added at runtime.
69+
* @param _collector Collector to map this metric. Can be set to NULL if it not yet known.
70+
* @param ... Optional user data specific to this metric instance.
6571
*
6672
*
6773
* Example usage:
6874
* @code{.c}
6975
*
7076
* PROMETHEUS_SUMMARY_DEFINE(http_request_summary, "HTTP request summary",
7177
* ({ .key = "request_latency",
72-
* .value = "request_latency_seconds" }));
78+
* .value = "request_latency_seconds" }), NULL);
7379
*
7480
* @endcode
7581
*/
7682

77-
#define PROMETHEUS_SUMMARY_DEFINE(_name, _desc, _label) \
83+
#define PROMETHEUS_SUMMARY_DEFINE(_name, _desc, _label, _collector, ...) \
7884
STRUCT_SECTION_ITERABLE(prometheus_summary, _name) = { \
7985
.base.name = STRINGIFY(_name), \
8086
.base.type = PROMETHEUS_SUMMARY, \
8187
.base.description = _desc, \
8288
.base.labels[0] = __DEBRACKET _label, \
8389
.base.num_labels = 1, \
90+
.base.collector = _collector, \
8491
.quantiles = NULL, \
8592
.num_quantiles = 0, \
8693
.sum = 0.0, \
8794
.count = 0U, \
95+
.user_data = COND_CODE_0( \
96+
NUM_VA_ARGS_LESS_1(LIST_DROP_EMPTY(__VA_ARGS__, _)), \
97+
(NULL), \
98+
(GET_ARG_N(1, __VA_ARGS__))), \
8899
}
89100

90101
/**

samples/net/prometheus/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ static void setup_tls(void)
146146
}
147147

148148
PROMETHEUS_COUNTER_DEFINE(http_request_counter, "HTTP request counter",
149-
({ .key = "http_request", .value = "request_count" }));
149+
({ .key = "http_request", .value = "request_count" }), NULL);
150150

151151
PROMETHEUS_COLLECTOR_DEFINE(test_collector);
152152

subsys/net/lib/prometheus/formatter.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,20 @@ int prometheus_format_exposition(struct prometheus_collector *collector, char *b
6363

6464
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&collector->metrics, metric, tmp, node) {
6565

66+
/* If there is a user callback, use it to update the metric data. */
67+
if (collector->user_cb) {
68+
ret = collector->user_cb(collector, metric, collector->user_data);
69+
if (ret < 0) {
70+
if (ret == -EAGAIN) {
71+
/* Skip this metric for now */
72+
continue;
73+
}
74+
75+
LOG_ERR("Error in user callback (%d)", ret);
76+
goto out;
77+
}
78+
}
79+
6680
/* write HELP line if available */
6781
if (metric->description[0] != '\0') {
6882
ret = write_metric_to_buffer(buffer + written, buffer_size - written,

tests/net/lib/prometheus/collector/src/main.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <zephyr/net/prometheus/collector.h>
1111

1212
PROMETHEUS_COUNTER_DEFINE(test_counter_m, "Test counter",
13-
({ .key = "test_counter", .value = "test" }));
13+
({ .key = "test_counter", .value = "test" }), NULL);
1414

1515
PROMETHEUS_COLLECTOR_DEFINE(test_custom_collector);
1616

@@ -31,9 +31,11 @@ ZTEST(test_collector, test_prometheus_collector_register)
3131
prometheus_collector_register_metric(&test_custom_collector, &test_counter_m.base);
3232

3333
counter = (struct prometheus_counter *)prometheus_collector_get_metric(
34-
&test_custom_collector, "test_counter");
34+
&test_custom_collector, "test_counter_m");
3535

36-
zassert_equal(counter, &test_counter_m, "Counter not found in collector");
36+
zassert_equal_ptr(counter, &test_counter_m,
37+
"Counter not found in collector (expected %p, got %p)",
38+
&test_counter_m, counter);
3739

3840
zassert_equal(test_counter_m.value, 0, "Counter value is not 0");
3941

tests/net/lib/prometheus/counter/src/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
#include <zephyr/net/prometheus/counter.h>
1010

1111
PROMETHEUS_COUNTER_DEFINE(test_counter_m, "Test counter",
12-
({ .key = "test_counter", .value = "test" }));
12+
({ .key = "test_counter", .value = "test" }),
13+
NULL);
1314

1415
/**
1516
* @brief Test prometheus_counter_inc

0 commit comments

Comments
 (0)