iota_network/randomness/
metrics.rs1use std::sync::Arc;
6
7use iota_types::{committee::EpochId, crypto::RandomnessRound};
8use prometheus::{
9 Histogram, IntGauge, Registry, register_histogram_with_registry,
10 register_int_gauge_with_registry,
11};
12use tap::Pipe;
13
14#[derive(Clone)]
15pub(super) struct Metrics(Option<Arc<Inner>>);
16
17impl std::fmt::Debug for Metrics {
18 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
19 fmt.debug_struct("Metrics").finish()
20 }
21}
22
23impl Metrics {
24 pub fn enabled(registry: &Registry) -> Self {
25 Metrics(Some(Inner::new(registry)))
26 }
27
28 pub fn disabled() -> Self {
29 Metrics(None)
30 }
31
32 pub fn set_epoch(&self, epoch: EpochId) {
33 if let Some(inner) = &self.0 {
34 inner.current_epoch.set(epoch as i64);
35 inner.highest_round_generated.set(-1);
36 inner.num_ignored_byzantine_peers.set(0);
37 }
38 }
39
40 pub fn record_completed_round(&self, round: RandomnessRound) {
41 if let Some(inner) = &self.0 {
42 inner
43 .highest_round_generated
44 .set(inner.highest_round_generated.get().max(round.0 as i64));
45 }
46 }
47
48 pub fn set_num_rounds_pending(&self, num_rounds_pending: i64) {
49 if let Some(inner) = &self.0 {
50 inner.num_rounds_pending.set(num_rounds_pending);
51 }
52 }
53
54 pub fn num_rounds_pending(&self) -> Option<i64> {
55 self.0.as_ref().map(|inner| inner.num_rounds_pending.get())
56 }
57
58 pub fn round_generation_latency_metric(&self) -> Option<&Histogram> {
59 self.0.as_ref().map(|inner| &inner.round_generation_latency)
60 }
61
62 pub fn round_observation_latency_metric(&self) -> Option<&Histogram> {
63 self.0
64 .as_ref()
65 .map(|inner| &inner.round_observation_latency)
66 }
67
68 pub fn inc_num_ignored_byzantine_peers(&self) {
69 if let Some(inner) = &self.0 {
70 inner.num_ignored_byzantine_peers.inc();
71 }
72 }
73}
74
75struct Inner {
76 current_epoch: IntGauge,
77 highest_round_generated: IntGauge,
78 num_rounds_pending: IntGauge,
79 round_generation_latency: Histogram,
80 round_observation_latency: Histogram,
81 num_ignored_byzantine_peers: IntGauge,
82}
83
84const LATENCY_SEC_BUCKETS: &[f64] = &[
85 0.001, 0.005, 0.01, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4,
86 1.6, 1.8, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.,
87 12.5, 15., 17.5, 20., 25., 30., 60., 90., 120., 180., 300.,
88];
89
90impl Inner {
91 pub fn new(registry: &Registry) -> Arc<Self> {
92 Self {
93 current_epoch: register_int_gauge_with_registry!(
94 "randomness_current_epoch",
95 "The current epoch for which randomness is being generated (only updated after DKG completes)",
96 registry
97 ).unwrap(),
98 highest_round_generated: register_int_gauge_with_registry!(
99 "randomness_highest_round_generated",
100 "The highest round for which randomness has been generated for the current epoch",
101 registry
102 ).unwrap(),
103 num_rounds_pending: register_int_gauge_with_registry!(
104 "randomness_num_rounds_pending",
105 "The number of rounds of randomness that are pending generation/observation",
106 registry
107 ).unwrap(),
108 round_generation_latency: register_histogram_with_registry!(
109 "randomness_round_generation_latency",
110 "Time taken to generate a single round of randomness, from when the round is requested to when the full signature is aggregated",
111 LATENCY_SEC_BUCKETS.to_vec(),
112 registry
113 ).unwrap(),
114 round_observation_latency: register_histogram_with_registry!(
115 "randomness_round_observation_latency",
116 "Time taken from when partial signatures are sent for a round of randomness to when the value is observed in an executed checkpoint",
117 LATENCY_SEC_BUCKETS.to_vec(),
118 registry
119 ).unwrap(),
120 num_ignored_byzantine_peers: register_int_gauge_with_registry!(
121 "randomness_num_ignored_byzantine_peers",
122 "The number of byzantine peers that have been ignored by the randomness network loop in the current epoch",
123 registry
124 ).unwrap(),
125 }
126 .pipe(Arc::new)
127 }
128}