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_HISTOGRAM_H_
9 #define ZEPHYR_INCLUDE_PROMETHEUS_HISTOGRAM_H_
10 
11 /**
12  * @file
13  *
14  * @brief Prometheus histogram APIs.
15  *
16  * @addtogroup prometheus
17  * @{
18  */
19 
20 #include <zephyr/sys/iterable_sections.h>
21 #include <zephyr/net/prometheus/metric.h>
22 
23 #include <stddef.h>
24 
25 /**
26  * @brief Prometheus histogram bucket definition.
27  *
28  * This structure defines a Prometheus histogram bucket.
29  */
30 struct prometheus_histogram_bucket {
31 	/** Upper bound value of bucket */
32 	double upper_bound;
33 	/** Cumulative count of observations in the bucket */
34 	unsigned long count;
35 };
36 
37 /**
38  * @brief Type used to represent a Prometheus histogram metric.
39  *
40  * * References
41  * * See https://prometheus.io/docs/concepts/metric_types/#histogram
42  */
43 struct prometheus_histogram {
44 	/** Base of the Prometheus histogram metric */
45 	struct prometheus_metric base;
46 	/** Array of buckets in the histogram */
47 	struct prometheus_histogram_bucket *buckets;
48 	/** Number of buckets in the histogram */
49 	size_t num_buckets;
50 	/** Sum of all observed values in the histogram */
51 	double sum;
52 	/** Total count of observations in the histogram */
53 	unsigned long count;
54 	/** User data */
55 	void *user_data;
56 };
57 
58 /**
59  * @brief Prometheus Histogram definition.
60  *
61  * This macro defines a Histogram metric. If you want to make the histogram static,
62  * then add "static" keyword before the PROMETHEUS_HISTOGRAM_DEFINE.
63  *
64  * @param _name The histogram metric name.
65  * @param _desc Histogram description
66  * @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.
69  *
70  * Example usage:
71  * @code{.c}
72  *
73  * PROMETHEUS_HISTOGRAM_DEFINE(http_request_histogram, "HTTP request histogram",
74  *                         ({ .key = "request_latency", .value = "request_latency_seconds" }),
75  *                         NULL);
76  *
77  * @endcode
78  */
79 #define PROMETHEUS_HISTOGRAM_DEFINE(_name, _desc, _label, _collector, ...) \
80 	STRUCT_SECTION_ITERABLE(prometheus_histogram, _name) = {	\
81 		.base.name = STRINGIFY(_name),				\
82 		.base.type = PROMETHEUS_HISTOGRAM,			\
83 		.base.description = _desc,				\
84 		.base.labels[0] = __DEBRACKET _label,			\
85 		.base.num_labels = 1,					\
86 		.base.collector = _collector,				\
87 		.buckets = NULL,					\
88 		.num_buckets = 0,					\
89 		.sum = 0.0,						\
90 		.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__))),			\
95 	}
96 
97 /**
98  * @brief Observe a value in a Prometheus histogram metric
99  *
100  * Observes the specified value in the given histogram metric.
101  *
102  * @param histogram Pointer to the histogram metric to observe.
103  * @param value Value to observe in the histogram metric.
104  * @return 0 on success, -EINVAL if the value is negative.
105  */
106 int prometheus_histogram_observe(struct prometheus_histogram *histogram, double value);
107 
108 /**
109  * @}
110  */
111 
112 #endif /* ZEPHYR_INCLUDE_PROMETHEUS_HISTOGRAM_H_ */
113