1 /* Copyright (c) 2020-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * @file metrics_store.c
6 * @brief Metrics interface to store them based on specific store type and get
7 * their MetricsPort output.
10 #define METRICS_STORE_ENTRY_PRIVATE
14 #include "lib/container/map.h"
15 #include "lib/log/util_bug.h"
16 #include "lib/malloc/malloc.h"
18 #include "lib/metrics/metrics_store.h"
19 #include "lib/metrics/metrics_store_entry.h"
22 #include "lib/metrics/prometheus.h"
24 /** A metric store which contains a map of entries. */
25 struct metrics_store_t
{
26 /** Indexed by metrics entry name. An entry is a smartlist_t of one or more
27 * metrics_store_entry_t allowing for multiple metrics of the same name.
29 * The reason we allow multiple entries is because there are cases where one
30 * metrics can be used twice by the same entity but with different labels.
31 * One example is an onion service with multiple ports, the port specific
32 * metrics will have a port value as a label. */
36 /** Function pointer to the format function of a specific driver. */
37 typedef void (fmt_driver_fn_t
)(const metrics_store_entry_t
*, buf_t
*);
39 /** Helper: Free a single entry in a metrics_store_t taking a void pointer
42 metrics_store_free_void(void *p
)
44 smartlist_t
*list
= p
;
45 SMARTLIST_FOREACH(list
, metrics_store_entry_t
*, entry
,
46 metrics_store_entry_free(entry
));
50 /** Put the given store output in the buffer data and use the format function
51 * given in fmt to get it for each entry. */
53 get_output(const metrics_store_t
*store
, buf_t
*data
, fmt_driver_fn_t fmt
)
59 STRMAP_FOREACH(store
->entries
, key
, const smartlist_t
*, entries
) {
60 SMARTLIST_FOREACH_BEGIN(entries
, const metrics_store_entry_t
*, entry
) {
62 } SMARTLIST_FOREACH_END(entry
);
66 /** Return a newly allocated and initialized store of the given type. */
68 metrics_store_new(void)
70 metrics_store_t
*store
= tor_malloc_zero(sizeof(*store
));
72 store
->entries
= strmap_new();
77 /** Free the given store including all its entries. */
79 metrics_store_free_(metrics_store_t
*store
)
85 strmap_free(store
->entries
, metrics_store_free_void
);
89 /** Find all metrics entry in the given store identified by name. If not found,
90 * NULL is returned. */
92 metrics_store_get_all(const metrics_store_t
*store
, const char *name
)
97 return strmap_get(store
->entries
, name
);
100 /** Add a new metrics entry to the given store and type. The name MUST be the
101 * unique identifier. The help string can be omitted. */
102 metrics_store_entry_t
*
103 metrics_store_add(metrics_store_t
*store
, metrics_type_t type
,
104 const char *name
, const char *help
)
106 smartlist_t
*entries
;
107 metrics_store_entry_t
*entry
;
112 entries
= metrics_store_get_all(store
, name
);
114 entries
= smartlist_new();
115 strmap_set(store
->entries
, name
, entries
);
117 entry
= metrics_store_entry_new(type
, name
, help
);
118 smartlist_add(entries
, entry
);
123 /** Set the output of the given store of the format fmt into the given buffer
126 metrics_store_get_output(const metrics_format_t fmt
,
127 const metrics_store_t
*store
, buf_t
*data
)
132 case METRICS_FORMAT_PROMETHEUS
:
133 get_output(store
, data
, prometheus_format_store_entry
);
137 tor_assert_unreached();