1 /* Copyright (c) 2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * @file relay_metrics.c
6 * @brief Relay metrics exposed through the MetricsPort
9 #define RELAY_METRICS_ENTRY_PRIVATE
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/circuitlist.h"
18 #include "core/or/dos.h"
19 #include "core/or/relay.h"
21 #include "app/config/config.h"
23 #include "lib/malloc/malloc.h"
24 #include "lib/container/smartlist.h"
25 #include "lib/metrics/metrics_store.h"
26 #include "lib/log/util_bug.h"
28 #include "feature/hs/hs_dos.h"
29 #include "feature/nodelist/nodelist.h"
30 #include "feature/nodelist/node_st.h"
31 #include "feature/nodelist/routerstatus_st.h"
32 #include "feature/relay/relay_metrics.h"
33 #include "feature/relay/router.h"
34 #include "feature/stats/rephist.h"
36 #include <event2/dns.h>
38 /** Declarations of each fill function for metrics defined in base_metrics. */
39 static void fill_cc_values(void);
40 static void fill_circuits_values(void);
41 static void fill_connections_values(void);
42 static void fill_dns_error_values(void);
43 static void fill_dns_query_values(void);
44 static void fill_dos_values(void);
45 static void fill_global_bw_limit_values(void);
46 static void fill_socket_values(void);
47 static void fill_onionskins_values(void);
48 static void fill_oom_values(void);
49 static void fill_streams_values(void);
50 static void fill_relay_flags(void);
51 static void fill_tcp_exhaustion_values(void);
52 static void fill_traffic_values(void);
54 /** The base metrics that is a static array of metrics added to the metrics
57 * The key member MUST be also the index of the entry in the array. */
58 static const relay_metrics_entry_t base_metrics
[] =
61 .key
= RELAY_METRICS_NUM_OOM_BYTES
,
62 .type
= METRICS_TYPE_COUNTER
,
63 .name
= METRICS_NAME(relay_load_oom_bytes_total
),
64 .help
= "Total number of bytes the OOM has freed by subsystem",
65 .fill_fn
= fill_oom_values
,
68 .key
= RELAY_METRICS_NUM_ONIONSKINS
,
69 .type
= METRICS_TYPE_COUNTER
,
70 .name
= METRICS_NAME(relay_load_onionskins_total
),
71 .help
= "Total number of onionskins handled",
72 .fill_fn
= fill_onionskins_values
,
75 .key
= RELAY_METRICS_NUM_SOCKETS
,
76 .type
= METRICS_TYPE_GAUGE
,
77 .name
= METRICS_NAME(relay_load_socket_total
),
78 .help
= "Total number of sockets",
79 .fill_fn
= fill_socket_values
,
82 .key
= RELAY_METRICS_NUM_GLOBAL_RW_LIMIT
,
83 .type
= METRICS_TYPE_COUNTER
,
84 .name
= METRICS_NAME(relay_load_global_rate_limit_reached_total
),
85 .help
= "Total number of global connection bucket limit reached",
86 .fill_fn
= fill_global_bw_limit_values
,
89 .key
= RELAY_METRICS_NUM_DNS
,
90 .type
= METRICS_TYPE_COUNTER
,
91 .name
= METRICS_NAME(relay_exit_dns_query_total
),
92 .help
= "Total number of DNS queries done by this relay",
93 .fill_fn
= fill_dns_query_values
,
96 .key
= RELAY_METRICS_NUM_DNS_ERRORS
,
97 .type
= METRICS_TYPE_COUNTER
,
98 .name
= METRICS_NAME(relay_exit_dns_error_total
),
99 .help
= "Total number of DNS errors encountered by this relay",
100 .fill_fn
= fill_dns_error_values
,
103 .key
= RELAY_METRICS_NUM_TCP_EXHAUSTION
,
104 .type
= METRICS_TYPE_COUNTER
,
105 .name
= METRICS_NAME(relay_load_tcp_exhaustion_total
),
106 .help
= "Total number of times we ran out of TCP ports",
107 .fill_fn
= fill_tcp_exhaustion_values
,
110 .key
= RELAY_METRICS_NUM_CONNECTIONS
,
111 .type
= METRICS_TYPE_COUNTER
,
112 .name
= METRICS_NAME(relay_connections_total
),
113 .help
= "Total number of connections",
114 .fill_fn
= fill_connections_values
,
117 .key
= RELAY_METRICS_NUM_STREAMS
,
118 .type
= METRICS_TYPE_COUNTER
,
119 .name
= METRICS_NAME(relay_streams_total
),
120 .help
= "Total number of streams",
121 .fill_fn
= fill_streams_values
,
124 .key
= RELAY_METRICS_NUM_CC
,
125 .type
= METRICS_TYPE_COUNTER
,
126 .name
= METRICS_NAME(relay_congestion_control_total
),
127 .help
= "Congestion control related counters",
128 .fill_fn
= fill_cc_values
,
131 .key
= RELAY_METRICS_NUM_DOS
,
132 .type
= METRICS_TYPE_COUNTER
,
133 .name
= METRICS_NAME(relay_dos_total
),
134 .help
= "Denial of Service defenses related counters",
135 .fill_fn
= fill_dos_values
,
138 .key
= RELAY_METRICS_NUM_TRAFFIC
,
139 .type
= METRICS_TYPE_COUNTER
,
140 .name
= METRICS_NAME(relay_traffic_bytes
),
141 .help
= "Traffic related counters",
142 .fill_fn
= fill_traffic_values
,
145 .key
= RELAY_METRICS_RELAY_FLAGS
,
146 .type
= METRICS_TYPE_GAUGE
,
147 .name
= METRICS_NAME(relay_flag
),
148 .help
= "Relay flags from consensus",
149 .fill_fn
= fill_relay_flags
,
152 .key
= RELAY_METRICS_NUM_CIRCUITS
,
153 .type
= METRICS_TYPE_GAUGE
,
154 .name
= METRICS_NAME(relay_circuits_total
),
155 .help
= "Total number of circuits",
156 .fill_fn
= fill_circuits_values
,
159 static const size_t num_base_metrics
= ARRAY_LENGTH(base_metrics
);
161 /** The only and single store of all the relay metrics. */
162 static metrics_store_t
*the_store
;
164 /** Helper function to convert an handshake type into a string. */
165 static inline const char *
166 handshake_type_to_str(const uint16_t type
)
169 case ONION_HANDSHAKE_TYPE_TAP
:
171 case ONION_HANDSHAKE_TYPE_FAST
:
173 case ONION_HANDSHAKE_TYPE_NTOR
:
175 case ONION_HANDSHAKE_TYPE_NTOR_V3
:
179 tor_assert_unreached();
184 /** Fill function for the RELAY_METRICS_NUM_CIRCUITS metric. */
186 fill_circuits_values(void)
188 const relay_metrics_entry_t
*rentry
=
189 &base_metrics
[RELAY_METRICS_NUM_CIRCUITS
];
190 metrics_store_entry_t
*sentry
=
191 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
193 metrics_store_entry_add_label(sentry
,
194 metrics_format_label("state", "opened"));
195 metrics_store_entry_update(sentry
,
196 smartlist_len(circuit_get_global_list()));
199 /** Fill function for the RELAY_METRICS_RELAY_FLAGS metric. */
201 fill_relay_flags(void)
203 uint8_t is_fast
= 0, is_exit
= 0, is_authority
= 0, is_stable
= 0;
204 uint8_t is_running
= 0, is_v2_dir
= 0, is_guard
= 0, is_sybil
= 0;
205 uint8_t is_hs_dir
= 0;
208 node_get_by_id((const char *) router_get_my_id_digest());
210 is_fast
= me
->rs
->is_fast
;
211 is_exit
= me
->rs
->is_exit
;
212 is_authority
= me
->rs
->is_authority
;
213 is_stable
= me
->rs
->is_stable
;
214 is_running
= me
->rs
->is_flagged_running
;
215 is_v2_dir
= me
->rs
->is_v2_dir
;
216 is_guard
= me
->rs
->is_possible_guard
;
217 is_sybil
= me
->rs
->is_sybil
;
218 is_hs_dir
= me
->rs
->is_hs_dir
;
221 const relay_metrics_entry_t
*rentry
=
222 &base_metrics
[RELAY_METRICS_RELAY_FLAGS
];
223 metrics_store_entry_t
*sentry
=
224 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
226 metrics_store_entry_add_label(sentry
,
227 metrics_format_label("type", "Fast"));
228 metrics_store_entry_update(sentry
, is_fast
);
230 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
232 metrics_store_entry_add_label(sentry
,
233 metrics_format_label("type", "Exit"));
234 metrics_store_entry_update(sentry
, is_exit
);
236 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
238 metrics_store_entry_add_label(sentry
,
239 metrics_format_label("type", "Authority"));
240 metrics_store_entry_update(sentry
, is_authority
);
242 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
244 metrics_store_entry_add_label(sentry
,
245 metrics_format_label("type", "Stable"));
246 metrics_store_entry_update(sentry
, is_stable
);
248 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
250 metrics_store_entry_add_label(sentry
,
251 metrics_format_label("type", "HSDir"));
252 metrics_store_entry_update(sentry
, is_hs_dir
);
254 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
256 metrics_store_entry_add_label(sentry
,
257 metrics_format_label("type", "Running"));
258 metrics_store_entry_update(sentry
, is_running
);
260 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
262 metrics_store_entry_add_label(sentry
,
263 metrics_format_label("type", "V2Dir"));
264 metrics_store_entry_update(sentry
, is_v2_dir
);
266 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
268 metrics_store_entry_add_label(sentry
,
269 metrics_format_label("type", "Sybil"));
270 metrics_store_entry_update(sentry
, is_sybil
);
272 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
274 metrics_store_entry_add_label(sentry
,
275 metrics_format_label("type", "Guard"));
276 metrics_store_entry_update(sentry
, is_guard
);
279 /** Fill function for the RELAY_METRICS_NUM_TRAFFIC metric. */
281 fill_traffic_values(void)
283 const relay_metrics_entry_t
*rentry
=
284 &base_metrics
[RELAY_METRICS_NUM_TRAFFIC
];
285 metrics_store_entry_t
*sentry
=
286 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
288 metrics_store_entry_add_label(sentry
,
289 metrics_format_label("direction", "read"));
290 metrics_store_entry_update(sentry
, get_bytes_read());
292 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
294 metrics_store_entry_add_label(sentry
,
295 metrics_format_label("direction", "written"));
296 metrics_store_entry_update(sentry
, get_bytes_written());
299 /** Fill function for the RELAY_METRICS_NUM_DOS metric. */
301 fill_dos_values(void)
303 const relay_metrics_entry_t
*rentry
= &base_metrics
[RELAY_METRICS_NUM_DOS
];
304 metrics_store_entry_t
*sentry
=
305 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
307 metrics_store_entry_add_label(sentry
,
308 metrics_format_label("type", "circuit_rejected"));
309 metrics_store_entry_update(sentry
, dos_get_num_cc_rejected());
311 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
313 metrics_store_entry_add_label(sentry
,
314 metrics_format_label("type", "circuit_killed_max_cell"));
315 metrics_store_entry_update(sentry
, stats_n_circ_max_cell_reached
);
317 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
319 metrics_store_entry_add_label(sentry
,
320 metrics_format_label("type", "marked_address"));
321 metrics_store_entry_update(sentry
, dos_get_num_cc_marked_addr());
323 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
325 metrics_store_entry_add_label(sentry
,
326 metrics_format_label("type", "marked_address_maxq"));
327 metrics_store_entry_update(sentry
, dos_get_num_cc_marked_addr_maxq());
329 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
331 metrics_store_entry_add_label(sentry
,
332 metrics_format_label("type", "conn_rejected"));
333 metrics_store_entry_update(sentry
, dos_get_num_conn_addr_connect_rejected());
335 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
337 metrics_store_entry_add_label(sentry
,
338 metrics_format_label("type", "concurrent_conn_rejected"));
339 metrics_store_entry_update(sentry
, dos_get_num_conn_addr_rejected());
341 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
343 metrics_store_entry_add_label(sentry
,
344 metrics_format_label("type", "single_hop_refused"));
345 metrics_store_entry_update(sentry
, dos_get_num_single_hop_refused());
347 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
349 metrics_store_entry_add_label(sentry
,
350 metrics_format_label("type", "introduce2_rejected"));
351 metrics_store_entry_update(sentry
, hs_dos_get_intro2_rejected_count());
354 /** Fill function for the RELAY_METRICS_NUM_CC metric. */
358 const relay_metrics_entry_t
*rentry
= &base_metrics
[RELAY_METRICS_NUM_CC
];
359 metrics_store_entry_t
*sentry
=
360 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
362 metrics_store_entry_add_label(sentry
,
363 metrics_format_label("state", "starvation"));
364 metrics_store_entry_add_label(sentry
,
365 metrics_format_label("action", "rtt_reset"));
366 metrics_store_entry_update(sentry
, congestion_control_get_num_rtt_reset());
369 /** Helper: Fill in single stream metrics output. */
371 fill_single_stream_value(metrics_store_entry_t
*sentry
, uint8_t cmd
)
373 metrics_store_entry_add_label(sentry
,
374 metrics_format_label("type", relay_command_to_string(cmd
)));
375 metrics_store_entry_update(sentry
, rep_hist_get_exit_stream_seen(cmd
));
378 /** Fill function for the RELAY_METRICS_NUM_STREAMS metric. */
380 fill_streams_values(void)
382 const relay_metrics_entry_t
*rentry
=
383 &base_metrics
[RELAY_METRICS_NUM_STREAMS
];
384 metrics_store_entry_t
*sentry
=
385 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
386 fill_single_stream_value(sentry
, RELAY_COMMAND_BEGIN
);
388 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
390 fill_single_stream_value(sentry
, RELAY_COMMAND_BEGIN_DIR
);
392 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
394 fill_single_stream_value(sentry
, RELAY_COMMAND_RESOLVE
);
397 /** Helper: Fill in single connection metrics output. */
399 fill_single_connection_value(metrics_store_entry_t
*sentry
,
400 unsigned int conn_type
,
401 const char* direction
,
405 metrics_store_entry_add_label(sentry
,
406 metrics_format_label("type", conn_type_to_string(conn_type
)));
407 metrics_store_entry_add_label(sentry
,
408 metrics_format_label("direction", direction
));
409 metrics_store_entry_add_label(sentry
,
410 metrics_format_label("state", state
));
411 metrics_store_entry_update(sentry
, value
);
414 /** Fill function for the RELAY_METRICS_NUM_CONNECTIONS metric. */
416 fill_connections_values(void)
418 const relay_metrics_entry_t
*rentry
=
419 &base_metrics
[RELAY_METRICS_NUM_CONNECTIONS
];
421 for (unsigned int i
= CONN_TYPE_MIN_
; i
< CONN_TYPE_MAX_
; i
++) {
422 /* Type is unused. Ugly but else we clobber the output. */
426 metrics_store_entry_t
*sentry
=
427 metrics_store_add(the_store
, rentry
->type
, rentry
->name
, rentry
->help
);
428 fill_single_connection_value(sentry
, i
, "initiated", "created",
429 rep_hist_get_conn_created(false, i
));
431 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
433 fill_single_connection_value(sentry
, i
, "received", "created",
434 rep_hist_get_conn_created(true, i
));
436 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
438 fill_single_connection_value(sentry
, i
, "initiated", "opened",
439 rep_hist_get_conn_opened(false, i
));
441 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
443 fill_single_connection_value(sentry
, i
, "received", "opened",
444 rep_hist_get_conn_opened(true, i
));
446 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
448 fill_single_connection_value(sentry
, i
, "received", "rejected",
449 rep_hist_get_conn_rejected(i
));
453 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
455 fill_tcp_exhaustion_values(void)
457 metrics_store_entry_t
*sentry
;
458 const relay_metrics_entry_t
*rentry
=
459 &base_metrics
[RELAY_METRICS_NUM_TCP_EXHAUSTION
];
461 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
463 metrics_store_entry_update(sentry
, rep_hist_get_n_tcp_exhaustion());
466 /* NOTE: Disable the record type label until libevent is fixed. */
468 /** Helper array containing mapping for the name of the different DNS records
469 * and their corresponding libevent values. */
470 static struct dns_type
{
474 { .name
= "A", .type
= DNS_IPv4_A
},
475 { .name
= "PTR", .type
= DNS_PTR
},
476 { .name
= "AAAA", .type
= DNS_IPv6_AAAA
},
478 static const size_t num_dns_types
= ARRAY_LENGTH(dns_types
);
481 /** Fill function for the RELAY_METRICS_NUM_DNS_ERRORS metrics. */
483 fill_dns_error_values(void)
485 metrics_store_entry_t
*sentry
;
486 const relay_metrics_entry_t
*rentry
=
487 &base_metrics
[RELAY_METRICS_NUM_DNS_ERRORS
];
489 /* Helper array to map libeven DNS errors to their names and so we can
490 * iterate over this array to add all metrics. */
491 static struct dns_error
{
495 { .name
= "success", .key
= DNS_ERR_NONE
},
496 { .name
= "format", .key
= DNS_ERR_FORMAT
},
497 { .name
= "serverfailed", .key
= DNS_ERR_SERVERFAILED
},
498 { .name
= "notexist", .key
= DNS_ERR_NOTEXIST
},
499 { .name
= "notimpl", .key
= DNS_ERR_NOTIMPL
},
500 { .name
= "refused", .key
= DNS_ERR_REFUSED
},
501 { .name
= "truncated", .key
= DNS_ERR_TRUNCATED
},
502 { .name
= "unknown", .key
= DNS_ERR_UNKNOWN
},
503 { .name
= "tor_timeout", .key
= DNS_ERR_TIMEOUT
},
504 { .name
= "shutdown", .key
= DNS_ERR_SHUTDOWN
},
505 { .name
= "cancel", .key
= DNS_ERR_CANCEL
},
506 { .name
= "nodata", .key
= DNS_ERR_NODATA
},
508 static const size_t num_errors
= ARRAY_LENGTH(errors
);
510 /* NOTE: Disable the record type label until libevent is fixed. */
512 for (size_t i
= 0; i
< num_dns_types
; i
++) {
513 /* Dup the label because metrics_format_label() returns a pointer to a
514 * string on the stack and we need that label for all metrics. */
516 tor_strdup(metrics_format_label("record", dns_types
[i
].name
));
518 for (size_t j
= 0; j
< num_errors
; j
++) {
519 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
521 metrics_store_entry_add_label(sentry
, record_label
);
522 metrics_store_entry_add_label(sentry
,
523 metrics_format_label("reason", errors
[j
].name
));
524 metrics_store_entry_update(sentry
,
525 rep_hist_get_n_dns_error(dns_types
[i
].type
, errors
[j
].key
));
527 tor_free(record_label
);
531 /* Put in the DNS errors, unfortunately not per-type for now. */
532 for (size_t j
= 0; j
< num_errors
; j
++) {
533 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
535 metrics_store_entry_add_label(sentry
,
536 metrics_format_label("reason", errors
[j
].name
));
537 metrics_store_entry_update(sentry
,
538 rep_hist_get_n_dns_error(0, errors
[j
].key
));
542 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
544 fill_dns_query_values(void)
546 metrics_store_entry_t
*sentry
;
547 const relay_metrics_entry_t
*rentry
=
548 &base_metrics
[RELAY_METRICS_NUM_DNS
];
550 /* NOTE: Disable the record type label until libevent is fixed (#40490). */
552 for (size_t i
= 0; i
< num_dns_types
; i
++) {
553 /* Dup the label because metrics_format_label() returns a pointer to a
554 * string on the stack and we need that label for all metrics. */
556 tor_strdup(metrics_format_label("record", dns_types
[i
].name
));
557 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
559 metrics_store_entry_add_label(sentry
, record_label
);
560 metrics_store_entry_update(sentry
,
561 rep_hist_get_n_dns_request(dns_types
[i
].type
));
562 tor_free(record_label
);
566 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
568 metrics_store_entry_update(sentry
, rep_hist_get_n_dns_request(0));
571 /** Fill function for the RELAY_METRICS_NUM_GLOBAL_RW_LIMIT metrics. */
573 fill_global_bw_limit_values(void)
575 metrics_store_entry_t
*sentry
;
576 const relay_metrics_entry_t
*rentry
=
577 &base_metrics
[RELAY_METRICS_NUM_GLOBAL_RW_LIMIT
];
579 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
581 metrics_store_entry_add_label(sentry
,
582 metrics_format_label("side", "read"));
583 metrics_store_entry_update(sentry
, rep_hist_get_n_read_limit_reached());
585 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
587 metrics_store_entry_add_label(sentry
,
588 metrics_format_label("side", "write"));
589 metrics_store_entry_update(sentry
, rep_hist_get_n_write_limit_reached());
592 /** Fill function for the RELAY_METRICS_NUM_SOCKETS metrics. */
594 fill_socket_values(void)
596 metrics_store_entry_t
*sentry
;
597 const relay_metrics_entry_t
*rentry
=
598 &base_metrics
[RELAY_METRICS_NUM_SOCKETS
];
600 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
602 metrics_store_entry_add_label(sentry
,
603 metrics_format_label("state", "opened"));
604 metrics_store_entry_update(sentry
, get_n_open_sockets());
606 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
608 metrics_store_entry_update(sentry
, get_max_sockets());
611 /** Fill function for the RELAY_METRICS_NUM_ONIONSKINS metrics. */
613 fill_onionskins_values(void)
615 metrics_store_entry_t
*sentry
;
616 const relay_metrics_entry_t
*rentry
=
617 &base_metrics
[RELAY_METRICS_NUM_ONIONSKINS
];
619 for (uint16_t t
= 0; t
<= MAX_ONION_HANDSHAKE_TYPE
; t
++) {
620 /* Dup the label because metrics_format_label() returns a pointer to a
621 * string on the stack and we need that label for all metrics. */
623 tor_strdup(metrics_format_label("type", handshake_type_to_str(t
)));
624 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
626 metrics_store_entry_add_label(sentry
, type_label
);
627 metrics_store_entry_add_label(sentry
,
628 metrics_format_label("action", "processed"));
629 metrics_store_entry_update(sentry
,
630 rep_hist_get_circuit_n_handshake_assigned(t
));
632 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
634 metrics_store_entry_add_label(sentry
, type_label
);
635 metrics_store_entry_add_label(sentry
,
636 metrics_format_label("action", "dropped"));
637 metrics_store_entry_update(sentry
,
638 rep_hist_get_circuit_n_handshake_dropped(t
));
639 tor_free(type_label
);
643 /** Fill function for the RELAY_METRICS_NUM_OOM_BYTES metrics. */
645 fill_oom_values(void)
647 metrics_store_entry_t
*sentry
;
648 const relay_metrics_entry_t
*rentry
=
649 &base_metrics
[RELAY_METRICS_NUM_OOM_BYTES
];
651 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
653 metrics_store_entry_add_label(sentry
,
654 metrics_format_label("subsys", "cell"));
655 metrics_store_entry_update(sentry
, oom_stats_n_bytes_removed_cell
);
657 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
659 metrics_store_entry_add_label(sentry
,
660 metrics_format_label("subsys", "dns"));
661 metrics_store_entry_update(sentry
, oom_stats_n_bytes_removed_dns
);
663 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
665 metrics_store_entry_add_label(sentry
,
666 metrics_format_label("subsys", "geoip"));
667 metrics_store_entry_update(sentry
, oom_stats_n_bytes_removed_geoip
);
669 sentry
= metrics_store_add(the_store
, rentry
->type
, rentry
->name
,
671 metrics_store_entry_add_label(sentry
,
672 metrics_format_label("subsys", "hsdir"));
673 metrics_store_entry_update(sentry
, oom_stats_n_bytes_removed_hsdir
);
676 /** Reset the global store and fill it with all the metrics from base_metrics
677 * and their associated values.
679 * To pull this off, every metrics has a "fill" function that is called and in
680 * charge of adding the metrics to the store, appropriate labels and finally
681 * updating the value to report. */
685 /* Reset the current store, we are about to fill it with all the things. */
686 metrics_store_reset(the_store
);
688 /* Call the fill function for each metrics. */
689 for (size_t i
= 0; i
< num_base_metrics
; i
++) {
690 if (BUG(!base_metrics
[i
].fill_fn
)) {
693 base_metrics
[i
].fill_fn();
697 /** Return a list of all the relay metrics stores. This is the
698 * function attached to the .get_metrics() member of the subsys_t. */
700 relay_metrics_get_stores(void)
702 /* We can't have the caller to free the returned list so keep it static,
703 * simply update it. */
704 static smartlist_t
*stores_list
= NULL
;
706 /* We dynamically fill the store with all the metrics upon a request. The
707 * reason for this is because the exposed metrics of a relay are often
708 * internal counters in the fast path and thus we fetch the value when a
709 * metrics port request arrives instead of keeping a local metrics store of
714 stores_list
= smartlist_new();
715 smartlist_add(stores_list
, the_store
);
721 /** Initialize the relay metrics. */
723 relay_metrics_init(void)
725 if (BUG(the_store
)) {
728 the_store
= metrics_store_new();
731 /** Free the relay metrics. */
733 relay_metrics_free(void)
738 /* NULL is set with this call. */
739 metrics_store_free(the_store
);