Fixed REND1 metric label value
[tor.git] / src / feature / relay / relay_metrics.c
blobd08f01838b77f382a31093b3df9e93f72ca9659e
1 /* Copyright (c) 2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * @file relay_metrics.c
6 * @brief Relay metrics exposed through the MetricsPort
7 **/
9 #define RELAY_METRICS_ENTRY_PRIVATE
11 #include "orconfig.h"
13 #include "core/or/or.h"
14 #include "core/mainloop/connection.h"
15 #include "core/mainloop/mainloop.h"
16 #include "core/or/congestion_control_common.h"
17 #include "core/or/congestion_control_vegas.h"
18 #include "core/or/congestion_control_flow.h"
19 #include "core/or/circuitlist.h"
20 #include "core/or/dos.h"
21 #include "core/or/relay.h"
23 #include "app/config/config.h"
25 #include "lib/container/smartlist.h"
26 #include "lib/log/util_bug.h"
27 #include "lib/malloc/malloc.h"
28 #include "lib/math/fp.h"
29 #include "lib/metrics/metrics_store.h"
31 #include "feature/hs/hs_dos.h"
32 #include "feature/nodelist/nodelist.h"
33 #include "feature/nodelist/node_st.h"
34 #include "feature/nodelist/routerstatus_st.h"
35 #include "feature/nodelist/torcert.h"
36 #include "feature/relay/relay_metrics.h"
37 #include "feature/relay/router.h"
38 #include "feature/relay/routerkeys.h"
39 #include "feature/stats/rephist.h"
41 #include <event2/dns.h>
43 /** Declarations of each fill function for metrics defined in base_metrics. */
44 static void fill_cc_counters_values(void);
45 static void fill_cc_gauges_values(void);
46 static void fill_circuits_values(void);
47 static void fill_conn_counter_values(void);
48 static void fill_conn_gauge_values(void);
49 static void fill_dns_error_values(void);
50 static void fill_dns_query_values(void);
51 static void fill_dos_values(void);
52 static void fill_global_bw_limit_values(void);
53 static void fill_socket_values(void);
54 static void fill_onionskins_values(void);
55 static void fill_oom_values(void);
56 static void fill_streams_values(void);
57 static void fill_relay_flags(void);
58 static void fill_tcp_exhaustion_values(void);
59 static void fill_traffic_values(void);
60 static void fill_signing_cert_expiry(void);
62 static void fill_est_intro_cells(void);
63 static void fill_est_rend_cells(void);
64 static void fill_intro1_cells(void);
65 static void fill_rend1_cells(void);
67 /** The base metrics that is a static array of metrics added to the metrics
68 * store.
70 * The key member MUST be also the index of the entry in the array. */
71 static const relay_metrics_entry_t base_metrics[] =
74 .key = RELAY_METRICS_NUM_OOM_BYTES,
75 .type = METRICS_TYPE_COUNTER,
76 .name = METRICS_NAME(relay_load_oom_bytes_total),
77 .help = "Total number of bytes the OOM has freed by subsystem",
78 .fill_fn = fill_oom_values,
81 .key = RELAY_METRICS_NUM_ONIONSKINS,
82 .type = METRICS_TYPE_COUNTER,
83 .name = METRICS_NAME(relay_load_onionskins_total),
84 .help = "Total number of onionskins handled",
85 .fill_fn = fill_onionskins_values,
88 .key = RELAY_METRICS_NUM_SOCKETS,
89 .type = METRICS_TYPE_GAUGE,
90 .name = METRICS_NAME(relay_load_socket_total),
91 .help = "Total number of sockets",
92 .fill_fn = fill_socket_values,
95 .key = RELAY_METRICS_NUM_GLOBAL_RW_LIMIT,
96 .type = METRICS_TYPE_COUNTER,
97 .name = METRICS_NAME(relay_load_global_rate_limit_reached_total),
98 .help = "Total number of global connection bucket limit reached",
99 .fill_fn = fill_global_bw_limit_values,
102 .key = RELAY_METRICS_NUM_DNS,
103 .type = METRICS_TYPE_COUNTER,
104 .name = METRICS_NAME(relay_exit_dns_query_total),
105 .help = "Total number of DNS queries done by this relay",
106 .fill_fn = fill_dns_query_values,
109 .key = RELAY_METRICS_NUM_DNS_ERRORS,
110 .type = METRICS_TYPE_COUNTER,
111 .name = METRICS_NAME(relay_exit_dns_error_total),
112 .help = "Total number of DNS errors encountered by this relay",
113 .fill_fn = fill_dns_error_values,
116 .key = RELAY_METRICS_NUM_TCP_EXHAUSTION,
117 .type = METRICS_TYPE_COUNTER,
118 .name = METRICS_NAME(relay_load_tcp_exhaustion_total),
119 .help = "Total number of times we ran out of TCP ports",
120 .fill_fn = fill_tcp_exhaustion_values,
123 .key = RELAY_METRICS_CONN_COUNTERS,
124 .type = METRICS_TYPE_COUNTER,
125 .name = METRICS_NAME(relay_connections_total),
126 .help = "Total number of created/rejected connections",
127 .fill_fn = fill_conn_counter_values,
130 .key = RELAY_METRICS_CONN_GAUGES,
131 .type = METRICS_TYPE_GAUGE,
132 .name = METRICS_NAME(relay_connections),
133 .help = "Total number of opened connections",
134 .fill_fn = fill_conn_gauge_values,
137 .key = RELAY_METRICS_NUM_STREAMS,
138 .type = METRICS_TYPE_COUNTER,
139 .name = METRICS_NAME(relay_streams_total),
140 .help = "Total number of streams",
141 .fill_fn = fill_streams_values,
144 .key = RELAY_METRICS_CC_COUNTERS,
145 .type = METRICS_TYPE_COUNTER,
146 .name = METRICS_NAME(relay_congestion_control_total),
147 .help = "Congestion control related counters",
148 .fill_fn = fill_cc_counters_values,
151 .key = RELAY_METRICS_CC_GAUGES,
152 .type = METRICS_TYPE_GAUGE,
153 .name = METRICS_NAME(relay_congestion_control),
154 .help = "Congestion control related gauges",
155 .fill_fn = fill_cc_gauges_values,
158 .key = RELAY_METRICS_NUM_DOS,
159 .type = METRICS_TYPE_COUNTER,
160 .name = METRICS_NAME(relay_dos_total),
161 .help = "Denial of Service defenses related counters",
162 .fill_fn = fill_dos_values,
165 .key = RELAY_METRICS_NUM_TRAFFIC,
166 .type = METRICS_TYPE_COUNTER,
167 .name = METRICS_NAME(relay_traffic_bytes),
168 .help = "Traffic related counters",
169 .fill_fn = fill_traffic_values,
172 .key = RELAY_METRICS_RELAY_FLAGS,
173 .type = METRICS_TYPE_GAUGE,
174 .name = METRICS_NAME(relay_flag),
175 .help = "Relay flags from consensus",
176 .fill_fn = fill_relay_flags,
179 .key = RELAY_METRICS_NUM_CIRCUITS,
180 .type = METRICS_TYPE_GAUGE,
181 .name = METRICS_NAME(relay_circuits_total),
182 .help = "Total number of circuits",
183 .fill_fn = fill_circuits_values,
186 .key = RELAY_METRICS_SIGNING_CERT_EXPIRY,
187 .type = METRICS_TYPE_GAUGE,
188 .name = METRICS_NAME(relay_signing_cert_expiry_timestamp),
189 .help = "Timestamp at which the current online keys will expire",
190 .fill_fn = fill_signing_cert_expiry,
193 .key = RELAY_METRICS_NUM_EST_REND,
194 .type = METRICS_TYPE_COUNTER,
195 .name = METRICS_NAME(relay_est_rend_total),
196 .help = "Total number of EST_REND cells we received",
197 .fill_fn = fill_est_rend_cells,
200 .key = RELAY_METRICS_NUM_EST_INTRO,
201 .type = METRICS_TYPE_COUNTER,
202 .name = METRICS_NAME(relay_est_intro_total),
203 .help = "Total number of EST_INTRO cells we received",
204 .fill_fn = fill_est_intro_cells,
207 .key = RELAY_METRICS_NUM_INTRO1_CELLS,
208 .type = METRICS_TYPE_COUNTER,
209 .name = METRICS_NAME(relay_intro1_total),
210 .help = "Total number of INTRO1 cells we received",
211 .fill_fn = fill_intro1_cells,
214 .key = RELAY_METRICS_NUM_REND1_CELLS,
215 .type = METRICS_TYPE_COUNTER,
216 .name = METRICS_NAME(relay_rend1_total),
217 .help = "Total number of REND1 cells we received",
218 .fill_fn = fill_rend1_cells,
221 static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
223 /** The only and single store of all the relay metrics. */
224 static metrics_store_t *the_store;
226 /** Helper function to convert an handshake type into a string. */
227 static inline const char *
228 handshake_type_to_str(const uint16_t type)
230 switch (type) {
231 case ONION_HANDSHAKE_TYPE_TAP:
232 return "tap";
233 case ONION_HANDSHAKE_TYPE_FAST:
234 return "fast";
235 case ONION_HANDSHAKE_TYPE_NTOR:
236 return "ntor";
237 case ONION_HANDSHAKE_TYPE_NTOR_V3:
238 return "ntor_v3";
239 default:
240 // LCOV_EXCL_START
241 tor_assert_unreached();
242 // LCOV_EXCL_STOP
246 /** Helper function to convert a socket family type into a string. */
247 static inline const char *
248 af_to_string(const int af)
250 switch (af) {
251 case AF_INET:
252 return "ipv4";
253 case AF_INET6:
254 return "ipv6";
255 case AF_UNIX:
256 return "unix";
257 default:
258 return "<unknown>";
262 /** Fill function for the RELAY_METRICS_NUM_CIRCUITS metric. */
263 static void
264 fill_circuits_values(void)
266 const relay_metrics_entry_t *rentry =
267 &base_metrics[RELAY_METRICS_NUM_CIRCUITS];
268 metrics_store_entry_t *sentry = metrics_store_add(
269 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
271 metrics_store_entry_add_label(sentry,
272 metrics_format_label("state", "opened"));
273 metrics_store_entry_update(sentry,
274 smartlist_len(circuit_get_global_list()));
277 /** Fill function for the RELAY_METRICS_RELAY_FLAGS metric. */
278 static void
279 fill_relay_flags(void)
281 uint8_t is_fast = 0, is_exit = 0, is_authority = 0, is_stable = 0;
282 uint8_t is_running = 0, is_v2_dir = 0, is_guard = 0, is_sybil = 0;
283 uint8_t is_hs_dir = 0;
285 const node_t *me =
286 node_get_by_id((const char *) router_get_my_id_digest());
287 if (me && me->rs) {
288 is_fast = me->rs->is_fast;
289 is_exit = me->rs->is_exit;
290 is_authority = me->rs->is_authority;
291 is_stable = me->rs->is_stable;
292 is_running = me->rs->is_flagged_running;
293 is_v2_dir = me->rs->is_v2_dir;
294 is_guard = me->rs->is_possible_guard;
295 is_sybil = me->rs->is_sybil;
296 is_hs_dir = me->rs->is_hs_dir;
299 const relay_metrics_entry_t *rentry =
300 &base_metrics[RELAY_METRICS_RELAY_FLAGS];
301 metrics_store_entry_t *sentry = metrics_store_add(
302 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
304 metrics_store_entry_add_label(sentry,
305 metrics_format_label("type", "Fast"));
306 metrics_store_entry_update(sentry, is_fast);
308 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
309 rentry->help, 0, NULL);
310 metrics_store_entry_add_label(sentry,
311 metrics_format_label("type", "Exit"));
312 metrics_store_entry_update(sentry, is_exit);
314 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
315 rentry->help, 0, NULL);
316 metrics_store_entry_add_label(sentry,
317 metrics_format_label("type", "Authority"));
318 metrics_store_entry_update(sentry, is_authority);
320 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
321 rentry->help, 0, NULL);
322 metrics_store_entry_add_label(sentry,
323 metrics_format_label("type", "Stable"));
324 metrics_store_entry_update(sentry, is_stable);
326 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
327 rentry->help, 0, NULL);
328 metrics_store_entry_add_label(sentry,
329 metrics_format_label("type", "HSDir"));
330 metrics_store_entry_update(sentry, is_hs_dir);
332 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
333 rentry->help, 0, NULL);
334 metrics_store_entry_add_label(sentry,
335 metrics_format_label("type", "Running"));
336 metrics_store_entry_update(sentry, is_running);
338 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
339 rentry->help, 0, NULL);
340 metrics_store_entry_add_label(sentry,
341 metrics_format_label("type", "V2Dir"));
342 metrics_store_entry_update(sentry, is_v2_dir);
344 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
345 rentry->help, 0, NULL);
346 metrics_store_entry_add_label(sentry,
347 metrics_format_label("type", "Sybil"));
348 metrics_store_entry_update(sentry, is_sybil);
350 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
351 rentry->help, 0, NULL);
352 metrics_store_entry_add_label(sentry,
353 metrics_format_label("type", "Guard"));
354 metrics_store_entry_update(sentry, is_guard);
357 /** Fill function for the RELAY_METRICS_NUM_TRAFFIC metric. */
358 static void
359 fill_traffic_values(void)
361 const relay_metrics_entry_t *rentry =
362 &base_metrics[RELAY_METRICS_NUM_TRAFFIC];
363 metrics_store_entry_t *sentry = metrics_store_add(
364 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
366 metrics_store_entry_add_label(sentry,
367 metrics_format_label("direction", "read"));
368 metrics_store_entry_update(sentry, get_bytes_read());
370 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
371 rentry->help, 0, NULL);
372 metrics_store_entry_add_label(sentry,
373 metrics_format_label("direction", "written"));
374 metrics_store_entry_update(sentry, get_bytes_written());
377 /** Fill function for the RELAY_METRICS_NUM_DOS metric. */
378 static void
379 fill_dos_values(void)
381 const relay_metrics_entry_t *rentry = &base_metrics[RELAY_METRICS_NUM_DOS];
382 metrics_store_entry_t *sentry = metrics_store_add(
383 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
385 metrics_store_entry_add_label(sentry,
386 metrics_format_label("type", "circuit_rejected"));
387 metrics_store_entry_update(sentry, dos_get_num_cc_rejected());
389 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
390 rentry->help, 0, NULL);
391 metrics_store_entry_add_label(sentry,
392 metrics_format_label("type", "circuit_killed_max_cell"));
393 metrics_store_entry_update(sentry, stats_n_circ_max_cell_reached);
395 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
396 rentry->help, 0, NULL);
397 metrics_store_entry_add_label(sentry,
398 metrics_format_label("type", "circuit_killed_max_cell_outq"));
399 metrics_store_entry_update(sentry, stats_n_circ_max_cell_outq_reached);
401 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
402 rentry->help, 0, NULL);
403 metrics_store_entry_add_label(sentry,
404 metrics_format_label("type", "marked_address"));
405 metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr());
407 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
408 rentry->help, 0, NULL);
409 metrics_store_entry_add_label(sentry,
410 metrics_format_label("type", "marked_address_maxq"));
411 metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr_maxq());
413 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
414 rentry->help, 0, NULL);
415 metrics_store_entry_add_label(sentry,
416 metrics_format_label("type", "conn_rejected"));
417 metrics_store_entry_update(sentry, dos_get_num_conn_addr_connect_rejected());
419 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
420 rentry->help, 0, NULL);
421 metrics_store_entry_add_label(sentry,
422 metrics_format_label("type", "concurrent_conn_rejected"));
423 metrics_store_entry_update(sentry, dos_get_num_conn_addr_rejected());
425 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
426 rentry->help, 0, NULL);
427 metrics_store_entry_add_label(sentry,
428 metrics_format_label("type", "single_hop_refused"));
429 metrics_store_entry_update(sentry, dos_get_num_single_hop_refused());
431 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
432 rentry->help, 0, NULL);
433 metrics_store_entry_add_label(sentry,
434 metrics_format_label("type", "introduce2_rejected"));
435 metrics_store_entry_update(sentry, hs_dos_get_intro2_rejected_count());
438 /** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */
439 static void
440 fill_cc_counters_values(void)
442 const relay_metrics_entry_t *rentry =
443 &base_metrics[RELAY_METRICS_CC_COUNTERS];
445 metrics_store_entry_t *sentry = metrics_store_add(
446 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
447 metrics_store_entry_add_label(sentry,
448 metrics_format_label("state", "starvation"));
449 metrics_store_entry_add_label(sentry,
450 metrics_format_label("action", "rtt_reset"));
451 metrics_store_entry_update(sentry, congestion_control_get_num_rtt_reset());
453 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
454 rentry->help, 0, NULL);
455 metrics_store_entry_add_label(sentry,
456 metrics_format_label("state", "clock_stalls"));
457 metrics_store_entry_add_label(sentry,
458 metrics_format_label("action", "rtt_skipped"));
459 metrics_store_entry_update(sentry,
460 congestion_control_get_num_clock_stalls());
462 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
463 rentry->help, 0, NULL);
464 metrics_store_entry_add_label(sentry,
465 metrics_format_label("state", "flow_control"));
466 metrics_store_entry_add_label(sentry,
467 metrics_format_label("action", "xoff_num_sent"));
468 metrics_store_entry_update(sentry,
469 cc_stats_flow_num_xoff_sent);
471 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
472 rentry->help, 0, NULL);
473 metrics_store_entry_add_label(sentry,
474 metrics_format_label("state", "flow_control"));
475 metrics_store_entry_add_label(sentry,
476 metrics_format_label("action", "xon_num_sent"));
477 metrics_store_entry_update(sentry,
478 cc_stats_flow_num_xon_sent);
480 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
481 rentry->help, 0, NULL);
482 metrics_store_entry_add_label(sentry,
483 metrics_format_label("state", "cc_limits"));
484 metrics_store_entry_add_label(sentry,
485 metrics_format_label("action", "above_delta"));
486 metrics_store_entry_update(sentry, cc_stats_vegas_above_delta);
488 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
489 rentry->help, 0, NULL);
490 metrics_store_entry_add_label(sentry,
491 metrics_format_label("state", "cc_limits"));
492 metrics_store_entry_add_label(sentry,
493 metrics_format_label("action", "above_ss_cwnd_max"));
494 metrics_store_entry_update(sentry, cc_stats_vegas_above_ss_cwnd_max);
496 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
497 rentry->help, 0, NULL);
498 metrics_store_entry_add_label(sentry,
499 metrics_format_label("state", "cc_limits"));
500 metrics_store_entry_add_label(sentry,
501 metrics_format_label("action", "below_ss_inc_floor"));
502 metrics_store_entry_update(sentry, cc_stats_vegas_below_ss_inc_floor);
504 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
505 rentry->help, 0, NULL);
506 metrics_store_entry_add_label(sentry,
507 metrics_format_label("state", "cc_circuits"));
508 metrics_store_entry_add_label(sentry,
509 metrics_format_label("action", "circs_created"));
510 metrics_store_entry_update(sentry, cc_stats_circs_created);
512 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
513 rentry->help, 0, NULL);
514 metrics_store_entry_add_label(sentry,
515 metrics_format_label("state", "cc_circuits"));
516 metrics_store_entry_add_label(sentry,
517 metrics_format_label("action", "circs_closed"));
518 metrics_store_entry_update(sentry, cc_stats_circs_closed);
520 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
521 rentry->help, 0, NULL);
522 metrics_store_entry_add_label(sentry,
523 metrics_format_label("state", "cc_circuits"));
524 metrics_store_entry_add_label(sentry,
525 metrics_format_label("action", "circs_exited_ss"));
526 metrics_store_entry_update(sentry, cc_stats_vegas_circ_exited_ss);
529 /** Fill function for the RELAY_METRICS_CC_GAUGES metric. */
530 static void
531 fill_cc_gauges_values(void)
533 const relay_metrics_entry_t *rentry =
534 &base_metrics[RELAY_METRICS_CC_GAUGES];
536 metrics_store_entry_t *sentry = metrics_store_add(
537 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
538 metrics_store_entry_add_label(sentry,
539 metrics_format_label("state", "slow_start_exit"));
540 metrics_store_entry_add_label(sentry,
541 metrics_format_label("action", "cwnd"));
542 metrics_store_entry_update(sentry,
543 tor_llround(cc_stats_vegas_exit_ss_cwnd_ma));
545 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
546 rentry->help, 0, NULL);
547 metrics_store_entry_add_label(sentry,
548 metrics_format_label("state", "slow_start_exit"));
549 metrics_store_entry_add_label(sentry,
550 metrics_format_label("action", "bdp"));
551 metrics_store_entry_update(sentry,
552 tor_llround(cc_stats_vegas_exit_ss_bdp_ma));
554 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
555 rentry->help, 0, NULL);
556 metrics_store_entry_add_label(sentry,
557 metrics_format_label("state", "slow_start_exit"));
558 metrics_store_entry_add_label(sentry,
559 metrics_format_label("action", "inc"));
560 metrics_store_entry_update(sentry,
561 tor_llround(cc_stats_vegas_exit_ss_inc_ma));
563 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
564 rentry->help, 0, NULL);
565 metrics_store_entry_add_label(sentry,
566 metrics_format_label("state", "on_circ_close"));
567 metrics_store_entry_add_label(sentry,
568 metrics_format_label("action", "cwnd"));
569 metrics_store_entry_update(sentry,
570 tor_llround(cc_stats_circ_close_cwnd_ma));
572 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
573 rentry->help, 0, NULL);
574 metrics_store_entry_add_label(sentry,
575 metrics_format_label("state", "on_circ_close"));
576 metrics_store_entry_add_label(sentry,
577 metrics_format_label("action", "ss_cwnd"));
578 metrics_store_entry_update(sentry,
579 tor_llround(cc_stats_circ_close_ss_cwnd_ma));
581 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
582 rentry->help, 0, NULL);
583 metrics_store_entry_add_label(sentry,
584 metrics_format_label("state", "buffers"));
585 metrics_store_entry_add_label(sentry,
586 metrics_format_label("action", "xon_outbuf"));
587 metrics_store_entry_update(sentry,
588 tor_llround(cc_stats_flow_xon_outbuf_ma));
590 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
591 rentry->help, 0, NULL);
592 metrics_store_entry_add_label(sentry,
593 metrics_format_label("state", "buffers"));
594 metrics_store_entry_add_label(sentry,
595 metrics_format_label("action", "xoff_outbuf"));
596 metrics_store_entry_update(sentry,
597 tor_llround(cc_stats_flow_xoff_outbuf_ma));
599 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
600 rentry->help, 0, NULL);
601 metrics_store_entry_add_label(sentry,
602 metrics_format_label("state", "cc_backoff"));
603 metrics_store_entry_add_label(sentry,
604 metrics_format_label("action", "chan_blocked_pct"));
605 metrics_store_entry_update(sentry,
606 tor_llround(cc_stats_vegas_csig_blocked_ma));
608 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
609 rentry->help, 0, NULL);
610 metrics_store_entry_add_label(sentry,
611 metrics_format_label("state", "cc_backoff"));
612 metrics_store_entry_add_label(sentry,
613 metrics_format_label("action", "gamma_drop"));
614 metrics_store_entry_update(sentry,
615 tor_llround(cc_stats_vegas_gamma_drop_ma));
617 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
618 rentry->help, 0, NULL);
619 metrics_store_entry_add_label(sentry,
620 metrics_format_label("state", "cc_backoff"));
621 metrics_store_entry_add_label(sentry,
622 metrics_format_label("action", "delta_drop"));
623 metrics_store_entry_update(sentry,
624 tor_llround(cc_stats_vegas_delta_drop_ma));
626 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
627 rentry->help, 0, NULL);
628 metrics_store_entry_add_label(sentry,
629 metrics_format_label("state", "cc_backoff"));
630 metrics_store_entry_add_label(sentry,
631 metrics_format_label("action", "ss_chan_blocked_pct"));
632 metrics_store_entry_update(sentry,
633 tor_llround(cc_stats_vegas_ss_csig_blocked_ma));
635 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
636 rentry->help, 0, NULL);
637 metrics_store_entry_add_label(sentry,
638 metrics_format_label("state", "cc_cwnd_update"));
639 metrics_store_entry_add_label(sentry,
640 metrics_format_label("action", "alpha_pct"));
641 metrics_store_entry_update(sentry,
642 tor_llround(cc_stats_vegas_csig_alpha_ma));
644 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
645 rentry->help, 0, NULL);
646 metrics_store_entry_add_label(sentry,
647 metrics_format_label("state", "cc_cwnd_update"));
648 metrics_store_entry_add_label(sentry,
649 metrics_format_label("action", "beta_pct"));
650 metrics_store_entry_update(sentry,
651 tor_llround(cc_stats_vegas_csig_beta_ma));
653 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
654 rentry->help, 0, NULL);
655 metrics_store_entry_add_label(sentry,
656 metrics_format_label("state", "cc_cwnd_update"));
657 metrics_store_entry_add_label(sentry,
658 metrics_format_label("action", "delta_pct"));
659 metrics_store_entry_update(sentry,
660 tor_llround(cc_stats_vegas_csig_delta_ma));
662 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
663 rentry->help, 0, NULL);
664 metrics_store_entry_add_label(sentry,
665 metrics_format_label("state", "cc_estimates"));
666 metrics_store_entry_add_label(sentry,
667 metrics_format_label("action", "ss_queue"));
668 metrics_store_entry_update(sentry,
669 tor_llround(cc_stats_vegas_ss_queue_ma));
671 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
672 rentry->help, 0, NULL);
673 metrics_store_entry_add_label(sentry,
674 metrics_format_label("state", "cc_estimates"));
675 metrics_store_entry_add_label(sentry,
676 metrics_format_label("action", "queue"));
677 metrics_store_entry_update(sentry,
678 tor_llround(cc_stats_vegas_queue_ma));
680 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
681 rentry->help, 0, NULL);
682 metrics_store_entry_add_label(sentry,
683 metrics_format_label("state", "cc_estimates"));
684 metrics_store_entry_add_label(sentry,
685 metrics_format_label("action", "bdp"));
686 metrics_store_entry_update(sentry,
687 tor_llround(cc_stats_vegas_bdp_ma));
690 /** Helper: Fill in single stream metrics output. */
691 static void
692 fill_single_stream_value(metrics_store_entry_t *sentry, uint8_t cmd)
694 metrics_store_entry_add_label(sentry,
695 metrics_format_label("type", relay_command_to_string(cmd)));
696 metrics_store_entry_update(sentry, rep_hist_get_exit_stream_seen(cmd));
699 /** Fill function for the RELAY_METRICS_NUM_STREAMS metric. */
700 static void
701 fill_streams_values(void)
703 const relay_metrics_entry_t *rentry =
704 &base_metrics[RELAY_METRICS_NUM_STREAMS];
705 metrics_store_entry_t *sentry = metrics_store_add(
706 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
707 fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN);
709 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
710 rentry->help, 0, NULL);
711 fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN_DIR);
713 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
714 rentry->help, 0, NULL);
715 fill_single_stream_value(sentry, RELAY_COMMAND_RESOLVE);
718 /** Helper: Fill in single connection metrics output. */
719 static void
720 fill_single_connection_value(metrics_store_entry_t *sentry,
721 unsigned int conn_type,
722 const char* direction,
723 const char* state,
724 int socket_family,
725 uint64_t value)
727 metrics_store_entry_add_label(sentry,
728 metrics_format_label("type", conn_type_to_string(conn_type)));
729 metrics_store_entry_add_label(sentry,
730 metrics_format_label("direction", direction));
731 metrics_store_entry_add_label(sentry,
732 metrics_format_label("state", state));
733 metrics_store_entry_add_label(sentry,
734 metrics_format_label("family", af_to_string(socket_family)));
735 metrics_store_entry_update(sentry, value);
738 /** Fill function for the RELAY_METRICS_CONN_COUNTERS metric. */
739 static void
740 fill_conn_counter_values(void)
742 const relay_metrics_entry_t *rentry =
743 &base_metrics[RELAY_METRICS_CONN_COUNTERS];
745 for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
746 /* Type is unused. Ugly but else we clobber the output. */
747 if (i == 10) {
748 continue;
750 metrics_store_entry_t *sentry = metrics_store_add(
751 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
752 fill_single_connection_value(sentry, i, "initiated", "created", AF_INET,
753 rep_hist_get_conn_created(false, i, AF_INET));
754 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
755 rentry->help, 0, NULL);
756 fill_single_connection_value(sentry, i, "initiated", "created", AF_INET6,
757 rep_hist_get_conn_created(false, i,
758 AF_INET6));
760 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
761 rentry->help, 0, NULL);
762 fill_single_connection_value(sentry, i, "received", "created", AF_INET,
763 rep_hist_get_conn_created(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", "created", AF_INET6,
767 rep_hist_get_conn_created(true, i, AF_INET6));
769 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
770 rentry->help, 0, NULL);
771 fill_single_connection_value(sentry, i, "received", "rejected", AF_INET,
772 rep_hist_get_conn_rejected(i, AF_INET));
773 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
774 rentry->help, 0, NULL);
775 fill_single_connection_value(sentry, i, "received", "rejected", AF_INET6,
776 rep_hist_get_conn_rejected(i, AF_INET6));
778 /* No counter for "initiated" + "rejected" connections exists. */
782 /** Fill function for the RELAY_METRICS_CONN_GAUGES metric. */
783 static void
784 fill_conn_gauge_values(void)
786 const relay_metrics_entry_t *rentry =
787 &base_metrics[RELAY_METRICS_CONN_GAUGES];
789 for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
790 /* Type is unused. Ugly but else we clobber the output. */
791 if (i == 10) {
792 continue;
794 metrics_store_entry_t *sentry = metrics_store_add(
795 the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
796 fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET,
797 rep_hist_get_conn_opened(false, i, AF_INET));
798 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
799 rentry->help, 0, NULL);
800 fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET6,
801 rep_hist_get_conn_opened(false, i, AF_INET6));
803 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
804 rentry->help, 0, NULL);
805 fill_single_connection_value(sentry, i, "received", "opened", AF_INET,
806 rep_hist_get_conn_opened(true, i, AF_INET));
807 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
808 rentry->help, 0, NULL);
809 fill_single_connection_value(sentry, i, "received", "opened", AF_INET6,
810 rep_hist_get_conn_opened(true, i, AF_INET6));
814 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
815 static void
816 fill_tcp_exhaustion_values(void)
818 metrics_store_entry_t *sentry;
819 const relay_metrics_entry_t *rentry =
820 &base_metrics[RELAY_METRICS_NUM_TCP_EXHAUSTION];
822 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
823 rentry->help, 0, NULL);
824 metrics_store_entry_update(sentry, rep_hist_get_n_tcp_exhaustion());
827 /* NOTE: Disable the record type label until libevent is fixed. */
828 #if 0
829 /** Helper array containing mapping for the name of the different DNS records
830 * and their corresponding libevent values. */
831 static struct dns_type {
832 const char *name;
833 uint8_t type;
834 } dns_types[] = {
835 { .name = "A", .type = DNS_IPv4_A },
836 { .name = "PTR", .type = DNS_PTR },
837 { .name = "AAAA", .type = DNS_IPv6_AAAA },
839 static const size_t num_dns_types = ARRAY_LENGTH(dns_types);
840 #endif
842 /** Fill function for the RELAY_METRICS_NUM_DNS_ERRORS metrics. */
843 static void
844 fill_dns_error_values(void)
846 metrics_store_entry_t *sentry;
847 const relay_metrics_entry_t *rentry =
848 &base_metrics[RELAY_METRICS_NUM_DNS_ERRORS];
850 /* Helper array to map libeven DNS errors to their names and so we can
851 * iterate over this array to add all metrics. */
852 static struct dns_error {
853 const char *name;
854 uint8_t key;
855 } errors[] = {
856 { .name = "success", .key = DNS_ERR_NONE },
857 { .name = "format", .key = DNS_ERR_FORMAT },
858 { .name = "serverfailed", .key = DNS_ERR_SERVERFAILED },
859 { .name = "notexist", .key = DNS_ERR_NOTEXIST },
860 { .name = "notimpl", .key = DNS_ERR_NOTIMPL },
861 { .name = "refused", .key = DNS_ERR_REFUSED },
862 { .name = "truncated", .key = DNS_ERR_TRUNCATED },
863 { .name = "unknown", .key = DNS_ERR_UNKNOWN },
864 { .name = "tor_timeout", .key = DNS_ERR_TIMEOUT },
865 { .name = "shutdown", .key = DNS_ERR_SHUTDOWN },
866 { .name = "cancel", .key = DNS_ERR_CANCEL },
867 { .name = "nodata", .key = DNS_ERR_NODATA },
869 static const size_t num_errors = ARRAY_LENGTH(errors);
871 /* NOTE: Disable the record type label until libevent is fixed. */
872 #if 0
873 for (size_t i = 0; i < num_dns_types; i++) {
874 /* Dup the label because metrics_format_label() returns a pointer to a
875 * string on the stack and we need that label for all metrics. */
876 char *record_label =
877 tor_strdup(metrics_format_label("record", dns_types[i].name));
879 for (size_t j = 0; j < num_errors; j++) {
880 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
881 rentry->help, 0, NULL);
882 metrics_store_entry_add_label(sentry, record_label);
883 metrics_store_entry_add_label(sentry,
884 metrics_format_label("reason", errors[j].name));
885 metrics_store_entry_update(sentry,
886 rep_hist_get_n_dns_error(dns_types[i].type, errors[j].key));
888 tor_free(record_label);
890 #endif
892 /* Put in the DNS errors, unfortunately not per-type for now. */
893 for (size_t j = 0; j < num_errors; j++) {
894 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
895 rentry->help, 0, NULL);
896 metrics_store_entry_add_label(sentry,
897 metrics_format_label("reason", errors[j].name));
898 metrics_store_entry_update(sentry,
899 rep_hist_get_n_dns_error(0, errors[j].key));
903 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
904 static void
905 fill_dns_query_values(void)
907 metrics_store_entry_t *sentry;
908 const relay_metrics_entry_t *rentry =
909 &base_metrics[RELAY_METRICS_NUM_DNS];
911 /* NOTE: Disable the record type label until libevent is fixed (#40490). */
912 #if 0
913 for (size_t i = 0; i < num_dns_types; i++) {
914 /* Dup the label because metrics_format_label() returns a pointer to a
915 * string on the stack and we need that label for all metrics. */
916 char *record_label =
917 tor_strdup(metrics_format_label("record", dns_types[i].name));
918 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
919 rentry->help, 0, NULL);
920 metrics_store_entry_add_label(sentry, record_label);
921 metrics_store_entry_update(sentry,
922 rep_hist_get_n_dns_request(dns_types[i].type));
923 tor_free(record_label);
925 #endif
927 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
928 rentry->help, 0, NULL);
929 metrics_store_entry_update(sentry, rep_hist_get_n_dns_request(0));
932 /** Fill function for the RELAY_METRICS_NUM_GLOBAL_RW_LIMIT metrics. */
933 static void
934 fill_global_bw_limit_values(void)
936 metrics_store_entry_t *sentry;
937 const relay_metrics_entry_t *rentry =
938 &base_metrics[RELAY_METRICS_NUM_GLOBAL_RW_LIMIT];
940 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
941 rentry->help, 0, NULL);
942 metrics_store_entry_add_label(sentry,
943 metrics_format_label("side", "read"));
944 metrics_store_entry_update(sentry, rep_hist_get_n_read_limit_reached());
946 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
947 rentry->help, 0, NULL);
948 metrics_store_entry_add_label(sentry,
949 metrics_format_label("side", "write"));
950 metrics_store_entry_update(sentry, rep_hist_get_n_write_limit_reached());
953 /** Fill function for the RELAY_METRICS_NUM_SOCKETS metrics. */
954 static void
955 fill_socket_values(void)
957 metrics_store_entry_t *sentry;
958 const relay_metrics_entry_t *rentry =
959 &base_metrics[RELAY_METRICS_NUM_SOCKETS];
961 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
962 rentry->help, 0, NULL);
963 metrics_store_entry_add_label(sentry,
964 metrics_format_label("state", "opened"));
965 metrics_store_entry_update(sentry, get_n_open_sockets());
967 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
968 rentry->help, 0, NULL);
969 metrics_store_entry_update(sentry, get_max_sockets());
972 /** Fill function for the RELAY_METRICS_NUM_ONIONSKINS metrics. */
973 static void
974 fill_onionskins_values(void)
976 metrics_store_entry_t *sentry;
977 const relay_metrics_entry_t *rentry =
978 &base_metrics[RELAY_METRICS_NUM_ONIONSKINS];
980 for (uint16_t t = 0; t <= MAX_ONION_HANDSHAKE_TYPE; t++) {
981 /* Dup the label because metrics_format_label() returns a pointer to a
982 * string on the stack and we need that label for all metrics. */
983 char *type_label =
984 tor_strdup(metrics_format_label("type", handshake_type_to_str(t)));
985 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
986 rentry->help, 0, NULL);
987 metrics_store_entry_add_label(sentry, type_label);
988 metrics_store_entry_add_label(sentry,
989 metrics_format_label("action", "processed"));
990 metrics_store_entry_update(sentry,
991 rep_hist_get_circuit_n_handshake_assigned(t));
993 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
994 rentry->help, 0, NULL);
995 metrics_store_entry_add_label(sentry, type_label);
996 metrics_store_entry_add_label(sentry,
997 metrics_format_label("action", "dropped"));
998 metrics_store_entry_update(sentry,
999 rep_hist_get_circuit_n_handshake_dropped(t));
1000 tor_free(type_label);
1004 /** Fill function for the RELAY_METRICS_NUM_OOM_BYTES metrics. */
1005 static void
1006 fill_oom_values(void)
1008 metrics_store_entry_t *sentry;
1009 const relay_metrics_entry_t *rentry =
1010 &base_metrics[RELAY_METRICS_NUM_OOM_BYTES];
1012 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
1013 rentry->help, 0, NULL);
1014 metrics_store_entry_add_label(sentry,
1015 metrics_format_label("subsys", "cell"));
1016 metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_cell);
1018 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
1019 rentry->help, 0, NULL);
1020 metrics_store_entry_add_label(sentry,
1021 metrics_format_label("subsys", "dns"));
1022 metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_dns);
1024 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
1025 rentry->help, 0, NULL);
1026 metrics_store_entry_add_label(sentry,
1027 metrics_format_label("subsys", "geoip"));
1028 metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_geoip);
1030 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
1031 rentry->help, 0, NULL);
1032 metrics_store_entry_add_label(sentry,
1033 metrics_format_label("subsys", "hsdir"));
1034 metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_hsdir);
1037 /** Fill function for the RELAY_METRICS_SIGNING_CERT_EXPIRY metrics. */
1038 static void
1039 fill_signing_cert_expiry(void)
1041 metrics_store_entry_t *sentry;
1042 const tor_cert_t *signing_key;
1043 const relay_metrics_entry_t *rentry =
1044 &base_metrics[RELAY_METRICS_SIGNING_CERT_EXPIRY];
1046 if (get_options()->OfflineMasterKey) {
1047 signing_key = get_master_signing_key_cert();
1048 if (signing_key) {
1049 sentry = metrics_store_add(the_store, rentry->type, rentry->name,
1050 rentry->help, 0, NULL);
1051 metrics_store_entry_update(sentry, signing_key->valid_until);
1056 static void
1057 fill_est_intro_cells(void)
1059 metrics_store_entry_t *sentry;
1060 const relay_metrics_entry_t *rentry =
1061 &base_metrics[RELAY_METRICS_NUM_EST_INTRO];
1063 static struct {
1064 const char *name;
1065 est_intro_action_t key;
1066 } actions[] = {
1067 {.name = "success", .key = EST_INTRO_SUCCESS},
1068 {.name = "malformed", .key = EST_INTRO_MALFORMED},
1069 {.name = "unsuitable_circuit", .key = EST_INTRO_UNSUITABLE_CIRCUIT},
1070 {.name = "circuit_dead", .key = EST_INTRO_CIRCUIT_DEAD},
1072 static const size_t num_actions = ARRAY_LENGTH(actions);
1074 for (size_t i = 0; i < num_actions; ++i) {
1075 sentry =
1076 metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
1077 metrics_store_entry_add_label(
1078 sentry, metrics_format_label("action", actions[i].name));
1079 metrics_store_entry_update(
1080 sentry, (long)rep_hist_get_est_intro_action_count(actions[i].key));
1084 static void
1085 fill_est_rend_cells(void)
1087 metrics_store_entry_t *sentry;
1088 const relay_metrics_entry_t *rentry =
1089 &base_metrics[RELAY_METRICS_NUM_EST_REND];
1091 static struct {
1092 const char *name;
1093 est_rend_action_t key;
1094 } actions[] = {
1095 {.name = "success", .key = EST_REND_SUCCESS},
1096 {.name = "unsuitable_circuit", .key = EST_REND_UNSUITABLE_CIRCUIT},
1097 {.name = "single_hop", .key = EST_REND_SINGLE_HOP},
1098 {.name = "malformed", .key = EST_REND_MALFORMED},
1099 {.name = "duplicate_cookie", .key = EST_REND_DUPLICATE_COOKIE},
1100 {.name = "circuit_dead", .key = EST_REND_CIRCUIT_DEAD},
1102 static const size_t num_actions = ARRAY_LENGTH(actions);
1104 for (size_t i = 0; i < num_actions; ++i) {
1105 sentry =
1106 metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
1107 metrics_store_entry_add_label(
1108 sentry, metrics_format_label("action", actions[i].name));
1109 metrics_store_entry_update(
1110 sentry, (long)rep_hist_get_est_rend_action_count(actions[i].key));
1114 static void
1115 fill_intro1_cells(void)
1117 metrics_store_entry_t *sentry;
1118 const relay_metrics_entry_t *rentry =
1119 &base_metrics[RELAY_METRICS_NUM_INTRO1_CELLS];
1121 static struct {
1122 const char *name;
1123 intro1_action_t key;
1124 } actions[] = {
1125 {.name = "success", .key = INTRO1_SUCCESS},
1126 {.name = "circuit_dead", .key = INTRO1_CIRCUIT_DEAD},
1127 {.name = "malformed", .key = INTRO1_MALFORMED},
1128 {.name = "unknown_service", .key = INTRO1_UNKNOWN_SERVICE},
1129 {.name = "rate_limited", .key = INTRO1_RATE_LIMITED},
1130 {.name = "circuit_reused", .key = INTRO1_CIRCUIT_REUSED},
1131 {.name = "single_hop", .key = INTRO1_SINGLE_HOP},
1133 static const size_t num_actions = ARRAY_LENGTH(actions);
1135 for (size_t i = 0; i < num_actions; ++i) {
1136 sentry =
1137 metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
1138 metrics_store_entry_add_label(
1139 sentry, metrics_format_label("action", actions[i].name));
1140 metrics_store_entry_update(
1141 sentry, (long)rep_hist_get_intro1_action_count(actions[i].key));
1145 static void
1146 fill_rend1_cells(void)
1148 metrics_store_entry_t *sentry;
1149 const relay_metrics_entry_t *rentry =
1150 &base_metrics[RELAY_METRICS_NUM_REND1_CELLS];
1152 static struct {
1153 const char *name;
1154 rend1_action_t key;
1155 } actions[] = {
1156 {.name = "success", .key = REND1_SUCCESS},
1157 {.name = "unsuitable_circuit", .key = REND1_UNSUITABLE_CIRCUIT},
1158 {.name = "malformed", .key = REND1_MALFORMED},
1159 {.name = "unknown_cookie", .key = REND1_UNKNOWN_COOKIE},
1160 {.name = "circuit_dead", .key = REND1_CIRCUIT_DEAD},
1162 static const size_t num_actions = ARRAY_LENGTH(actions);
1164 for (size_t i = 0; i < num_actions; ++i) {
1165 sentry =
1166 metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
1167 metrics_store_entry_add_label(
1168 sentry, metrics_format_label("action", actions[i].name));
1169 metrics_store_entry_update(
1170 sentry, (long)rep_hist_get_rend1_action_count(actions[i].key));
1174 /** Reset the global store and fill it with all the metrics from base_metrics
1175 * and their associated values.
1177 * To pull this off, every metrics has a "fill" function that is called and in
1178 * charge of adding the metrics to the store, appropriate labels and finally
1179 * updating the value to report. */
1180 static void
1181 fill_store(void)
1183 /* Reset the current store, we are about to fill it with all the things. */
1184 metrics_store_reset(the_store);
1186 /* Call the fill function for each metrics. */
1187 for (size_t i = 0; i < num_base_metrics; i++) {
1188 if (BUG(!base_metrics[i].fill_fn)) {
1189 continue;
1191 base_metrics[i].fill_fn();
1195 /** Return a list of all the relay metrics stores. This is the
1196 * function attached to the .get_metrics() member of the subsys_t. */
1197 const smartlist_t *
1198 relay_metrics_get_stores(void)
1200 /* We can't have the caller to free the returned list so keep it static,
1201 * simply update it. */
1202 static smartlist_t *stores_list = NULL;
1204 /* We dynamically fill the store with all the metrics upon a request. The
1205 * reason for this is because the exposed metrics of a relay are often
1206 * internal counters in the fast path and thus we fetch the value when a
1207 * metrics port request arrives instead of keeping a local metrics store of
1208 * those values. */
1209 fill_store();
1211 if (!stores_list) {
1212 stores_list = smartlist_new();
1213 smartlist_add(stores_list, the_store);
1216 return stores_list;
1219 /** Initialize the relay metrics. */
1220 void
1221 relay_metrics_init(void)
1223 if (BUG(the_store)) {
1224 return;
1226 the_store = metrics_store_new();
1229 /** Free the relay metrics. */
1230 void
1231 relay_metrics_free(void)
1233 if (!the_store) {
1234 return;
1236 /* NULL is set with this call. */
1237 metrics_store_free(the_store);