Tor  0.4.6.0-alpha-dev
hs_metrics.c
Go to the documentation of this file.
1 /* Copyright (c) 2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * @file hs_metrics.c
6  * @brief Onion service metrics exposed through the MetricsPort
7  **/
8 
9 #define HS_METRICS_ENTRY_PRIVATE
10 
11 #include "orconfig.h"
12 
13 #include "lib/malloc/malloc.h"
16 
17 #include "feature/hs/hs_metrics.h"
19 #include "feature/hs/hs_service.h"
20 
21 /** Return a static buffer pointer that contains the port as a string.
22  *
23  * Subsequent call to this function invalidates the previous buffer. */
24 static const char *
25 port_to_str(const uint16_t port)
26 {
27  static char buf[8];
28  tor_snprintf(buf, sizeof(buf), "%u", port);
29  return buf;
30 }
31 
32 /** Return a static buffer pointer that contains a formatted label on the form
33  * of key=value.
34  *
35  * Subsequent call to this function invalidates the previous buffer. */
36 static const char *
37 format_label(const char *key, const char *value)
38 {
39  static char buf[128];
40  tor_snprintf(buf, sizeof(buf), "%s=%s", key, value);
41  return buf;
42 }
43 
44 /** Initialize a metrics store for the given service.
45  *
46  * Essentially, this goes over the base_metrics array and adds them all to the
47  * store set with their label(s) if any. */
48 static void
50 {
51  metrics_store_t *store;
52 
53  tor_assert(service);
54 
55  store = service->metrics.store;
56 
57  for (size_t i = 0; i < base_metrics_size; ++i) {
58  metrics_store_entry_t *entry =
60  base_metrics[i].help);
61 
62  /* Add labels to the entry. */
64  format_label("onion", service->onion_address));
65  if (base_metrics[i].port_as_label && service->config.ports) {
67  const rend_service_port_config_t *, p) {
69  format_label("port", port_to_str(p->virtual_port)));
70  } SMARTLIST_FOREACH_END(p);
71  }
72  }
73 }
74 
75 /** Update the metrics key entry in the store in the given service. The port,
76  * if non 0, is used to find the correct metrics entry. The value n is the
77  * value used to update the entry. */
78 void
79 hs_metrics_update_by_service(const hs_metrics_key_t key,
80  hs_service_t *service, const uint16_t port,
81  int64_t n)
82 {
83  tor_assert(service);
84 
85  /* Get the metrics entry in the store. */
86  smartlist_t *entries = metrics_store_get_all(service->metrics.store,
87  base_metrics[key].name);
88  if (BUG(!entries)) {
89  return;
90  }
91 
92  /* We need to find the right metrics entry by finding the port label if any.
93  *
94  * XXX: This is not the most optimal due to the string format. Maybe at some
95  * point turn this into a kvline and a map in a metric entry? */
96  SMARTLIST_FOREACH_BEGIN(entries, metrics_store_entry_t *, entry) {
97  if (port == 0 ||
99  format_label("port", port_to_str(port)))) {
100  metrics_store_entry_update(entry, n);
101  break;
102  }
103  } SMARTLIST_FOREACH_END(entry);
104 }
105 
106 /** Update the metrics key entry in the store of a service identified by the
107  * given identity public key. The port, if non 0, is used to find the correct
108  * metrics entry. The value n is the value used to update the entry.
109  *
110  * This is used by callsite that have access to the key but not the service
111  * object so an extra lookup is done to find the service. */
112 void
113 hs_metrics_update_by_ident(const hs_metrics_key_t key,
114  const ed25519_public_key_t *ident_pk,
115  const uint16_t port, int64_t n)
116 {
117  hs_service_t *service;
118 
119  tor_assert(ident_pk);
120 
121  service = hs_service_find(ident_pk);
122  if (!service) {
123  /* This is possible because an onion service client can end up here due to
124  * having an identity key onto a connection _to_ an onion service. We
125  * can't differentiate that from an actual onion service initiated by a
126  * service and thus the only way to know is to lookup the service. */
127  return;
128  }
129  hs_metrics_update_by_service(key, service, port, n);
130 }
131 
132 /** Return a list of all the onion service metrics stores. This is the
133  * function attached to the .get_metrics() member of the subsys_t. */
134 const smartlist_t *
136 {
137  /* We can't have the caller to free the returned list so keep it static,
138  * simply update it. */
139  static smartlist_t *stores_list = NULL;
140 
141  smartlist_free(stores_list);
142  stores_list = hs_service_get_metrics_stores();
143  return stores_list;
144 }
145 
146 /** Initialize the metrics store in the given service. */
147 void
149 {
150  tor_assert(service);
151 
152  /* Calling this function twice on a service object is wrong. The caller must
153  * free the metrics before if so. */
154  if (BUG(service->metrics.store)) {
155  return;
156  }
157 
158  service->metrics.store = metrics_store_new();
159  init_store(service);
160 }
161 
162 /** Free the metrics store in the given service. */
163 void
165 {
166  tor_assert(service);
167 
168  metrics_store_free(service->metrics.store);
169 }
hs_service_t::config
hs_service_config_t config
Definition: hs_service.h:316
hs_service.h
Header file containing service data for the HS subsystem.
hs_metrics_entry.h
Header for feature/hs/hs_metrics_entry.c.
name
const char * name
Definition: config.c:2464
metrics_store_t
Definition: metrics_store.c:25
port_to_str
static const char * port_to_str(const uint16_t port)
Definition: hs_metrics.c:25
smartlist.h
Header for smartlist.c.
metrics_store_entry_add_label
void metrics_store_entry_add_label(metrics_store_entry_t *entry, const char *label)
Definition: metrics_store_entry.c:111
tor_assert
#define tor_assert(expr)
Definition: util_bug.h:102
rend_service_port_config_t
Definition: hs_common.h:153
hs_metrics_update_by_service
void hs_metrics_update_by_service(const hs_metrics_key_t key, hs_service_t *service, const uint16_t port, int64_t n)
Definition: hs_metrics.c:79
hs_metrics_service_init
void hs_metrics_service_init(hs_service_t *service)
Definition: hs_metrics.c:148
metrics_store_new
metrics_store_t * metrics_store_new(void)
Definition: metrics_store.c:68
tor_snprintf
int tor_snprintf(char *str, size_t size, const char *format,...)
Definition: printf.c:27
hs_service_find
hs_service_t * hs_service_find(const ed25519_public_key_t *identity_pk)
Definition: hs_service.c:4236
hs_metrics.h
Header for feature/hs/hs_metrics.c.
hs_service_t::metrics
hs_service_metrics_t metrics
Definition: hs_service.h:324
hs_metrics_service_free
void hs_metrics_service_free(hs_service_t *service)
Definition: hs_metrics.c:164
hs_metrics_get_stores
const smartlist_t * hs_metrics_get_stores(void)
Definition: hs_metrics.c:135
format_label
static const char * format_label(const char *key, const char *value)
Definition: hs_metrics.c:37
base_metrics
const hs_metrics_entry_t base_metrics[]
Definition: hs_metrics_entry.c:21
ed25519_public_key_t
Definition: crypto_ed25519.h:23
hs_service_get_metrics_stores
smartlist_t * hs_service_get_metrics_stores(void)
Definition: hs_service.c:4220
metrics_store_add
metrics_store_entry_t * metrics_store_add(metrics_store_t *store, metrics_type_t type, const char *name, const char *help)
Definition: metrics_store.c:103
hs_service_metrics_t::store
metrics_store_t * store
Definition: hs_service.h:41
malloc.h
Headers for util_malloc.c.
hs_service_t
Definition: hs_service.h:300
base_metrics_size
const size_t base_metrics_size
Definition: hs_metrics_entry.c:65
SMARTLIST_FOREACH_BEGIN
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
Definition: smartlist_foreach.h:78
hs_service_config_t::ports
smartlist_t * ports
Definition: hs_service.h:214
hs_service_t::onion_address
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
Definition: hs_service.h:303
metrics_store.h
Header for lib/metrics/metrics_store.c.
metrics_store_get_all
smartlist_t * metrics_store_get_all(const metrics_store_t *store, const char *name)
Definition: metrics_store.c:92
hs_metrics_update_by_ident
void hs_metrics_update_by_ident(const hs_metrics_key_t key, const ed25519_public_key_t *ident_pk, const uint16_t port, int64_t n)
Definition: hs_metrics.c:113
init_store
static void init_store(hs_service_t *service)
Definition: hs_metrics.c:49
metrics_store_entry_update
void metrics_store_entry_update(metrics_store_entry_t *entry, const int64_t value)
Definition: metrics_store_entry.c:60
smartlist_t
Definition: smartlist_core.h:26
metrics_store_entry_has_label
bool metrics_store_entry_has_label(const metrics_store_entry_t *entry, const char *label)
Definition: metrics_store_entry.c:122