Tor  0.4.7.0-alpha-dev
metrics_store.c
Go to the documentation of this file.
1 /* Copyright (c) 2020-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * @file metrics_store.c
6  * @brief Metrics interface to store them based on specific store type and get
7  * their MetricsPort output.
8  **/
9 
10 #define METRICS_STORE_ENTRY_PRIVATE
11 
12 #include "orconfig.h"
13 
14 #include "lib/container/map.h"
15 #include "lib/log/util_bug.h"
16 #include "lib/malloc/malloc.h"
17 
20 
21 /* Format Drivers. */
22 #include "lib/metrics/prometheus.h"
23 
24 /** A metric store which contains a map of entries. */
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.
28  *
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. */
33  strmap_t *entries;
34 };
35 
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 *,
38  bool no_comment);
39 
40 /** Helper: Free a single entry in a metrics_store_t taking a void pointer
41  * parameter. */
42 static void
44 {
45  smartlist_t *list = p;
46  SMARTLIST_FOREACH(list, metrics_store_entry_t *, entry,
47  metrics_store_entry_free(entry));
48  smartlist_free(list);
49 }
50 
51 #include <stdio.h>
52 
53 /** Put the given store output in the buffer data and use the format function
54  * given in fmt to get it for each entry. */
55 static void
56 get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
57 {
58  tor_assert(store);
59  tor_assert(data);
60  tor_assert(fmt);
61 
62  STRMAP_FOREACH(store->entries, key, const smartlist_t *, entries) {
63  /* Indicate that we've formatted the coment already for the entries. */
64  bool comment_formatted = false;
65  SMARTLIST_FOREACH_BEGIN(entries, const metrics_store_entry_t *, entry) {
66  fmt(entry, data, comment_formatted);
67  comment_formatted = true;
68  } SMARTLIST_FOREACH_END(entry);
69  } STRMAP_FOREACH_END;
70 }
71 
72 /** Return a newly allocated and initialized store of the given type. */
75 {
76  metrics_store_t *store = tor_malloc_zero(sizeof(*store));
77 
78  store->entries = strmap_new();
79 
80  return store;
81 }
82 
83 /** Free the given store including all its entries. */
84 void
86 {
87  if (store == NULL) {
88  return;
89  }
90 
91  strmap_free(store->entries, metrics_store_free_void);
92  tor_free(store);
93 }
94 
95 /** Find all metrics entry in the given store identified by name. If not found,
96  * NULL is returned. */
98 metrics_store_get_all(const metrics_store_t *store, const char *name)
99 {
100  tor_assert(store);
101  tor_assert(name);
102 
103  return strmap_get(store->entries, name);
104 }
105 
106 /** Add a new metrics entry to the given store and type. The name MUST be the
107  * unique identifier. The help string can be omitted. */
108 metrics_store_entry_t *
110  const char *name, const char *help)
111 {
112  smartlist_t *entries;
113  metrics_store_entry_t *entry;
114 
115  tor_assert(store);
116  tor_assert(name);
117 
118  entries = metrics_store_get_all(store, name);
119  if (!entries) {
120  entries = smartlist_new();
121  strmap_set(store->entries, name, entries);
122  }
123  entry = metrics_store_entry_new(type, name, help);
124  smartlist_add(entries, entry);
125 
126  return entry;
127 }
128 
129 /** Set the output of the given store of the format fmt into the given buffer
130  * data. */
131 void
133  const metrics_store_t *store, buf_t *data)
134 {
135  tor_assert(store);
136 
137  switch (fmt) {
140  break;
141  default:
142  // LCOV_EXCL_START
143  tor_assert_unreached();
144  // LCOV_EXCL_STOP
145  }
146 }
147 
148 /** Reset a store as in free its content. */
149 void
151 {
152  if (store == NULL) {
153  return;
154  }
155  strmap_free(store->entries, metrics_store_free_void);
156  store->entries = strmap_new();
157 }
const char * name
Definition: config.c:2434
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:52
Headers for map.c.
metrics_type_t
metrics_format_t
@ METRICS_FORMAT_PROMETHEUS
void metrics_store_free_(metrics_store_t *store)
Definition: metrics_store.c:85
static void get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
Definition: metrics_store.c:56
smartlist_t * metrics_store_get_all(const metrics_store_t *store, const char *name)
Definition: metrics_store.c:98
metrics_store_entry_t * metrics_store_add(metrics_store_t *store, metrics_type_t type, const char *name, const char *help)
void metrics_store_get_output(const metrics_format_t fmt, const metrics_store_t *store, buf_t *data)
metrics_store_t * metrics_store_new(void)
Definition: metrics_store.c:74
void() fmt_driver_fn_t(const metrics_store_entry_t *, buf_t *, bool no_comment)
Definition: metrics_store.c:37
static void metrics_store_free_void(void *p)
Definition: metrics_store.c:43
void metrics_store_reset(metrics_store_t *store)
Header for lib/metrics/metrics_store.c.
metrics_store_entry_t * metrics_store_entry_new(const metrics_type_t type, const char *name, const char *help)
Header for lib/metrics/metrics_store_entry.c.
void prometheus_format_store_entry(const metrics_store_entry_t *entry, buf_t *data, bool no_comment)
Definition: prometheus.c:45
Header for feature/metrics/prometheus.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
strmap_t * entries
Definition: metrics_store.c:33
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:102