tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

relay_metrics.c (50920B)


      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"
     14 #include "core/mainloop/connection.h"
     15 #include "core/mainloop/mainloop.h"
     16 #include "core/or/command.h"
     17 #include "core/or/congestion_control_common.h"
     18 #include "core/or/congestion_control_vegas.h"
     19 #include "core/or/congestion_control_flow.h"
     20 #include "core/or/circuitlist.h"
     21 #include "core/or/dos.h"
     22 #include "core/or/relay.h"
     23 
     24 #include "app/config/config.h"
     25 
     26 #include "lib/container/smartlist.h"
     27 #include "lib/log/util_bug.h"
     28 #include "lib/malloc/malloc.h"
     29 #include "lib/math/fp.h"
     30 #include "lib/metrics/metrics_store.h"
     31 
     32 #include "feature/hs/hs_dos.h"
     33 #include "feature/nodelist/nodelist.h"
     34 #include "feature/nodelist/node_st.h"
     35 #include "feature/nodelist/routerstatus_st.h"
     36 #include "feature/nodelist/torcert.h"
     37 #include "feature/relay/relay_metrics.h"
     38 #include "feature/relay/router.h"
     39 #include "feature/relay/routerkeys.h"
     40 #include "feature/stats/rephist.h"
     41 
     42 #include <event2/dns.h>
     43 
     44 /** Declarations of each fill function for metrics defined in base_metrics. */
     45 static void fill_cc_counters_values(void);
     46 static void fill_cc_gauges_values(void);
     47 static void fill_circuits_values(void);
     48 static void fill_conn_counter_values(void);
     49 static void fill_conn_gauge_values(void);
     50 static void fill_dns_error_values(void);
     51 static void fill_dns_query_values(void);
     52 static void fill_dos_values(void);
     53 static void fill_global_bw_limit_values(void);
     54 static void fill_socket_values(void);
     55 static void fill_onionskins_values(void);
     56 static void fill_oom_values(void);
     57 static void fill_streams_values(void);
     58 static void fill_relay_circ_proto_violation(void);
     59 static void fill_relay_destroy_cell(void);
     60 static void fill_relay_drop_cell(void);
     61 static void fill_relay_flags(void);
     62 static void fill_tcp_exhaustion_values(void);
     63 static void fill_traffic_values(void);
     64 static void fill_signing_cert_expiry(void);
     65 
     66 static void fill_est_intro_cells(void);
     67 static void fill_est_rend_cells(void);
     68 static void fill_intro1_cells(void);
     69 static void fill_rend1_cells(void);
     70 
     71 /** The base metrics that is a static array of metrics added to the metrics
     72 * store.
     73 *
     74 * The key member MUST be also the index of the entry in the array. */
     75 static const relay_metrics_entry_t base_metrics[] =
     76 {
     77  {
     78    .key = RELAY_METRICS_NUM_OOM_BYTES,
     79    .type = METRICS_TYPE_COUNTER,
     80    .name = METRICS_NAME(relay_load_oom_bytes_total),
     81    .help = "Total number of bytes the OOM has freed by subsystem",
     82    .fill_fn = fill_oom_values,
     83  },
     84  {
     85    .key = RELAY_METRICS_NUM_ONIONSKINS,
     86    .type = METRICS_TYPE_COUNTER,
     87    .name = METRICS_NAME(relay_load_onionskins_total),
     88    .help = "Total number of onionskins handled",
     89    .fill_fn = fill_onionskins_values,
     90  },
     91  {
     92    .key = RELAY_METRICS_NUM_SOCKETS,
     93    .type = METRICS_TYPE_GAUGE,
     94    .name = METRICS_NAME(relay_load_socket_total),
     95    .help = "Total number of sockets",
     96    .fill_fn = fill_socket_values,
     97  },
     98  {
     99    .key = RELAY_METRICS_NUM_GLOBAL_RW_LIMIT,
    100    .type = METRICS_TYPE_COUNTER,
    101    .name = METRICS_NAME(relay_load_global_rate_limit_reached_total),
    102    .help = "Total number of global connection bucket limit reached",
    103    .fill_fn = fill_global_bw_limit_values,
    104  },
    105  {
    106    .key = RELAY_METRICS_NUM_DNS,
    107    .type = METRICS_TYPE_COUNTER,
    108    .name = METRICS_NAME(relay_exit_dns_query_total),
    109    .help = "Total number of DNS queries done by this relay",
    110    .fill_fn = fill_dns_query_values,
    111  },
    112  {
    113    .key = RELAY_METRICS_NUM_DNS_ERRORS,
    114    .type = METRICS_TYPE_COUNTER,
    115    .name = METRICS_NAME(relay_exit_dns_error_total),
    116    .help = "Total number of DNS errors encountered by this relay",
    117    .fill_fn = fill_dns_error_values,
    118  },
    119  {
    120    .key = RELAY_METRICS_NUM_TCP_EXHAUSTION,
    121    .type = METRICS_TYPE_COUNTER,
    122    .name = METRICS_NAME(relay_load_tcp_exhaustion_total),
    123    .help = "Total number of times we ran out of TCP ports",
    124    .fill_fn = fill_tcp_exhaustion_values,
    125  },
    126  {
    127    .key = RELAY_METRICS_CONN_COUNTERS,
    128    .type = METRICS_TYPE_COUNTER,
    129    .name = METRICS_NAME(relay_connections_total),
    130    .help = "Total number of created/rejected connections",
    131    .fill_fn = fill_conn_counter_values,
    132  },
    133  {
    134    .key = RELAY_METRICS_CONN_GAUGES,
    135    .type = METRICS_TYPE_GAUGE,
    136    .name = METRICS_NAME(relay_connections),
    137    .help = "Total number of opened connections",
    138    .fill_fn = fill_conn_gauge_values,
    139  },
    140  {
    141    .key = RELAY_METRICS_NUM_STREAMS,
    142    .type = METRICS_TYPE_COUNTER,
    143    .name = METRICS_NAME(relay_streams_total),
    144    .help = "Total number of streams",
    145    .fill_fn = fill_streams_values,
    146  },
    147  {
    148    .key = RELAY_METRICS_CC_COUNTERS,
    149    .type = METRICS_TYPE_COUNTER,
    150    .name = METRICS_NAME(relay_congestion_control_total),
    151    .help = "Congestion control related counters",
    152    .fill_fn = fill_cc_counters_values,
    153  },
    154  {
    155    .key = RELAY_METRICS_CC_GAUGES,
    156    .type = METRICS_TYPE_GAUGE,
    157    .name = METRICS_NAME(relay_congestion_control),
    158    .help = "Congestion control related gauges",
    159    .fill_fn = fill_cc_gauges_values,
    160  },
    161  {
    162    .key = RELAY_METRICS_NUM_DOS,
    163    .type = METRICS_TYPE_COUNTER,
    164    .name = METRICS_NAME(relay_dos_total),
    165    .help = "Denial of Service defenses related counters",
    166    .fill_fn = fill_dos_values,
    167  },
    168  {
    169    .key = RELAY_METRICS_NUM_TRAFFIC,
    170    .type = METRICS_TYPE_COUNTER,
    171    .name = METRICS_NAME(relay_traffic_bytes),
    172    .help = "Traffic related counters",
    173    .fill_fn = fill_traffic_values,
    174  },
    175  {
    176    .key = RELAY_METRICS_RELAY_FLAGS,
    177    .type = METRICS_TYPE_GAUGE,
    178    .name = METRICS_NAME(relay_flag),
    179    .help = "Relay flags from consensus",
    180    .fill_fn = fill_relay_flags,
    181  },
    182  {
    183    .key = RELAY_METRICS_NUM_CIRCUITS,
    184    .type = METRICS_TYPE_GAUGE,
    185    .name = METRICS_NAME(relay_circuits_total),
    186    .help = "Total number of circuits",
    187    .fill_fn = fill_circuits_values,
    188  },
    189  {
    190    .key = RELAY_METRICS_SIGNING_CERT_EXPIRY,
    191    .type = METRICS_TYPE_GAUGE,
    192    .name = METRICS_NAME(relay_signing_cert_expiry_timestamp),
    193    .help = "Timestamp at which the current online keys will expire",
    194    .fill_fn = fill_signing_cert_expiry,
    195  },
    196  {
    197    .key = RELAY_METRICS_NUM_EST_REND,
    198    .type = METRICS_TYPE_COUNTER,
    199    .name = METRICS_NAME(relay_est_rend_total),
    200    .help = "Total number of EST_REND cells we received",
    201    .fill_fn = fill_est_rend_cells,
    202  },
    203  {
    204    .key = RELAY_METRICS_NUM_EST_INTRO,
    205    .type = METRICS_TYPE_COUNTER,
    206    .name = METRICS_NAME(relay_est_intro_total),
    207    .help = "Total number of EST_INTRO cells we received",
    208    .fill_fn = fill_est_intro_cells,
    209  },
    210  {
    211    .key = RELAY_METRICS_NUM_INTRO1_CELLS,
    212    .type = METRICS_TYPE_COUNTER,
    213    .name = METRICS_NAME(relay_intro1_total),
    214    .help = "Total number of INTRO1 cells we received",
    215    .fill_fn = fill_intro1_cells,
    216  },
    217  {
    218    .key = RELAY_METRICS_NUM_REND1_CELLS,
    219    .type = METRICS_TYPE_COUNTER,
    220    .name = METRICS_NAME(relay_rend1_total),
    221    .help = "Total number of REND1 cells we received",
    222    .fill_fn = fill_rend1_cells,
    223  },
    224  {
    225    .key = RELAY_METRICS_CIRC_DESTROY_CELL,
    226    .type = METRICS_TYPE_COUNTER,
    227    .name = METRICS_NAME(relay_destroy_cell_total),
    228    .help = "Total number of DESTROY cell we received",
    229    .fill_fn = fill_relay_destroy_cell,
    230  },
    231  {
    232    .key = RELAY_METRICS_CIRC_PROTO_VIOLATION,
    233    .type = METRICS_TYPE_COUNTER,
    234    .name = METRICS_NAME(relay_circ_proto_violation_total),
    235    .help = "Total number of circuit protocol violation",
    236    .fill_fn = fill_relay_circ_proto_violation,
    237  },
    238  {
    239    .key = RELAY_METRICS_CIRC_DROP_CELL,
    240    .type = METRICS_TYPE_COUNTER,
    241    .name = METRICS_NAME(relay_drop_cell_total),
    242    .help = "Total number of DROP cell we received",
    243    .fill_fn = fill_relay_drop_cell,
    244  },
    245 };
    246 static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
    247 
    248 /** The only and single store of all the relay metrics. */
    249 static metrics_store_t *the_store;
    250 
    251 /** Helper function to convert an handshake type into a string. */
    252 static inline const char *
    253 handshake_type_to_str(const uint16_t type)
    254 {
    255  switch (type) {
    256    case ONION_HANDSHAKE_TYPE_TAP:
    257      return "tap";
    258    case ONION_HANDSHAKE_TYPE_FAST:
    259      return "fast";
    260    case ONION_HANDSHAKE_TYPE_NTOR:
    261      return "ntor";
    262    case ONION_HANDSHAKE_TYPE_NTOR_V3:
    263      return "ntor_v3";
    264    default:
    265      // LCOV_EXCL_START
    266      tor_assert_unreached();
    267      // LCOV_EXCL_STOP
    268  }
    269 }
    270 
    271 /** Helper function to convert a socket family type into a string. */
    272 static inline const char *
    273 af_to_string(const int af)
    274 {
    275  switch (af) {
    276  case AF_INET:
    277    return "ipv4";
    278  case AF_INET6:
    279    return "ipv6";
    280  case AF_UNIX:
    281    return "unix";
    282  default:
    283    return "<unknown>";
    284  }
    285 }
    286 
    287 /** Fill function for the RELAY_METRICS_NUM_CIRCUITS metric. */
    288 static void
    289 fill_circuits_values(void)
    290 {
    291  const relay_metrics_entry_t *rentry =
    292    &base_metrics[RELAY_METRICS_NUM_CIRCUITS];
    293  metrics_store_entry_t *sentry = metrics_store_add(
    294      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    295 
    296  metrics_store_entry_add_label(sentry,
    297          metrics_format_label("state", "opened"));
    298  metrics_store_entry_update(sentry,
    299                             smartlist_len(circuit_get_global_list()));
    300 }
    301 
    302 /** Fill function for the RELAY_METRICS_RELAY_FLAGS metric. */
    303 static void
    304 fill_relay_flags(void)
    305 {
    306  uint8_t is_fast = 0, is_exit = 0, is_authority = 0, is_stable = 0;
    307  uint8_t is_running = 0, is_v2_dir = 0, is_guard = 0, is_sybil = 0;
    308  uint8_t is_hs_dir = 0;
    309 
    310  const node_t *me =
    311    node_get_by_id((const char *) router_get_my_id_digest());
    312  if (me && me->rs) {
    313    is_fast = me->rs->is_fast;
    314    is_exit = me->rs->is_exit;
    315    is_authority = me->rs->is_authority;
    316    is_stable = me->rs->is_stable;
    317    is_running = me->rs->is_flagged_running;
    318    is_v2_dir = me->rs->is_v2_dir;
    319    is_guard = me->rs->is_possible_guard;
    320    is_sybil = me->rs->is_sybil;
    321    is_hs_dir = me->rs->is_hs_dir;
    322  }
    323 
    324  const relay_metrics_entry_t *rentry =
    325    &base_metrics[RELAY_METRICS_RELAY_FLAGS];
    326  metrics_store_entry_t *sentry = metrics_store_add(
    327      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    328 
    329  metrics_store_entry_add_label(sentry,
    330          metrics_format_label("type", "Fast"));
    331  metrics_store_entry_update(sentry, is_fast);
    332 
    333  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    334                             rentry->help, 0, NULL);
    335  metrics_store_entry_add_label(sentry,
    336          metrics_format_label("type", "Exit"));
    337  metrics_store_entry_update(sentry, is_exit);
    338 
    339  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    340                             rentry->help, 0, NULL);
    341  metrics_store_entry_add_label(sentry,
    342          metrics_format_label("type", "Authority"));
    343  metrics_store_entry_update(sentry, is_authority);
    344 
    345  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    346                             rentry->help, 0, NULL);
    347  metrics_store_entry_add_label(sentry,
    348          metrics_format_label("type", "Stable"));
    349  metrics_store_entry_update(sentry, is_stable);
    350 
    351  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    352                             rentry->help, 0, NULL);
    353  metrics_store_entry_add_label(sentry,
    354          metrics_format_label("type", "HSDir"));
    355  metrics_store_entry_update(sentry, is_hs_dir);
    356 
    357  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    358                             rentry->help, 0, NULL);
    359  metrics_store_entry_add_label(sentry,
    360          metrics_format_label("type", "Running"));
    361  metrics_store_entry_update(sentry, is_running);
    362 
    363  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    364                             rentry->help, 0, NULL);
    365  metrics_store_entry_add_label(sentry,
    366          metrics_format_label("type", "V2Dir"));
    367  metrics_store_entry_update(sentry, is_v2_dir);
    368 
    369  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    370                             rentry->help, 0, NULL);
    371  metrics_store_entry_add_label(sentry,
    372          metrics_format_label("type", "Sybil"));
    373  metrics_store_entry_update(sentry, is_sybil);
    374 
    375  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    376                             rentry->help, 0, NULL);
    377  metrics_store_entry_add_label(sentry,
    378          metrics_format_label("type", "Guard"));
    379  metrics_store_entry_update(sentry, is_guard);
    380 }
    381 
    382 /** Fill function for the RELAY_METRICS_NUM_TRAFFIC metric. */
    383 static void
    384 fill_traffic_values(void)
    385 {
    386  const relay_metrics_entry_t *rentry =
    387    &base_metrics[RELAY_METRICS_NUM_TRAFFIC];
    388  metrics_store_entry_t *sentry = metrics_store_add(
    389      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    390 
    391  metrics_store_entry_add_label(sentry,
    392          metrics_format_label("direction", "read"));
    393  metrics_store_entry_update(sentry, get_bytes_read());
    394 
    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("direction", "written"));
    399  metrics_store_entry_update(sentry, get_bytes_written());
    400 }
    401 
    402 /** Fill function for the RELAY_METRICS_NUM_DOS metric. */
    403 static void
    404 fill_dos_values(void)
    405 {
    406  const relay_metrics_entry_t *rentry = &base_metrics[RELAY_METRICS_NUM_DOS];
    407  metrics_store_entry_t *sentry = metrics_store_add(
    408      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    409 
    410  metrics_store_entry_add_label(sentry,
    411          metrics_format_label("type", "circuit_rejected"));
    412  metrics_store_entry_update(sentry, dos_get_num_cc_rejected());
    413 
    414  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    415                             rentry->help, 0, NULL);
    416  metrics_store_entry_add_label(sentry,
    417          metrics_format_label("type", "circuit_killed_max_cell"));
    418  metrics_store_entry_update(sentry, stats_n_circ_max_cell_reached);
    419 
    420  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    421                             rentry->help, 0, NULL);
    422  metrics_store_entry_add_label(sentry,
    423          metrics_format_label("type", "circuit_killed_max_cell_outq"));
    424  metrics_store_entry_update(sentry, stats_n_circ_max_cell_outq_reached);
    425 
    426  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    427                             rentry->help, 0, NULL);
    428  metrics_store_entry_add_label(sentry,
    429          metrics_format_label("type", "marked_address"));
    430  metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr());
    431 
    432  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    433                             rentry->help, 0, NULL);
    434  metrics_store_entry_add_label(sentry,
    435          metrics_format_label("type", "marked_address_maxq"));
    436  metrics_store_entry_update(sentry, dos_get_num_cc_marked_addr_maxq());
    437 
    438  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    439                             rentry->help, 0, NULL);
    440  metrics_store_entry_add_label(sentry,
    441          metrics_format_label("type", "conn_rejected"));
    442  metrics_store_entry_update(sentry, dos_get_num_conn_addr_connect_rejected());
    443 
    444  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    445                             rentry->help, 0, NULL);
    446  metrics_store_entry_add_label(sentry,
    447          metrics_format_label("type", "concurrent_conn_rejected"));
    448  metrics_store_entry_update(sentry, dos_get_num_conn_addr_rejected());
    449 
    450  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    451                             rentry->help, 0, NULL);
    452  metrics_store_entry_add_label(sentry,
    453          metrics_format_label("type", "single_hop_refused"));
    454  metrics_store_entry_update(sentry, dos_get_num_single_hop_refused());
    455 
    456  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    457                             rentry->help, 0, NULL);
    458  metrics_store_entry_add_label(sentry,
    459          metrics_format_label("type", "introduce2_rejected"));
    460  metrics_store_entry_update(sentry, hs_dos_get_intro2_rejected_count());
    461 
    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("type", "stream_rejected"));
    466  metrics_store_entry_update(sentry, dos_get_num_stream_rejected());
    467 }
    468 
    469 /** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */
    470 static void
    471 fill_cc_counters_values(void)
    472 {
    473  const relay_metrics_entry_t *rentry =
    474    &base_metrics[RELAY_METRICS_CC_COUNTERS];
    475 
    476  metrics_store_entry_t *sentry = metrics_store_add(
    477      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    478  metrics_store_entry_add_label(sentry,
    479          metrics_format_label("state", "starvation"));
    480  metrics_store_entry_add_label(sentry,
    481          metrics_format_label("action", "rtt_reset"));
    482  metrics_store_entry_update(sentry, congestion_control_get_num_rtt_reset());
    483 
    484  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    485                             rentry->help, 0, NULL);
    486  metrics_store_entry_add_label(sentry,
    487          metrics_format_label("state", "clock_stalls"));
    488  metrics_store_entry_add_label(sentry,
    489          metrics_format_label("action", "rtt_skipped"));
    490  metrics_store_entry_update(sentry,
    491                             congestion_control_get_num_clock_stalls());
    492 
    493  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    494                             rentry->help, 0, NULL);
    495  metrics_store_entry_add_label(sentry,
    496          metrics_format_label("state", "flow_control"));
    497  metrics_store_entry_add_label(sentry,
    498          metrics_format_label("action", "xoff_num_sent"));
    499  metrics_store_entry_update(sentry,
    500                             cc_stats_flow_num_xoff_sent);
    501 
    502  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    503                             rentry->help, 0, NULL);
    504  metrics_store_entry_add_label(sentry,
    505          metrics_format_label("state", "flow_control"));
    506  metrics_store_entry_add_label(sentry,
    507          metrics_format_label("action", "xon_num_sent"));
    508  metrics_store_entry_update(sentry,
    509                             cc_stats_flow_num_xon_sent);
    510 
    511  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    512                             rentry->help, 0, NULL);
    513  metrics_store_entry_add_label(sentry,
    514          metrics_format_label("state", "cc_limits"));
    515  metrics_store_entry_add_label(sentry,
    516          metrics_format_label("action", "above_delta"));
    517  metrics_store_entry_update(sentry, cc_stats_vegas_above_delta);
    518 
    519  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    520                             rentry->help, 0, NULL);
    521  metrics_store_entry_add_label(sentry,
    522          metrics_format_label("state", "cc_limits"));
    523  metrics_store_entry_add_label(sentry,
    524          metrics_format_label("action", "above_ss_cwnd_max"));
    525  metrics_store_entry_update(sentry, cc_stats_vegas_above_ss_cwnd_max);
    526 
    527  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    528                             rentry->help, 0, NULL);
    529  metrics_store_entry_add_label(sentry,
    530          metrics_format_label("state", "cc_limits"));
    531  metrics_store_entry_add_label(sentry,
    532          metrics_format_label("action", "below_ss_inc_floor"));
    533  metrics_store_entry_update(sentry, cc_stats_vegas_below_ss_inc_floor);
    534 
    535  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    536                             rentry->help, 0, NULL);
    537  metrics_store_entry_add_label(sentry,
    538          metrics_format_label("state", "cc_circuits"));
    539  metrics_store_entry_add_label(sentry,
    540          metrics_format_label("action", "circs_created"));
    541  metrics_store_entry_update(sentry, cc_stats_circs_created);
    542 
    543  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    544                             rentry->help, 0, NULL);
    545  metrics_store_entry_add_label(sentry,
    546          metrics_format_label("state", "cc_circuits"));
    547  metrics_store_entry_add_label(sentry,
    548          metrics_format_label("action", "circs_closed"));
    549  metrics_store_entry_update(sentry, cc_stats_circs_closed);
    550 
    551  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    552                             rentry->help, 0, NULL);
    553  metrics_store_entry_add_label(sentry,
    554          metrics_format_label("state", "cc_circuits"));
    555  metrics_store_entry_add_label(sentry,
    556          metrics_format_label("action", "circs_exited_ss"));
    557  metrics_store_entry_update(sentry, cc_stats_vegas_circ_exited_ss);
    558 }
    559 
    560 /** Fill function for the RELAY_METRICS_CC_GAUGES metric. */
    561 static void
    562 fill_cc_gauges_values(void)
    563 {
    564  const relay_metrics_entry_t *rentry =
    565    &base_metrics[RELAY_METRICS_CC_GAUGES];
    566 
    567  metrics_store_entry_t *sentry = metrics_store_add(
    568      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    569  metrics_store_entry_add_label(sentry,
    570          metrics_format_label("state", "slow_start_exit"));
    571  metrics_store_entry_add_label(sentry,
    572          metrics_format_label("action", "cwnd"));
    573  metrics_store_entry_update(sentry,
    574                             tor_llround(cc_stats_vegas_exit_ss_cwnd_ma));
    575 
    576  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    577                             rentry->help, 0, NULL);
    578  metrics_store_entry_add_label(sentry,
    579          metrics_format_label("state", "slow_start_exit"));
    580  metrics_store_entry_add_label(sentry,
    581          metrics_format_label("action", "bdp"));
    582  metrics_store_entry_update(sentry,
    583                             tor_llround(cc_stats_vegas_exit_ss_bdp_ma));
    584 
    585  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    586                             rentry->help, 0, NULL);
    587  metrics_store_entry_add_label(sentry,
    588          metrics_format_label("state", "slow_start_exit"));
    589  metrics_store_entry_add_label(sentry,
    590          metrics_format_label("action", "inc"));
    591  metrics_store_entry_update(sentry,
    592                             tor_llround(cc_stats_vegas_exit_ss_inc_ma));
    593 
    594  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    595                             rentry->help, 0, NULL);
    596  metrics_store_entry_add_label(sentry,
    597          metrics_format_label("state", "on_circ_close"));
    598  metrics_store_entry_add_label(sentry,
    599          metrics_format_label("action", "cwnd"));
    600  metrics_store_entry_update(sentry,
    601                             tor_llround(cc_stats_circ_close_cwnd_ma));
    602 
    603  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    604                             rentry->help, 0, NULL);
    605  metrics_store_entry_add_label(sentry,
    606          metrics_format_label("state", "on_circ_close"));
    607  metrics_store_entry_add_label(sentry,
    608          metrics_format_label("action", "ss_cwnd"));
    609  metrics_store_entry_update(sentry,
    610                             tor_llround(cc_stats_circ_close_ss_cwnd_ma));
    611 
    612  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    613                             rentry->help, 0, NULL);
    614  metrics_store_entry_add_label(sentry,
    615          metrics_format_label("state", "buffers"));
    616  metrics_store_entry_add_label(sentry,
    617          metrics_format_label("action", "xon_outbuf"));
    618  metrics_store_entry_update(sentry,
    619                             tor_llround(cc_stats_flow_xon_outbuf_ma));
    620 
    621  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    622                             rentry->help, 0, NULL);
    623  metrics_store_entry_add_label(sentry,
    624          metrics_format_label("state", "buffers"));
    625  metrics_store_entry_add_label(sentry,
    626          metrics_format_label("action", "xoff_outbuf"));
    627  metrics_store_entry_update(sentry,
    628                             tor_llround(cc_stats_flow_xoff_outbuf_ma));
    629 
    630  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    631                             rentry->help, 0, NULL);
    632  metrics_store_entry_add_label(sentry,
    633          metrics_format_label("state", "cc_backoff"));
    634  metrics_store_entry_add_label(sentry,
    635          metrics_format_label("action", "chan_blocked_pct"));
    636  metrics_store_entry_update(sentry,
    637                             tor_llround(cc_stats_vegas_csig_blocked_ma));
    638 
    639  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    640                             rentry->help, 0, NULL);
    641  metrics_store_entry_add_label(sentry,
    642          metrics_format_label("state", "cc_backoff"));
    643  metrics_store_entry_add_label(sentry,
    644          metrics_format_label("action", "gamma_drop"));
    645  metrics_store_entry_update(sentry,
    646                             tor_llround(cc_stats_vegas_gamma_drop_ma));
    647 
    648  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    649                             rentry->help, 0, NULL);
    650  metrics_store_entry_add_label(sentry,
    651          metrics_format_label("state", "cc_backoff"));
    652  metrics_store_entry_add_label(sentry,
    653          metrics_format_label("action", "delta_drop"));
    654  metrics_store_entry_update(sentry,
    655                             tor_llround(cc_stats_vegas_delta_drop_ma));
    656 
    657  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    658                             rentry->help, 0, NULL);
    659  metrics_store_entry_add_label(sentry,
    660          metrics_format_label("state", "cc_backoff"));
    661  metrics_store_entry_add_label(sentry,
    662          metrics_format_label("action", "ss_chan_blocked_pct"));
    663  metrics_store_entry_update(sentry,
    664                             tor_llround(cc_stats_vegas_ss_csig_blocked_ma));
    665 
    666  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    667                             rentry->help, 0, NULL);
    668  metrics_store_entry_add_label(sentry,
    669          metrics_format_label("state", "cc_cwnd_update"));
    670  metrics_store_entry_add_label(sentry,
    671          metrics_format_label("action", "alpha_pct"));
    672  metrics_store_entry_update(sentry,
    673                             tor_llround(cc_stats_vegas_csig_alpha_ma));
    674 
    675  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    676                             rentry->help, 0, NULL);
    677  metrics_store_entry_add_label(sentry,
    678          metrics_format_label("state", "cc_cwnd_update"));
    679  metrics_store_entry_add_label(sentry,
    680          metrics_format_label("action", "beta_pct"));
    681  metrics_store_entry_update(sentry,
    682                             tor_llround(cc_stats_vegas_csig_beta_ma));
    683 
    684  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    685                             rentry->help, 0, NULL);
    686  metrics_store_entry_add_label(sentry,
    687          metrics_format_label("state", "cc_cwnd_update"));
    688  metrics_store_entry_add_label(sentry,
    689          metrics_format_label("action", "delta_pct"));
    690  metrics_store_entry_update(sentry,
    691                             tor_llround(cc_stats_vegas_csig_delta_ma));
    692 
    693  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    694                             rentry->help, 0, NULL);
    695  metrics_store_entry_add_label(sentry,
    696          metrics_format_label("state", "cc_estimates"));
    697  metrics_store_entry_add_label(sentry,
    698          metrics_format_label("action", "ss_queue"));
    699  metrics_store_entry_update(sentry,
    700                             tor_llround(cc_stats_vegas_ss_queue_ma));
    701 
    702  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    703                             rentry->help, 0, NULL);
    704  metrics_store_entry_add_label(sentry,
    705          metrics_format_label("state", "cc_estimates"));
    706  metrics_store_entry_add_label(sentry,
    707          metrics_format_label("action", "queue"));
    708  metrics_store_entry_update(sentry,
    709                             tor_llround(cc_stats_vegas_queue_ma));
    710 
    711  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    712                             rentry->help, 0, NULL);
    713  metrics_store_entry_add_label(sentry,
    714          metrics_format_label("state", "cc_estimates"));
    715  metrics_store_entry_add_label(sentry,
    716          metrics_format_label("action", "bdp"));
    717  metrics_store_entry_update(sentry,
    718                             tor_llround(cc_stats_vegas_bdp_ma));
    719 }
    720 
    721 /** Helper: Fill in single stream metrics output. */
    722 static void
    723 fill_single_stream_value(metrics_store_entry_t *sentry, uint8_t cmd)
    724 {
    725  metrics_store_entry_add_label(sentry,
    726          metrics_format_label("type", relay_command_to_string(cmd)));
    727  metrics_store_entry_update(sentry, rep_hist_get_exit_stream_seen(cmd));
    728 }
    729 
    730 /** Fill function for the RELAY_METRICS_NUM_STREAMS metric. */
    731 static void
    732 fill_streams_values(void)
    733 {
    734  const relay_metrics_entry_t *rentry =
    735    &base_metrics[RELAY_METRICS_NUM_STREAMS];
    736  metrics_store_entry_t *sentry = metrics_store_add(
    737      the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    738  fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN);
    739 
    740  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    741                             rentry->help, 0, NULL);
    742  fill_single_stream_value(sentry, RELAY_COMMAND_BEGIN_DIR);
    743 
    744  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    745                             rentry->help, 0, NULL);
    746  fill_single_stream_value(sentry, RELAY_COMMAND_RESOLVE);
    747 }
    748 
    749 /** Helper: Fill in single connection metrics output. */
    750 static void
    751 fill_single_connection_value(metrics_store_entry_t *sentry,
    752                             unsigned int conn_type,
    753                             const char* direction,
    754                             const char* state,
    755                             int socket_family,
    756                             uint64_t value)
    757 {
    758  metrics_store_entry_add_label(sentry,
    759          metrics_format_label("type", conn_type_to_string(conn_type)));
    760  metrics_store_entry_add_label(sentry,
    761          metrics_format_label("direction", direction));
    762  metrics_store_entry_add_label(sentry,
    763          metrics_format_label("state", state));
    764  metrics_store_entry_add_label(sentry,
    765          metrics_format_label("family", af_to_string(socket_family)));
    766  metrics_store_entry_update(sentry, value);
    767 }
    768 
    769 /** Fill function for the RELAY_METRICS_CONN_COUNTERS metric. */
    770 static void
    771 fill_conn_counter_values(void)
    772 {
    773  const relay_metrics_entry_t *rentry =
    774    &base_metrics[RELAY_METRICS_CONN_COUNTERS];
    775 
    776  for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
    777    /* Type is unused. Ugly but else we clobber the output. */
    778    if (i == 10) {
    779      continue;
    780    }
    781    metrics_store_entry_t *sentry = metrics_store_add(
    782        the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    783    fill_single_connection_value(sentry, i, "initiated", "created", AF_INET,
    784                                 rep_hist_get_conn_created(false, i, AF_INET));
    785    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    786                               rentry->help, 0, NULL);
    787    fill_single_connection_value(sentry, i, "initiated", "created", AF_INET6,
    788                                 rep_hist_get_conn_created(false, i,
    789                                                           AF_INET6));
    790 
    791    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    792                               rentry->help, 0, NULL);
    793    fill_single_connection_value(sentry, i, "received", "created", AF_INET,
    794                                 rep_hist_get_conn_created(true, i, AF_INET));
    795    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    796                               rentry->help, 0, NULL);
    797    fill_single_connection_value(sentry, i, "received", "created", AF_INET6,
    798                                 rep_hist_get_conn_created(true, i, AF_INET6));
    799 
    800    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    801                               rentry->help, 0, NULL);
    802    fill_single_connection_value(sentry, i, "received", "rejected", AF_INET,
    803                                 rep_hist_get_conn_rejected(i, AF_INET));
    804    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    805                               rentry->help, 0, NULL);
    806    fill_single_connection_value(sentry, i, "received", "rejected", AF_INET6,
    807                                 rep_hist_get_conn_rejected(i, AF_INET6));
    808 
    809    /* No counter for "initiated" + "rejected" connections exists. */
    810  }
    811 }
    812 
    813 /** Fill function for the RELAY_METRICS_CONN_GAUGES metric. */
    814 static void
    815 fill_conn_gauge_values(void)
    816 {
    817  const relay_metrics_entry_t *rentry =
    818    &base_metrics[RELAY_METRICS_CONN_GAUGES];
    819 
    820  for (unsigned int i = CONN_TYPE_MIN_; i < CONN_TYPE_MAX_ ; i++) {
    821    /* Type is unused. Ugly but else we clobber the output. */
    822    if (i == 10) {
    823      continue;
    824    }
    825    metrics_store_entry_t *sentry = metrics_store_add(
    826        the_store, rentry->type, rentry->name, rentry->help, 0, NULL);
    827    fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET,
    828                                 rep_hist_get_conn_opened(false, i, AF_INET));
    829    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    830                               rentry->help, 0, NULL);
    831    fill_single_connection_value(sentry, i, "initiated", "opened", AF_INET6,
    832                                 rep_hist_get_conn_opened(false, i, AF_INET6));
    833 
    834    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    835                               rentry->help, 0, NULL);
    836    fill_single_connection_value(sentry, i, "received", "opened", AF_INET,
    837                                 rep_hist_get_conn_opened(true, i, AF_INET));
    838    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    839                               rentry->help, 0, NULL);
    840    fill_single_connection_value(sentry, i, "received", "opened", AF_INET6,
    841                                 rep_hist_get_conn_opened(true, i, AF_INET6));
    842  }
    843 }
    844 
    845 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
    846 static void
    847 fill_tcp_exhaustion_values(void)
    848 {
    849  metrics_store_entry_t *sentry;
    850  const relay_metrics_entry_t *rentry =
    851    &base_metrics[RELAY_METRICS_NUM_TCP_EXHAUSTION];
    852 
    853  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    854                             rentry->help, 0, NULL);
    855  metrics_store_entry_update(sentry, rep_hist_get_n_tcp_exhaustion());
    856 }
    857 
    858 /* NOTE: Disable the record type label until libevent is fixed. */
    859 #if 0
    860 /** Helper array containing mapping for the name of the different DNS records
    861 * and their corresponding libevent values. */
    862 static struct dns_type {
    863  const char *name;
    864  uint8_t type;
    865 } dns_types[] = {
    866  { .name = "A",    .type = DNS_IPv4_A     },
    867  { .name = "PTR",  .type = DNS_PTR        },
    868  { .name = "AAAA", .type = DNS_IPv6_AAAA  },
    869 };
    870 static const size_t num_dns_types = ARRAY_LENGTH(dns_types);
    871 #endif
    872 
    873 /** Fill function for the RELAY_METRICS_NUM_DNS_ERRORS metrics. */
    874 static void
    875 fill_dns_error_values(void)
    876 {
    877  metrics_store_entry_t *sentry;
    878  const relay_metrics_entry_t *rentry =
    879    &base_metrics[RELAY_METRICS_NUM_DNS_ERRORS];
    880 
    881  /* Helper array to map libeven DNS errors to their names and so we can
    882   * iterate over this array to add all metrics. */
    883  static struct dns_error {
    884    const char *name;
    885    uint8_t key;
    886  } errors[] = {
    887    { .name = "success",      .key = DNS_ERR_NONE         },
    888    { .name = "format",       .key = DNS_ERR_FORMAT       },
    889    { .name = "serverfailed", .key = DNS_ERR_SERVERFAILED },
    890    { .name = "notexist",     .key = DNS_ERR_NOTEXIST     },
    891    { .name = "notimpl",      .key = DNS_ERR_NOTIMPL      },
    892    { .name = "refused",      .key = DNS_ERR_REFUSED      },
    893    { .name = "truncated",    .key = DNS_ERR_TRUNCATED    },
    894    { .name = "unknown",      .key = DNS_ERR_UNKNOWN      },
    895    { .name = "tor_timeout",  .key = DNS_ERR_TIMEOUT      },
    896    { .name = "shutdown",     .key = DNS_ERR_SHUTDOWN     },
    897    { .name = "cancel",       .key = DNS_ERR_CANCEL       },
    898    { .name = "nodata",       .key = DNS_ERR_NODATA       },
    899  };
    900  static const size_t num_errors = ARRAY_LENGTH(errors);
    901 
    902  /* NOTE: Disable the record type label until libevent is fixed. */
    903 #if 0
    904  for (size_t i = 0; i < num_dns_types; i++) {
    905    /* Dup the label because metrics_format_label() returns a pointer to a
    906     * string on the stack and we need that label for all metrics. */
    907    char *record_label =
    908      tor_strdup(metrics_format_label("record", dns_types[i].name));
    909 
    910    for (size_t j = 0; j < num_errors; j++) {
    911      sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    912                                 rentry->help, 0, NULL);
    913      metrics_store_entry_add_label(sentry, record_label);
    914      metrics_store_entry_add_label(sentry,
    915              metrics_format_label("reason", errors[j].name));
    916      metrics_store_entry_update(sentry,
    917              rep_hist_get_n_dns_error(dns_types[i].type, errors[j].key));
    918    }
    919    tor_free(record_label);
    920  }
    921 #endif
    922 
    923  /* Put in the DNS errors, unfortunately not per-type for now. */
    924  for (size_t j = 0; j < num_errors; j++) {
    925    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    926                               rentry->help, 0, NULL);
    927    metrics_store_entry_add_label(sentry,
    928            metrics_format_label("reason", errors[j].name));
    929    metrics_store_entry_update(sentry,
    930            rep_hist_get_n_dns_error(0, errors[j].key));
    931  }
    932 }
    933 
    934 /** Fill function for the RELAY_METRICS_NUM_DNS metrics. */
    935 static void
    936 fill_dns_query_values(void)
    937 {
    938  metrics_store_entry_t *sentry;
    939  const relay_metrics_entry_t *rentry =
    940    &base_metrics[RELAY_METRICS_NUM_DNS];
    941 
    942    /* NOTE: Disable the record type label until libevent is fixed (#40490). */
    943 #if 0
    944  for (size_t i = 0; i < num_dns_types; i++) {
    945    /* Dup the label because metrics_format_label() returns a pointer to a
    946     * string on the stack and we need that label for all metrics. */
    947    char *record_label =
    948      tor_strdup(metrics_format_label("record", dns_types[i].name));
    949    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    950                               rentry->help, 0, NULL);
    951    metrics_store_entry_add_label(sentry, record_label);
    952    metrics_store_entry_update(sentry,
    953                               rep_hist_get_n_dns_request(dns_types[i].type));
    954    tor_free(record_label);
    955  }
    956 #endif
    957 
    958  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    959                             rentry->help, 0, NULL);
    960  metrics_store_entry_update(sentry, rep_hist_get_n_dns_request(0));
    961 }
    962 
    963 /** Fill function for the RELAY_METRICS_NUM_GLOBAL_RW_LIMIT metrics. */
    964 static void
    965 fill_global_bw_limit_values(void)
    966 {
    967  metrics_store_entry_t *sentry;
    968  const relay_metrics_entry_t *rentry =
    969    &base_metrics[RELAY_METRICS_NUM_GLOBAL_RW_LIMIT];
    970 
    971  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    972                             rentry->help, 0, NULL);
    973  metrics_store_entry_add_label(sentry,
    974                                metrics_format_label("side", "read"));
    975  metrics_store_entry_update(sentry, rep_hist_get_n_read_limit_reached());
    976 
    977  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    978                             rentry->help, 0, NULL);
    979  metrics_store_entry_add_label(sentry,
    980                                metrics_format_label("side", "write"));
    981  metrics_store_entry_update(sentry, rep_hist_get_n_write_limit_reached());
    982 }
    983 
    984 /** Fill function for the RELAY_METRICS_NUM_SOCKETS metrics. */
    985 static void
    986 fill_socket_values(void)
    987 {
    988  metrics_store_entry_t *sentry;
    989  const relay_metrics_entry_t *rentry =
    990    &base_metrics[RELAY_METRICS_NUM_SOCKETS];
    991 
    992  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    993                             rentry->help, 0, NULL);
    994  metrics_store_entry_add_label(sentry,
    995                                metrics_format_label("state", "opened"));
    996  metrics_store_entry_update(sentry, get_n_open_sockets());
    997 
    998  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
    999                             rentry->help, 0, NULL);
   1000  metrics_store_entry_update(sentry, get_max_sockets());
   1001 }
   1002 
   1003 /** Fill function for the RELAY_METRICS_NUM_ONIONSKINS metrics. */
   1004 static void
   1005 fill_onionskins_values(void)
   1006 {
   1007  metrics_store_entry_t *sentry;
   1008  const relay_metrics_entry_t *rentry =
   1009    &base_metrics[RELAY_METRICS_NUM_ONIONSKINS];
   1010 
   1011  for (uint16_t t = 0; t <= MAX_ONION_HANDSHAKE_TYPE; t++) {
   1012    /* Dup the label because metrics_format_label() returns a pointer to a
   1013     * string on the stack and we need that label for all metrics. */
   1014    char *type_label =
   1015      tor_strdup(metrics_format_label("type", handshake_type_to_str(t)));
   1016    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1017                               rentry->help, 0, NULL);
   1018    metrics_store_entry_add_label(sentry, type_label);
   1019    metrics_store_entry_add_label(sentry,
   1020                        metrics_format_label("action", "processed"));
   1021    metrics_store_entry_update(sentry,
   1022                               rep_hist_get_circuit_n_handshake_assigned(t));
   1023 
   1024    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1025                               rentry->help, 0, NULL);
   1026    metrics_store_entry_add_label(sentry, type_label);
   1027    metrics_store_entry_add_label(sentry,
   1028                        metrics_format_label("action", "dropped"));
   1029    metrics_store_entry_update(sentry,
   1030                               rep_hist_get_circuit_n_handshake_dropped(t));
   1031    tor_free(type_label);
   1032  }
   1033 }
   1034 
   1035 /** Fill function for the RELAY_METRICS_NUM_OOM_BYTES metrics. */
   1036 static void
   1037 fill_oom_values(void)
   1038 {
   1039  metrics_store_entry_t *sentry;
   1040  const relay_metrics_entry_t *rentry =
   1041    &base_metrics[RELAY_METRICS_NUM_OOM_BYTES];
   1042 
   1043  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1044                             rentry->help, 0, NULL);
   1045  metrics_store_entry_add_label(sentry,
   1046                                metrics_format_label("subsys", "cell"));
   1047  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_cell);
   1048 
   1049  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1050                             rentry->help, 0, NULL);
   1051  metrics_store_entry_add_label(sentry,
   1052                                metrics_format_label("subsys", "dns"));
   1053  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_dns);
   1054 
   1055  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1056                             rentry->help, 0, NULL);
   1057  metrics_store_entry_add_label(sentry,
   1058                                metrics_format_label("subsys", "geoip"));
   1059  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_geoip);
   1060 
   1061  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1062                             rentry->help, 0, NULL);
   1063  metrics_store_entry_add_label(sentry,
   1064                                metrics_format_label("subsys", "hsdir"));
   1065  metrics_store_entry_update(sentry, oom_stats_n_bytes_removed_hsdir);
   1066 }
   1067 
   1068 /** Fill function for the RELAY_METRICS_SIGNING_CERT_EXPIRY metrics. */
   1069 static void
   1070 fill_signing_cert_expiry(void)
   1071 {
   1072  metrics_store_entry_t *sentry;
   1073  const tor_cert_t *signing_key;
   1074  const relay_metrics_entry_t *rentry =
   1075    &base_metrics[RELAY_METRICS_SIGNING_CERT_EXPIRY];
   1076 
   1077  if (get_options()->OfflineMasterKey) {
   1078    signing_key = get_master_signing_key_cert();
   1079    if (signing_key) {
   1080      sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1081                                 rentry->help, 0, NULL);
   1082      metrics_store_entry_update(sentry, signing_key->valid_until);
   1083    }
   1084  }
   1085 }
   1086 
   1087 static uint64_t est_intro_actions[EST_INTRO_ACTION_COUNT] = {0};
   1088 
   1089 void
   1090 relay_increment_est_intro_action(est_intro_action_t action)
   1091 {
   1092  est_intro_actions[action]++;
   1093 }
   1094 
   1095 static void
   1096 fill_est_intro_cells(void)
   1097 {
   1098  metrics_store_entry_t *sentry;
   1099  const relay_metrics_entry_t *rentry =
   1100      &base_metrics[RELAY_METRICS_NUM_EST_INTRO];
   1101 
   1102  static struct {
   1103    const char *name;
   1104    est_intro_action_t key;
   1105  } actions[] = {
   1106      {.name = "success", .key = EST_INTRO_SUCCESS},
   1107      {.name = "malformed", .key = EST_INTRO_MALFORMED},
   1108      {.name = "unsuitable_circuit", .key = EST_INTRO_UNSUITABLE_CIRCUIT},
   1109      {.name = "circuit_dead", .key = EST_INTRO_CIRCUIT_DEAD},
   1110  };
   1111  static const size_t num_actions = ARRAY_LENGTH(actions);
   1112 
   1113  for (size_t i = 0; i < num_actions; ++i) {
   1114    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1115                               rentry->help, 0, NULL);
   1116    metrics_store_entry_add_label(
   1117        sentry, metrics_format_label("action", actions[i].name));
   1118    metrics_store_entry_update(sentry,
   1119                               (long)est_intro_actions[actions[i].key]);
   1120  }
   1121 }
   1122 
   1123 static uint64_t est_rend_actions[EST_REND_ACTION_COUNT] = {0};
   1124 
   1125 void
   1126 relay_increment_est_rend_action(est_rend_action_t action)
   1127 {
   1128  est_rend_actions[action]++;
   1129 }
   1130 
   1131 static void
   1132 fill_est_rend_cells(void)
   1133 {
   1134  metrics_store_entry_t *sentry;
   1135  const relay_metrics_entry_t *rentry =
   1136      &base_metrics[RELAY_METRICS_NUM_EST_REND];
   1137 
   1138  static struct {
   1139    const char *name;
   1140    est_rend_action_t key;
   1141  } actions[] = {
   1142      {.name = "success", .key = EST_REND_SUCCESS},
   1143      {.name = "unsuitable_circuit", .key = EST_REND_UNSUITABLE_CIRCUIT},
   1144      {.name = "single_hop", .key = EST_REND_SINGLE_HOP},
   1145      {.name = "malformed", .key = EST_REND_MALFORMED},
   1146      {.name = "duplicate_cookie", .key = EST_REND_DUPLICATE_COOKIE},
   1147      {.name = "circuit_dead", .key = EST_REND_CIRCUIT_DEAD},
   1148  };
   1149  static const size_t num_actions = ARRAY_LENGTH(actions);
   1150 
   1151  for (size_t i = 0; i < num_actions; ++i) {
   1152    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1153                               rentry->help, 0, NULL);
   1154    metrics_store_entry_add_label(
   1155        sentry, metrics_format_label("action", actions[i].name));
   1156    metrics_store_entry_update(sentry, (long)est_rend_actions[actions[i].key]);
   1157  }
   1158 }
   1159 
   1160 static uint64_t intro1_actions[INTRO1_ACTION_COUNT] = {0};
   1161 
   1162 void
   1163 relay_increment_intro1_action(intro1_action_t action)
   1164 {
   1165  intro1_actions[action]++;
   1166 }
   1167 
   1168 static void
   1169 fill_intro1_cells(void)
   1170 {
   1171  metrics_store_entry_t *sentry;
   1172  const relay_metrics_entry_t *rentry =
   1173      &base_metrics[RELAY_METRICS_NUM_INTRO1_CELLS];
   1174 
   1175  static struct {
   1176    const char *name;
   1177    intro1_action_t key;
   1178  } actions[] = {
   1179      {.name = "success", .key = INTRO1_SUCCESS},
   1180      {.name = "circuit_dead", .key = INTRO1_CIRCUIT_DEAD},
   1181      {.name = "malformed", .key = INTRO1_MALFORMED},
   1182      {.name = "unknown_service", .key = INTRO1_UNKNOWN_SERVICE},
   1183      {.name = "rate_limited", .key = INTRO1_RATE_LIMITED},
   1184      {.name = "circuit_reused", .key = INTRO1_CIRCUIT_REUSED},
   1185      {.name = "single_hop", .key = INTRO1_SINGLE_HOP},
   1186  };
   1187  static const size_t num_actions = ARRAY_LENGTH(actions);
   1188 
   1189  for (size_t i = 0; i < num_actions; ++i) {
   1190    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1191                               rentry->help, 0, NULL);
   1192    metrics_store_entry_add_label(
   1193        sentry, metrics_format_label("action", actions[i].name));
   1194    metrics_store_entry_update(sentry, (long)intro1_actions[actions[i].key]);
   1195  }
   1196 }
   1197 
   1198 static uint64_t rend1_actions[REND1_ACTION_COUNT] = {0};
   1199 
   1200 void
   1201 relay_increment_rend1_action(rend1_action_t action)
   1202 {
   1203  rend1_actions[action]++;
   1204 }
   1205 
   1206 static void
   1207 fill_rend1_cells(void)
   1208 {
   1209  metrics_store_entry_t *sentry;
   1210  const relay_metrics_entry_t *rentry =
   1211      &base_metrics[RELAY_METRICS_NUM_REND1_CELLS];
   1212 
   1213  static struct {
   1214    const char *name;
   1215    rend1_action_t key;
   1216  } actions[] = {
   1217      {.name = "success", .key = REND1_SUCCESS},
   1218      {.name = "unsuitable_circuit", .key = REND1_UNSUITABLE_CIRCUIT},
   1219      {.name = "malformed", .key = REND1_MALFORMED},
   1220      {.name = "unknown_cookie", .key = REND1_UNKNOWN_COOKIE},
   1221      {.name = "circuit_dead", .key = REND1_CIRCUIT_DEAD},
   1222  };
   1223  static const size_t num_actions = ARRAY_LENGTH(actions);
   1224 
   1225  for (size_t i = 0; i < num_actions; ++i) {
   1226    sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1227                               rentry->help, 0, NULL);
   1228    metrics_store_entry_add_label(
   1229        sentry, metrics_format_label("action", actions[i].name));
   1230    metrics_store_entry_update(sentry, (long)rend1_actions[actions[i].key]);
   1231  }
   1232 }
   1233 
   1234 /** Fill the metrics store for the RELAY_METRICS_CIRC_DESTROY_CELL counter. */
   1235 static void
   1236 fill_relay_destroy_cell(void)
   1237 {
   1238  metrics_store_entry_t *sentry;
   1239  const relay_metrics_entry_t *rentry =
   1240    &base_metrics[RELAY_METRICS_CIRC_DESTROY_CELL];
   1241 
   1242  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1243                             rentry->help, 0, NULL);
   1244  metrics_store_entry_update(sentry,
   1245                             (int64_t) stats_n_destroy_cells_processed);
   1246 }
   1247 
   1248 /** Fill the metrics store for the RELAY_METRICS_CIRC_DROP_CELL counter. */
   1249 static void
   1250 fill_relay_drop_cell(void)
   1251 {
   1252  metrics_store_entry_t *sentry;
   1253  const relay_metrics_entry_t *rentry =
   1254    &base_metrics[RELAY_METRICS_CIRC_DROP_CELL];
   1255 
   1256  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1257                             rentry->help, 0, NULL);
   1258  metrics_store_entry_update(sentry, rep_hist_get_drop_cell_received_count());
   1259 }
   1260 
   1261 /** Fill the metrics store for the RELAY_METRICS_CIRC_PROTO_VIOLATION. */
   1262 static void
   1263 fill_relay_circ_proto_violation(void)
   1264 {
   1265  metrics_store_entry_t *sentry;
   1266  const relay_metrics_entry_t *rentry =
   1267    &base_metrics[RELAY_METRICS_CIRC_PROTO_VIOLATION];
   1268 
   1269  sentry = metrics_store_add(the_store, rentry->type, rentry->name,
   1270                             rentry->help, 0, NULL);
   1271  metrics_store_entry_update(sentry, circ_n_proto_violation);
   1272 }
   1273 
   1274 /** Reset the global store and fill it with all the metrics from base_metrics
   1275 * and their associated values.
   1276 *
   1277 * To pull this off, every metrics has a "fill" function that is called and in
   1278 * charge of adding the metrics to the store, appropriate labels and finally
   1279 * updating the value to report. */
   1280 static void
   1281 fill_store(void)
   1282 {
   1283  /* Reset the current store, we are about to fill it with all the things. */
   1284  metrics_store_reset(the_store);
   1285 
   1286  /* Call the fill function for each metrics. */
   1287  for (size_t i = 0; i < num_base_metrics; i++) {
   1288    if (BUG(!base_metrics[i].fill_fn)) {
   1289      continue;
   1290    }
   1291    base_metrics[i].fill_fn();
   1292  }
   1293 }
   1294 
   1295 /** Return a list of all the relay metrics stores. This is the
   1296 * function attached to the .get_metrics() member of the subsys_t. */
   1297 const smartlist_t *
   1298 relay_metrics_get_stores(void)
   1299 {
   1300  /* We can't have the caller to free the returned list so keep it static,
   1301   * simply update it. */
   1302  static smartlist_t *stores_list = NULL;
   1303 
   1304  /* We dynamically fill the store with all the metrics upon a request. The
   1305   * reason for this is because the exposed metrics of a relay are often
   1306   * internal counters in the fast path and thus we fetch the value when a
   1307   * metrics port request arrives instead of keeping a local metrics store of
   1308   * those values. */
   1309  fill_store();
   1310 
   1311  if (!stores_list) {
   1312    stores_list = smartlist_new();
   1313    smartlist_add(stores_list, the_store);
   1314  }
   1315 
   1316  return stores_list;
   1317 }
   1318 
   1319 /** Initialize the relay metrics. */
   1320 void
   1321 relay_metrics_init(void)
   1322 {
   1323  if (BUG(the_store)) {
   1324    return;
   1325  }
   1326  the_store = metrics_store_new();
   1327 }
   1328 
   1329 /** Free the relay metrics. */
   1330 void
   1331 relay_metrics_free(void)
   1332 {
   1333  if (!the_store) {
   1334    return;
   1335  }
   1336  /* NULL is set with this call. */
   1337  metrics_store_free(the_store);
   1338 }