Tor  0.4.8.0-alpha-dev
relay_metrics.c
Go to the documentation of this file.
1 /* Copyright (c) 2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * @file relay_metrics.c
6  * @brief Relay metrics exposed through the MetricsPort
7  **/
8 
9 #define RELAY_METRICS_ENTRY_PRIVATE
10 
11 #include "orconfig.h"
12 
13 #include "core/or/or.h"
15 #include "core/mainloop/mainloop.h"
19 #include "core/or/circuitlist.h"
20 #include "core/or/dos.h"
21 #include "core/or/relay.h"
22 
23 #include "app/config/config.h"
24 
26 #include "lib/log/util_bug.h"
27 #include "lib/malloc/malloc.h"
28 #include "lib/math/fp.h"
30 
31 #include "feature/hs/hs_dos.h"
36 #include "feature/relay/router.h"
37 #include "feature/stats/rephist.h"
38 
39 #include <event2/dns.h>
40 
41 /** Declarations of each fill function for metrics defined in base_metrics. */
42 static void fill_cc_counters_values(void);
43 static void fill_cc_gauges_values(void);
44 static void fill_circuits_values(void);
45 static void fill_conn_counter_values(void);
46 static void fill_conn_gauge_values(void);
47 static void fill_dns_error_values(void);
48 static void fill_dns_query_values(void);
49 static void fill_dos_values(void);
50 static void fill_global_bw_limit_values(void);
51 static void fill_socket_values(void);
52 static void fill_onionskins_values(void);
53 static void fill_oom_values(void);
54 static void fill_streams_values(void);
55 static void fill_relay_flags(void);
56 static void fill_tcp_exhaustion_values(void);
57 static void fill_traffic_values(void);
58 
59 /** The base metrics that is a static array of metrics added to the metrics
60  * store.
61  *
62  * The key member MUST be also the index of the entry in the array. */
64 {
65  {
67  .type = METRICS_TYPE_COUNTER,
68  .name = METRICS_NAME(relay_load_oom_bytes_total),
69  .help = "Total number of bytes the OOM has freed by subsystem",
70  .fill_fn = fill_oom_values,
71  },
72  {
74  .type = METRICS_TYPE_COUNTER,
75  .name = METRICS_NAME(relay_load_onionskins_total),
76  .help = "Total number of onionskins handled",
77  .fill_fn = fill_onionskins_values,
78  },
79  {
81  .type = METRICS_TYPE_GAUGE,
82  .name = METRICS_NAME(relay_load_socket_total),
83  .help = "Total number of sockets",
84  .fill_fn = fill_socket_values,
85  },
86  {
88  .type = METRICS_TYPE_COUNTER,
89  .name = METRICS_NAME(relay_load_global_rate_limit_reached_total),
90  .help = "Total number of global connection bucket limit reached",
91  .fill_fn = fill_global_bw_limit_values,
92  },
93  {
94  .key = RELAY_METRICS_NUM_DNS,
95  .type = METRICS_TYPE_COUNTER,
96  .name = METRICS_NAME(relay_exit_dns_query_total),
97  .help = "Total number of DNS queries done by this relay",
98  .fill_fn = fill_dns_query_values,
99  },
100  {
102  .type = METRICS_TYPE_COUNTER,
103  .name = METRICS_NAME(relay_exit_dns_error_total),
104  .help = "Total number of DNS errors encountered by this relay",
105  .fill_fn = fill_dns_error_values,
106  },
107  {
109  .type = METRICS_TYPE_COUNTER,
110  .name = METRICS_NAME(relay_load_tcp_exhaustion_total),
111  .help = "Total number of times we ran out of TCP ports",
112  .fill_fn = fill_tcp_exhaustion_values,
113  },
114  {
116  .type = METRICS_TYPE_COUNTER,
117  .name = METRICS_NAME(relay_connections_total),
118  .help = "Total number of created/rejected connections",
119  .fill_fn = fill_conn_counter_values,
120  },
121  {
123  .type = METRICS_TYPE_GAUGE,
124  .name = METRICS_NAME(relay_connections),
125  .help = "Total number of opened connections",
126  .fill_fn = fill_conn_gauge_values,
127  },
128  {
130  .type = METRICS_TYPE_COUNTER,
131  .name = METRICS_NAME(relay_streams_total),
132  .help = "Total number of streams",
133  .fill_fn = fill_streams_values,
134  },
135  {
137  .type = METRICS_TYPE_COUNTER,
138  .name = METRICS_NAME(relay_congestion_control_total),
139  .help = "Congestion control related counters",
140  .fill_fn = fill_cc_counters_values,
141  },
142  {
144  .type = METRICS_TYPE_GAUGE,
145  .name = METRICS_NAME(relay_congestion_control),
146  .help = "Congestion control related gauges",
147  .fill_fn = fill_cc_gauges_values,
148  },
149  {
150  .key = RELAY_METRICS_NUM_DOS,
151  .type = METRICS_TYPE_COUNTER,
152  .name = METRICS_NAME(relay_dos_total),
153  .help = "Denial of Service defenses related counters",
154  .fill_fn = fill_dos_values,
155  },
156  {
158  .type = METRICS_TYPE_COUNTER,
159  .name = METRICS_NAME(relay_traffic_bytes),
160  .help = "Traffic related counters",
161  .fill_fn = fill_traffic_values,
162  },
163  {
165  .type = METRICS_TYPE_GAUGE,
166  .name = METRICS_NAME(relay_flag),
167  .help = "Relay flags from consensus",
168  .fill_fn = fill_relay_flags,
169  },
170  {
172  .type = METRICS_TYPE_GAUGE,
173  .name = METRICS_NAME(relay_circuits_total),
174  .help = "Total number of circuits",
175  .fill_fn = fill_circuits_values,
176  },
177 };
178 static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
179 
180 /** The only and single store of all the relay metrics. */
182 
183 /** Helper function to convert an handshake type into a string. */
184 static inline const char *
185 handshake_type_to_str(const uint16_t type)
186 {
187  switch (type) {
188  case ONION_HANDSHAKE_TYPE_TAP:
189  return "tap";
190  case ONION_HANDSHAKE_TYPE_FAST:
191  return "fast";
192  case ONION_HANDSHAKE_TYPE_NTOR:
193  return "ntor";
194  case ONION_HANDSHAKE_TYPE_NTOR_V3:
195  return "ntor_v3";
196  default:
197  // LCOV_EXCL_START
198  tor_assert_unreached();
199  // LCOV_EXCL_STOP
200  }
201 }
202 
203 /** Helper function to convert a socket family type into a string. */
204 static inline const char *
205 af_to_string(const int af)
206 {
207  switch (af) {
208  case AF_INET:
209  return "ipv4";
210  case AF_INET6:
211  return "ipv6";
212  case AF_UNIX:
213  return "unix";
214  default:
215  return "<unknown>";
216  }
217 }
218 
219 /** Fill function for the RELAY_METRICS_NUM_CIRCUITS metric. */
220 static void
222 {
223  const relay_metrics_entry_t *rentry =
225  metrics_store_entry_t *sentry = metrics_store_add(
226  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
227 
229  metrics_format_label("state", "opened"));
231  smartlist_len(circuit_get_global_list()));
232 }
233 
234 /** Fill function for the RELAY_METRICS_RELAY_FLAGS metric. */
235 static void
237 {
238  uint8_t is_fast = 0, is_exit = 0, is_authority = 0, is_stable = 0;
239  uint8_t is_running = 0, is_v2_dir = 0, is_guard = 0, is_sybil = 0;
240  uint8_t is_hs_dir = 0;
241 
242  const node_t *me =
243  node_get_by_id((const char *) router_get_my_id_digest());
244  if (me && me->rs) {
245  is_fast = me->rs->is_fast;
246  is_exit = me->rs->is_exit;
247  is_authority = me->rs->is_authority;
248  is_stable = me->rs->is_stable;
249  is_running = me->rs->is_flagged_running;
250  is_v2_dir = me->rs->is_v2_dir;
251  is_guard = me->rs->is_possible_guard;
252  is_sybil = me->rs->is_sybil;
253  is_hs_dir = me->rs->is_hs_dir;
254  }
255 
256  const relay_metrics_entry_t *rentry =
258  metrics_store_entry_t *sentry = metrics_store_add(
259  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
260 
262  metrics_format_label("type", "Fast"));
263  metrics_store_entry_update(sentry, is_fast);
264 
265  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
266  rentry->help, 0, NULL);
268  metrics_format_label("type", "Exit"));
269  metrics_store_entry_update(sentry, is_exit);
270 
271  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
272  rentry->help, 0, NULL);
274  metrics_format_label("type", "Authority"));
275  metrics_store_entry_update(sentry, is_authority);
276 
277  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
278  rentry->help, 0, NULL);
280  metrics_format_label("type", "Stable"));
281  metrics_store_entry_update(sentry, is_stable);
282 
283  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
284  rentry->help, 0, NULL);
286  metrics_format_label("type", "HSDir"));
287  metrics_store_entry_update(sentry, is_hs_dir);
288 
289  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
290  rentry->help, 0, NULL);
292  metrics_format_label("type", "Running"));
293  metrics_store_entry_update(sentry, is_running);
294 
295  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
296  rentry->help, 0, NULL);
298  metrics_format_label("type", "V2Dir"));
299  metrics_store_entry_update(sentry, is_v2_dir);
300 
301  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
302  rentry->help, 0, NULL);
304  metrics_format_label("type", "Sybil"));
305  metrics_store_entry_update(sentry, is_sybil);
306 
307  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
308  rentry->help, 0, NULL);
310  metrics_format_label("type", "Guard"));
311  metrics_store_entry_update(sentry, is_guard);
312 }
313 
314 /** Fill function for the RELAY_METRICS_NUM_TRAFFIC metric. */
315 static void
317 {
318  const relay_metrics_entry_t *rentry =
320  metrics_store_entry_t *sentry = metrics_store_add(
321  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
322 
324  metrics_format_label("direction", "read"));
326 
327  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
328  rentry->help, 0, NULL);
330  metrics_format_label("direction", "written"));
332 }
333 
334 /** Fill function for the RELAY_METRICS_NUM_DOS metric. */
335 static void
337 {
339  metrics_store_entry_t *sentry = metrics_store_add(
340  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
341 
343  metrics_format_label("type", "circuit_rejected"));
344  metrics_store_entry_update(sentry, dos_get_num_cc_rejected());
345 
346  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
347  rentry->help, 0, NULL);
349  metrics_format_label("type", "circuit_killed_max_cell"));
351 
352  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
353  rentry->help, 0, NULL);
355  metrics_format_label("type", "circuit_killed_max_cell_outq"));
356  metrics_store_entry_update(sentry, stats_n_circ_max_cell_outq_reached);
357 
358  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
359  rentry->help, 0, NULL);
361  metrics_format_label("type", "marked_address"));
362  metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr());
363 
364  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
365  rentry->help, 0, NULL);
367  metrics_format_label("type", "marked_address_maxq"));
368  metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr_maxq());
369 
370  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
371  rentry->help, 0, NULL);
373  metrics_format_label("type", "conn_rejected"));
374  metrics_store_entry_update(sentry, dos_get_num_conn_addr_connect_rejected());
375 
376  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
377  rentry->help, 0, NULL);
379  metrics_format_label("type", "concurrent_conn_rejected"));
380  metrics_store_entry_update(sentry, dos_get_num_conn_addr_rejected());
381 
382  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
383  rentry->help, 0, NULL);
385  metrics_format_label("type", "single_hop_refused"));
386  metrics_store_entry_update(sentry, dos_get_num_single_hop_refused());
387 
388  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
389  rentry->help, 0, NULL);
391  metrics_format_label("type", "introduce2_rejected"));
393 }
394 
395 /** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */
396 static void
398 {
399  const relay_metrics_entry_t *rentry =
401 
402  metrics_store_entry_t *sentry = metrics_store_add(
403  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
405  metrics_format_label("state", "starvation"));
407  metrics_format_label("action", "rtt_reset"));
409 
410  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
411  rentry->help, 0, NULL);
413  metrics_format_label("state", "clock_stalls"));
415  metrics_format_label("action", "rtt_skipped"));
418 
419  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
420  rentry->help, 0, NULL);
422  metrics_format_label("state", "flow_control"));
424  metrics_format_label("action", "xoff_num_sent"));
427 
428  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
429  rentry->help, 0, NULL);
431  metrics_format_label("state", "flow_control"));
433  metrics_format_label("action", "xon_num_sent"));
435  cc_stats_flow_num_xon_sent);
436 
437  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
438  rentry->help, 0, NULL);
440  metrics_format_label("state", "cc_limits"));
442  metrics_format_label("action", "above_delta"));
444 
445  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
446  rentry->help, 0, NULL);
448  metrics_format_label("state", "cc_limits"));
450  metrics_format_label("action", "above_ss_cwnd_max"));
452 
453  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
454  rentry->help, 0, NULL);
456  metrics_format_label("state", "cc_limits"));
458  metrics_format_label("action", "below_ss_inc_floor"));
459  metrics_store_entry_update(sentry, cc_stats_vegas_below_ss_inc_floor);
460 
461  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
462  rentry->help, 0, NULL);
464  metrics_format_label("state", "cc_circuits"));
466  metrics_format_label("action", "circs_created"));
468 
469  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
470  rentry->help, 0, NULL);
472  metrics_format_label("state", "cc_circuits"));
474  metrics_format_label("action", "circs_closed"));
475  metrics_store_entry_update(sentry, cc_stats_circs_closed);
476 
477  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
478  rentry->help, 0, NULL);
480  metrics_format_label("state", "cc_circuits"));
482  metrics_format_label("action", "circs_exited_ss"));
483  metrics_store_entry_update(sentry, cc_stats_vegas_circ_exited_ss);
484 }
485 
486 /** Fill function for the RELAY_METRICS_CC_GAUGES metric. */
487 static void
489 {
490  const relay_metrics_entry_t *rentry =
492 
493  metrics_store_entry_t *sentry = metrics_store_add(
494  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
496  metrics_format_label("state", "slow_start_exit"));
498  metrics_format_label("action", "cwnd"));
501 
502  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
503  rentry->help, 0, NULL);
505  metrics_format_label("state", "slow_start_exit"));
507  metrics_format_label("action", "bdp"));
509  tor_llround(cc_stats_vegas_exit_ss_bdp_ma));
510 
511  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
512  rentry->help, 0, NULL);
514  metrics_format_label("state", "slow_start_exit"));
516  metrics_format_label("action", "inc"));
518  tor_llround(cc_stats_vegas_exit_ss_inc_ma));
519 
520  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
521  rentry->help, 0, NULL);
523  metrics_format_label("state", "on_circ_close"));
525  metrics_format_label("action", "cwnd"));
528 
529  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
530  rentry->help, 0, NULL);
532  metrics_format_label("state", "on_circ_close"));
534  metrics_format_label("action", "ss_cwnd"));
537 
538  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
539  rentry->help, 0, NULL);
541  metrics_format_label("state", "buffers"));
543  metrics_format_label("action", "xon_outbuf"));
545  tor_llround(cc_stats_flow_xon_outbuf_ma));
546 
547  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
548  rentry->help, 0, NULL);
550  metrics_format_label("state", "buffers"));
552  metrics_format_label("action", "xoff_outbuf"));
554  tor_llround(cc_stats_flow_xoff_outbuf_ma));
555 
556  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
557  rentry->help, 0, NULL);
559  metrics_format_label("state", "cc_backoff"));
561  metrics_format_label("action", "chan_blocked_pct"));
563  tor_llround(cc_stats_vegas_csig_blocked_ma));
564 
565  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
566  rentry->help, 0, NULL);
568  metrics_format_label("state", "cc_backoff"));
570  metrics_format_label("action", "gamma_drop"));
572  tor_llround(cc_stats_vegas_gamma_drop_ma));
573 
574  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
575  rentry->help, 0, NULL);
577  metrics_format_label("state", "cc_backoff"));
579  metrics_format_label("action", "delta_drop"));
581  tor_llround(cc_stats_vegas_delta_drop_ma));
582 
583  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
584  rentry->help, 0, NULL);
586  metrics_format_label("state", "cc_backoff"));
588  metrics_format_label("action", "ss_chan_blocked_pct"));
590  tor_llround(cc_stats_vegas_ss_csig_blocked_ma));
591 
592  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
593  rentry->help, 0, NULL);
595  metrics_format_label("state", "cc_cwnd_update"));
597  metrics_format_label("action", "alpha_pct"));
599  tor_llround(cc_stats_vegas_csig_alpha_ma));
600 
601  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
602  rentry->help, 0, NULL);
604  metrics_format_label("state", "cc_cwnd_update"));
606  metrics_format_label("action", "beta_pct"));
608  tor_llround(cc_stats_vegas_csig_beta_ma));
609 
610  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
611  rentry->help, 0, NULL);
613  metrics_format_label("state", "cc_cwnd_update"));
615  metrics_format_label("action", "delta_pct"));
617  tor_llround(cc_stats_vegas_csig_delta_ma));
618 
619  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
620  rentry->help, 0, NULL);
622  metrics_format_label("state", "cc_estimates"));
624  metrics_format_label("action", "ss_queue"));
626  tor_llround(cc_stats_vegas_ss_queue_ma));
627 
628  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
629  rentry->help, 0, NULL);
631  metrics_format_label("state", "cc_estimates"));
633  metrics_format_label("action", "queue"));
635  tor_llround(cc_stats_vegas_queue_ma));
636 
637  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
638  rentry->help, 0, NULL);
640  metrics_format_label("state", "cc_estimates"));
642  metrics_format_label("action", "bdp"));
644  tor_llround(cc_stats_vegas_bdp_ma));
645 }
646 
647 /** Helper: Fill in single stream metrics output. */
648 static void
649 fill_single_stream_value(metrics_store_entry_t *sentry, uint8_t cmd)
650 {
654 }
655 
656 /** Fill function for the RELAY_METRICS_NUM_STREAMS metric. */
657 static void
659 {
660  const relay_metrics_entry_t *rentry =
662  metrics_store_entry_t *sentry = metrics_store_add(
663  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
664  fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN);
665 
666  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
667  rentry->help, 0, NULL);
668  fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN_DIR);
669 
670  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
671  rentry->help, 0, NULL);
672  fill_single_stream_value(sentry, RELAY_COMMAND_RESOLVE);
673 }
674 
675 /** Helper: Fill in single connection metrics output. */
676 static void
677 fill_single_connection_value(metrics_store_entry_t *sentry,
678  unsigned int conn_type,
679  const char* direction,
680  const char* state,
681  int socket_family,
682  uint64_t value)
683 {
685  metrics_format_label("type", conn_type_to_string(conn_type)));
687  metrics_format_label("direction", direction));
689  metrics_format_label("state", state));
691  metrics_format_label("family", af_to_string(socket_family)));
692  metrics_store_entry_update(sentry, value);
693 }
694 
695 /** Fill function for the RELAY_METRICS_CONN_COUNTERS metric. */
696 static void
698 {
699  const relay_metrics_entry_t *rentry =
701 
702  for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
703  /* Type is unused. Ugly but else we clobber the output. */
704  if (i == 10) {
705  continue;
706  }
707  metrics_store_entry_t *sentry = metrics_store_add(
708  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
709  fill_single_connection_value(sentry, i, "initiated", "created", AF_INET,
710  rep_hist_get_conn_created(false, i, AF_INET));
711  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
712  rentry->help, 0, NULL);
713  fill_single_connection_value(sentry, i, "initiated", "created", AF_INET6,
714  rep_hist_get_conn_created(false, i,
715  AF_INET6));
716 
717  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
718  rentry->help, 0, NULL);
719  fill_single_connection_value(sentry, i, "received", "created", AF_INET,
720  rep_hist_get_conn_created(true, i, AF_INET));
721  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
722  rentry->help, 0, NULL);
723  fill_single_connection_value(sentry, i, "received", "created", AF_INET6,
724  rep_hist_get_conn_created(true, i, AF_INET6));
725 
726  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
727  rentry->help, 0, NULL);
728  fill_single_connection_value(sentry, i, "received", "rejected", AF_INET,
729  rep_hist_get_conn_rejected(i, AF_INET));
730  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
731  rentry->help, 0, NULL);
732  fill_single_connection_value(sentry, i, "received", "rejected", AF_INET6,
733  rep_hist_get_conn_rejected(i, AF_INET6));
734 
735  /* No counter for "initiated" + "rejected" connections exists. */
736  }
737 }
738 
739 /** Fill function for the RELAY_METRICS_CONN_GAUGES metric. */
740 static void
742 {
743  const relay_metrics_entry_t *rentry =
745 
746  for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
747  /* Type is unused. Ugly but else we clobber the output. */
748  if (i == 10) {
749  continue;
750  }
751  metrics_store_entry_t *sentry = metrics_store_add(
752  the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
753  fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET,
754  rep_hist_get_conn_opened(false, i, AF_INET));
755  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
756  rentry->help, 0, NULL);
757  fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET6,
758  rep_hist_get_conn_opened(false, i, AF_INET6));
759 
760  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
761  rentry->help, 0, NULL);
762  fill_single_connection_value(sentry, i, "received", "opened", AF_INET,
763  rep_hist_get_conn_opened(true, i, AF_INET));
764  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
765  rentry->help, 0, NULL);
766  fill_single_connection_value(sentry, i, "received", "opened", AF_INET6,
767  rep_hist_get_conn_opened(true, i, AF_INET6));
768  }
769 }
770 
771 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
772 static void
774 {
775  metrics_store_entry_t *sentry;
776  const relay_metrics_entry_t *rentry =
778 
779  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
780  rentry->help, 0, NULL);
782 }
783 
784 /* NOTE: Disable the record type label until libevent is fixed. */
785 #if 0
786 /** Helper array containing mapping for the name of the different DNS records
787  * and their corresponding libevent values. */
788 static struct dns_type {
789  const char *name;
790  uint8_t type;
791 } dns_types[] = {
792  { .name = "A", .type = DNS_IPv4_A },
793  { .name = "PTR", .type = DNS_PTR },
794  { .name = "AAAA", .type = DNS_IPv6_AAAA },
795 };
796 static const size_t num_dns_types = ARRAY_LENGTH(dns_types);
797 #endif
798 
799 /** Fill function for the RELAY_METRICS_NUM_DNS_ERRORS metrics. */
800 static void
802 {
803  metrics_store_entry_t *sentry;
804  const relay_metrics_entry_t *rentry =
806 
807  /* Helper array to map libeven DNS errors to their names and so we can
808  * iterate over this array to add all metrics. */
809  static struct dns_error {
810  const char *name;
811  uint8_t key;
812  } errors[] = {
813  { .name = "success", .key = DNS_ERR_NONE },
814  { .name = "format", .key = DNS_ERR_FORMAT },
815  { .name = "serverfailed", .key = DNS_ERR_SERVERFAILED },
816  { .name = "notexist", .key = DNS_ERR_NOTEXIST },
817  { .name = "notimpl", .key = DNS_ERR_NOTIMPL },
818  { .name = "refused", .key = DNS_ERR_REFUSED },
819  { .name = "truncated", .key = DNS_ERR_TRUNCATED },
820  { .name = "unknown", .key = DNS_ERR_UNKNOWN },
821  { .name = "tor_timeout", .key = DNS_ERR_TIMEOUT },
822  { .name = "shutdown", .key = DNS_ERR_SHUTDOWN },
823  { .name = "cancel", .key = DNS_ERR_CANCEL },
824  { .name = "nodata", .key = DNS_ERR_NODATA },
825  };
826  static const size_t num_errors = ARRAY_LENGTH(errors);
827 
828  /* NOTE: Disable the record type label until libevent is fixed. */
829 #if 0
830  for (size_t i = 0; i < num_dns_types; i++) {
831  /* Dup the label because metrics_format_label() returns a pointer to a
832  * string on the stack and we need that label for all metrics. */
833  char *record_label =
834  tor_strdup(metrics_format_label("record", dns_types[i].name));
835 
836  for (size_t j = 0; j < num_errors; j++) {
837  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
838  rentry->help, 0, NULL);
839  metrics_store_entry_add_label(sentry, record_label);
841  metrics_format_label("reason", errors[j].name));
843  rep_hist_get_n_dns_error(dns_types[i].type, errors[j].key));
844  }
845  tor_free(record_label);
846  }
847 #endif
848 
849  /* Put in the DNS errors, unfortunately not per-type for now. */
850  for (size_t j = 0; j < num_errors; j++) {
851  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
852  rentry->help, 0, NULL);
854  metrics_format_label("reason", errors[j].name));
856  rep_hist_get_n_dns_error(0, errors[j].key));
857  }
858 }
859 
860 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
861 static void
863 {
864  metrics_store_entry_t *sentry;
865  const relay_metrics_entry_t *rentry =
867 
868  /* NOTE: Disable the record type label until libevent is fixed (#40490). */
869 #if 0
870  for (size_t i = 0; i < num_dns_types; i++) {
871  /* Dup the label because metrics_format_label() returns a pointer to a
872  * string on the stack and we need that label for all metrics. */
873  char *record_label =
874  tor_strdup(metrics_format_label("record", dns_types[i].name));
875  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
876  rentry->help, 0, NULL);
877  metrics_store_entry_add_label(sentry, record_label);
879  rep_hist_get_n_dns_request(dns_types[i].type));
880  tor_free(record_label);
881  }
882 #endif
883 
884  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
885  rentry->help, 0, NULL);
887 }
888 
889 /** Fill function for the RELAY_METRICS_NUM_GLOBAL_RW_LIMIT metrics. */
890 static void
892 {
893  metrics_store_entry_t *sentry;
894  const relay_metrics_entry_t *rentry =
896 
897  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
898  rentry->help, 0, NULL);
900  metrics_format_label("side", "read"));
902 
903  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
904  rentry->help, 0, NULL);
906  metrics_format_label("side", "write"));
908 }
909 
910 /** Fill function for the RELAY_METRICS_NUM_SOCKETS metrics. */
911 static void
913 {
914  metrics_store_entry_t *sentry;
915  const relay_metrics_entry_t *rentry =
917 
918  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
919  rentry->help, 0, NULL);
921  metrics_format_label("state", "opened"));
923 
924  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
925  rentry->help, 0, NULL);
927 }
928 
929 /** Fill function for the RELAY_METRICS_NUM_ONIONSKINS metrics. */
930 static void
932 {
933  metrics_store_entry_t *sentry;
934  const relay_metrics_entry_t *rentry =
936 
937  for (uint16_t t = 0; t <= MAX_ONION_HANDSHAKE_TYPE; t++) {
938  /* Dup the label because metrics_format_label() returns a pointer to a
939  * string on the stack and we need that label for all metrics. */
940  char *type_label =
941  tor_strdup(metrics_format_label("type", handshake_type_to_str(t)));
942  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
943  rentry->help, 0, NULL);
944  metrics_store_entry_add_label(sentry, type_label);
946  metrics_format_label("action", "processed"));
949 
950  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
951  rentry->help, 0, NULL);
952  metrics_store_entry_add_label(sentry, type_label);
954  metrics_format_label("action", "dropped"));
957  tor_free(type_label);
958  }
959 }
960 
961 /** Fill function for the RELAY_METRICS_NUM_OOM_BYTES metrics. */
962 static void
964 {
965  metrics_store_entry_t *sentry;
966  const relay_metrics_entry_t *rentry =
968 
969  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
970  rentry->help, 0, NULL);
972  metrics_format_label("subsys", "cell"));
973  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_cell);
974 
975  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
976  rentry->help, 0, NULL);
978  metrics_format_label("subsys", "dns"));
980 
981  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
982  rentry->help, 0, NULL);
984  metrics_format_label("subsys", "geoip"));
985  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_geoip);
986 
987  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
988  rentry->help, 0, NULL);
990  metrics_format_label("subsys", "hsdir"));
991  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_hsdir);
992 }
993 
994 /** Reset the global store and fill it with all the metrics from base_metrics
995  * and their associated values.
996  *
997  * To pull this off, every metrics has a "fill" function that is called and in
998  * charge of adding the metrics to the store, appropriate labels and finally
999  * updating the value to report. */
1000 static void
1002 {
1003  /* Reset the current store, we are about to fill it with all the things. */
1005 
1006  /* Call the fill function for each metrics. */
1007  for (size_t i = 0; i < num_base_metrics; i++) {
1008  if (BUG(!base_metrics[i].fill_fn)) {
1009  continue;
1010  }
1011  base_metrics[i].fill_fn();
1012  }
1013 }
1014 
1015 /** Return a list of all the relay metrics stores. This is the
1016  * function attached to the .get_metrics() member of the subsys_t. */
1017 const smartlist_t *
1019 {
1020  /* We can't have the caller to free the returned list so keep it static,
1021  * simply update it. */
1022  static smartlist_t *stores_list = NULL;
1023 
1024  /* We dynamically fill the store with all the metrics upon a request. The
1025  * reason for this is because the exposed metrics of a relay are often
1026  * internal counters in the fast path and thus we fetch the value when a
1027  * metrics port request arrives instead of keeping a local metrics store of
1028  * those values. */
1029  fill_store();
1030 
1031  if (!stores_list) {
1032  stores_list = smartlist_new();
1033  smartlist_add(stores_list, the_store);
1034  }
1035 
1036  return stores_list;
1037 }
1038 
1039 /** Initialize the relay metrics. */
1040 void
1042 {
1043  if (BUG(the_store)) {
1044  return;
1045  }
1047 }
1048 
1049 /** Free the relay metrics. */
1050 void
1052 {
1053  if (!the_store) {
1054  return;
1055  }
1056  /* NULL is set with this call. */
1057  metrics_store_free(the_store);
1058 }
double cc_stats_circ_close_ss_cwnd_ma
Definition: circuitlist.c:155
smartlist_t * circuit_get_global_list(void)
Definition: circuitlist.c:705
double cc_stats_circ_close_cwnd_ma
Definition: circuitlist.c:153
Header file for circuitlist.c.
#define ARRAY_LENGTH(x)
const char * name
Definition: config.c:2443
Header file for config.c.
uint64_t congestion_control_get_num_clock_stalls(void)
uint64_t congestion_control_get_num_rtt_reset(void)
uint64_t cc_stats_circs_created
Public APIs for congestion control.
uint64_t cc_stats_flow_num_xoff_sent
APIs for stream flow control on congestion controlled circuits.
uint64_t cc_stats_vegas_above_ss_cwnd_max
uint64_t cc_stats_vegas_above_delta
double cc_stats_vegas_exit_ss_cwnd_ma
Private-ish APIs for the TOR_VEGAS congestion control algorithm.
const char * conn_type_to_string(int type)
Definition: connection.c:271
Header file for connection.c.
int64_t tor_llround(double d)
Definition: fp.c:46
Header for fp.c.
uint64_t hs_dos_get_intro2_rejected_count(void)
Definition: hs_dos.c:218
Header file containing denial of service defenses for the HS subsystem for all versions.
uint64_t get_bytes_read(void)
Definition: mainloop.c:455
uint64_t get_bytes_written(void)
Definition: mainloop.c:465
Header file for mainloop.c.
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:56
const char * metrics_format_label(const char *key, const char *value)
metrics_store_entry_t * metrics_store_add(metrics_store_t *store, metrics_type_t type, const char *name, const char *help, size_t bucket_count, const int64_t *buckets)
metrics_store_t * metrics_store_new(void)
Definition: metrics_store.c:74
void metrics_store_reset(metrics_store_t *store)
Header for lib/metrics/metrics_store.c.
void metrics_store_entry_update(metrics_store_entry_t *entry, const int64_t value)
void metrics_store_entry_add_label(metrics_store_entry_t *entry, const char *label)
Node information structure.
const node_t * node_get_by_id(const char *identity_digest)
Definition: nodelist.c:226
Header file for nodelist.c.
Master header file for Tor-specific functionality.
uint64_t oom_stats_n_bytes_removed_dns
Definition: relay.c:2774
uint64_t stats_n_circ_max_cell_reached
Definition: relay.c:130
const char * relay_command_to_string(uint8_t command)
Definition: relay.c:507
Header file for relay.c.
static void fill_oom_values(void)
static const char * handshake_type_to_str(const uint16_t type)
static void fill_traffic_values(void)
static void fill_store(void)
static void fill_streams_values(void)
static void fill_tcp_exhaustion_values(void)
static void fill_dns_query_values(void)
static void fill_onionskins_values(void)
static void fill_dos_values(void)
static void fill_dns_error_values(void)
static void fill_conn_gauge_values(void)
static void fill_conn_counter_values(void)
void relay_metrics_init(void)
static void fill_single_stream_value(metrics_store_entry_t *sentry, uint8_t cmd)
static void fill_single_connection_value(metrics_store_entry_t *sentry, unsigned int conn_type, const char *direction, const char *state, int socket_family, uint64_t value)
static void fill_circuits_values(void)
static void fill_global_bw_limit_values(void)
const smartlist_t * relay_metrics_get_stores(void)
static void fill_cc_counters_values(void)
void relay_metrics_free(void)
static const char * af_to_string(const int af)
static void fill_relay_flags(void)
static const relay_metrics_entry_t base_metrics[]
Definition: relay_metrics.c:63
static void fill_cc_gauges_values(void)
static void fill_socket_values(void)
static metrics_store_t * the_store
Header for feature/relay/relay_metrics.c.
@ RELAY_METRICS_CC_GAUGES
Definition: relay_metrics.h:41
@ RELAY_METRICS_NUM_GLOBAL_RW_LIMIT
Definition: relay_metrics.h:25
@ RELAY_METRICS_NUM_STREAMS
Definition: relay_metrics.h:37
@ RELAY_METRICS_NUM_CIRCUITS
Definition: relay_metrics.h:49
@ RELAY_METRICS_NUM_TCP_EXHAUSTION
Definition: relay_metrics.h:31
@ RELAY_METRICS_NUM_SOCKETS
Definition: relay_metrics.h:23
@ RELAY_METRICS_NUM_DOS
Definition: relay_metrics.h:43
@ RELAY_METRICS_CONN_COUNTERS
Definition: relay_metrics.h:33
@ RELAY_METRICS_CC_COUNTERS
Definition: relay_metrics.h:39
@ RELAY_METRICS_CONN_GAUGES
Definition: relay_metrics.h:35
@ RELAY_METRICS_NUM_ONIONSKINS
Definition: relay_metrics.h:21
@ RELAY_METRICS_NUM_DNS
Definition: relay_metrics.h:27
@ RELAY_METRICS_RELAY_FLAGS
Definition: relay_metrics.h:47
@ RELAY_METRICS_NUM_DNS_ERRORS
Definition: relay_metrics.h:29
@ RELAY_METRICS_NUM_OOM_BYTES
Definition: relay_metrics.h:19
@ RELAY_METRICS_NUM_TRAFFIC
Definition: relay_metrics.h:45
uint64_t rep_hist_get_conn_created(bool from_listener, unsigned int type, int af)
Definition: rephist.c:1774
uint64_t rep_hist_get_n_dns_request(int type)
Definition: rephist.c:355
uint64_t rep_hist_get_conn_rejected(unsigned int type, int af)
Definition: rephist.c:1806
uint64_t rep_hist_get_circuit_n_handshake_assigned(uint16_t type)
Definition: rephist.c:2423
uint64_t rep_hist_get_conn_opened(bool from_listener, unsigned int type, int af)
Definition: rephist.c:1790
uint64_t rep_hist_get_n_dns_error(int type, uint8_t error)
Definition: rephist.c:314
uint64_t rep_hist_get_n_read_limit_reached(void)
Definition: rephist.c:458
uint64_t rep_hist_get_n_tcp_exhaustion(void)
Definition: rephist.c:583
uint64_t rep_hist_get_circuit_n_handshake_dropped(uint16_t type)
Definition: rephist.c:2430
uint64_t rep_hist_get_exit_stream_seen(unsigned int cmd)
Definition: rephist.c:1673
uint64_t rep_hist_get_n_write_limit_reached(void)
Definition: rephist.c:465
Header file for rephist.c.
const uint8_t * router_get_my_id_digest(void)
Definition: router.c:1747
Header file for router.c.
Routerstatus (consensus entry) structure.
Header for smartlist.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
int get_max_sockets(void)
Definition: socket.c:98
int get_n_open_sockets(void)
Definition: socket.c:440
Definition: node_st.h:34
Definition: relay_metrics.h:53
unsigned int is_sybil
unsigned int is_hs_dir
unsigned int is_possible_guard
unsigned int is_stable
unsigned int is_flagged_running
unsigned int is_exit
unsigned int is_authority
unsigned int is_fast
Macros to manage assertions, fatal and non-fatal.