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_COUNTER_H_
9 #define ZEPHYR_INCLUDE_PROMETHEUS_COUNTER_H_
10 
11 /**
12  * @file
13  *
14  * @brief Prometheus counter APIs.
15  *
16  * @addtogroup prometheus
17  * @{
18  */
19 
20 #include <stdint.h>
21 
22 #include <zephyr/sys/iterable_sections.h>
23 #include <zephyr/net/prometheus/metric.h>
24 
25 /**
26  * @brief Type used to represent a Prometheus counter metric.
27  *
28  * * References
29  * * See https://prometheus.io/docs/concepts/metric_types/#counter
30  */
31 struct prometheus_counter {
32 	/** Base of the Prometheus counter metric */
33 	struct prometheus_metric base;
34 	/** Value of the Prometheus counter metric */
35 	uint64_t value;
36 	/** User data */
37 	void *user_data;
38 };
39 
40 /**
41  * @brief Prometheus Counter definition.
42  *
43  * This macro defines a Counter metric. If you want to make the counter static,
44  * then add "static" keyword before the PROMETHEUS_COUNTER_DEFINE.
45  *
46  * @param _name The counter metric name
47  * @param _desc Counter description
48  * @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.
51  *
52  * Example usage:
53  * @code{.c}
54  *
55  * PROMETHEUS_COUNTER_DEFINE(http_request_counter, "HTTP request counter",
56  *                           ({ .key = "http_request", .value = "request_count" }),
57  *                           NULL);
58  * @endcode
59  */
60 #define PROMETHEUS_COUNTER_DEFINE(_name, _desc, _label, _collector, ...) \
61 	STRUCT_SECTION_ITERABLE(prometheus_counter, _name) = {		\
62 		.base.name = STRINGIFY(_name),				\
63 		.base.type = PROMETHEUS_COUNTER,			\
64 		.base.description = _desc,				\
65 		.base.labels[0] = __DEBRACKET _label,			\
66 		.base.num_labels = 1,					\
67 		.base.collector = _collector,				\
68 		.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__))),			\
73 	}
74 
75 /**
76  * @brief Increment the value of a Prometheus counter metric
77  * Increments the value of the specified counter metric by arbitrary amount.
78  * @param counter Pointer to the counter metric to increment.
79  * @param value Amount to increment the counter by.
80  * @return 0 on success, negative errno on error.
81  */
82 int prometheus_counter_add(struct prometheus_counter *counter, uint64_t value);
83 
84 /**
85  * @brief Increment the value of a Prometheus counter metric
86  * Increments the value of the specified counter metric by one.
87  * @param counter Pointer to the counter metric to increment.
88  * @return 0 on success, negative errno on error.
89  */
prometheus_counter_inc(struct prometheus_counter * counter)90 static inline int prometheus_counter_inc(struct prometheus_counter *counter)
91 {
92 	return prometheus_counter_add(counter, 1ULL);
93 }
94 
95 /**
96  * @brief Set the counter value to specific value.
97  * The new value must be higher than the current value. This function can be used
98  * if we cannot add individual increments to the counter but need to periodically
99  * update the counter value. This function will add the difference between the
100  * new value and the old value to the counter.
101  * @param counter Pointer to the counter metric to increment.
102  * @param value New value of the counter.
103  * @return 0 on success, negative errno on error.
104  */
105 int prometheus_counter_set(struct prometheus_counter *counter, uint64_t value);
106 
107 /**
108  * @}
109  */
110 
111 #endif /* ZEPHYR_INCLUDE_PROMETHEUS_COUNTER_H_ */
112