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_SUMMARY_H_
9 #define ZEPHYR_INCLUDE_PROMETHEUS_SUMMARY_H_
10 
11 /**
12  * @file
13  *
14  * @brief Prometheus summary 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 summary quantile definition.
27  *
28  * This structure defines a Prometheus summary quantile.
29  */
30 struct prometheus_summary_quantile {
31 	/** Quantile of the summary */
32 	double quantile;
33 	/** Value of the quantile */
34 	double value;
35 	/** User data */
36 	void *user_data;
37 };
38 
39 /**
40  * @brief Type used to represent a Prometheus summary metric.
41  *
42  * * References
43  * * See https://prometheus.io/docs/concepts/metric_types/#summary
44  */
45 struct prometheus_summary {
46 	/** Base of the Prometheus summary metric */
47 	struct prometheus_metric base;
48 	/** Array of quantiles associated with the Prometheus summary metric */
49 	struct prometheus_summary_quantile *quantiles;
50 	/** Number of quantiles associated with the Prometheus summary metric */
51 	size_t num_quantiles;
52 	/** Sum of all observed values in the summary metric */
53 	double sum;
54 	/** Total count of observations in the summary metric */
55 	unsigned long count;
56 	/** User data */
57 	void *user_data;
58 };
59 
60 /**
61  * @brief Prometheus Summary definition.
62  *
63  * This macro defines a Summary metric. If you want to make the summary static,
64  * then add "static" keyword before the PROMETHEUS_SUMMARY_DEFINE.
65  *
66  * @param _name The summary metric name.
67  * @param _desc Summary description
68  * @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.
71  *
72  *
73  * Example usage:
74  * @code{.c}
75  *
76  * PROMETHEUS_SUMMARY_DEFINE(http_request_summary, "HTTP request summary",
77  *                           ({ .key = "request_latency",
78  *                              .value = "request_latency_seconds" }), NULL);
79  *
80  * @endcode
81  */
82 
83 #define PROMETHEUS_SUMMARY_DEFINE(_name, _desc, _label, _collector, ...) \
84 	STRUCT_SECTION_ITERABLE(prometheus_summary, _name) = {		\
85 		.base.name = STRINGIFY(_name),				\
86 		.base.type = PROMETHEUS_SUMMARY,			\
87 		.base.description = _desc,				\
88 		.base.labels[0] = __DEBRACKET _label,			\
89 		.base.num_labels = 1,					\
90 		.base.collector = _collector,				\
91 		.quantiles = NULL,					\
92 		.num_quantiles = 0,					\
93 		.sum = 0.0,						\
94 		.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__))),			\
99 	}
100 
101 /**
102  * @brief Observes a value in a Prometheus summary metric
103  *
104  * Observes the specified value in the given summary metric.
105  *
106  * @param summary Pointer to the summary metric to observe.
107  * @param value Value to observe in the summary metric.
108  * @return 0 on success, -EINVAL if the value is negative.
109  */
110 int prometheus_summary_observe(struct prometheus_summary *summary, double value);
111 
112 /**
113  * @brief Set the summary value to specific value.
114  * The new value must be higher than the current value. This function can be used
115  * if we cannot add individual increments to the summary but need to periodically
116  * update the counter value. This function will add the difference between the
117  * new value and the old value to the summary fields.
118  * @param summary Pointer to the summary metric to increment.
119  * @param value New value of the summary.
120  * @param count New counter value of the summary.
121  * @return 0 on success, negative errno on error.
122  */
123 int prometheus_summary_observe_set(struct prometheus_summary *summary,
124 				   double value, unsigned long count);
125 
126 /**
127  * @}
128  */
129 
130 #endif /* ZEPHYR_INCLUDE_PROMETHEUS_SUMMARY_H_ */
131