Skip to main content

iota_core/epoch/
epoch_metrics.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::sync::Arc;
6
7use prometheus_filtered::{
8    IntCounter, IntGauge, MetricLevel, Registry, register_int_counter_with_registry,
9    register_int_gauge_with_registry,
10};
11
12pub struct EpochMetrics {
13    /// The current epoch ID. This is updated only when the AuthorityState
14    /// finishes reconfiguration.
15    pub current_epoch: IntGauge,
16
17    /// Current voting right of the validator in the protocol. Updated at the
18    /// start of epochs.
19    pub current_voting_right: IntGauge,
20
21    /// Total duration of the epoch. This is measured from when the current
22    /// epoch store is opened, until the current epoch store is replaced
23    /// with the next epoch store.
24    pub epoch_total_duration: IntGauge,
25
26    /// Number of checkpoints in the epoch.
27    pub epoch_checkpoint_count: IntGauge,
28
29    /// Number of transactions in the epoch.
30    pub epoch_transaction_count: IntGauge,
31
32    /// Total amount of gas rewards (i.e. computation gas cost) in the epoch.
33    pub epoch_total_gas_reward: IntGauge,
34
35    // An active validator reconfigures through the following steps:
36    // 1. Halt validator (a.k.a. close epoch) and stop accepting user transaction certs.
37    // 2. Finishes processing all pending certificates and then send EndOfPublish message.
38    // 3. Stop accepting messages from consensus after seeing 2f+1 EndOfPublish messages.
39    // 4. Creating the last checkpoint of the epoch by augmenting it with AdvanceEpoch transaction.
40    // 5. CheckpointExecutor finishes executing the last checkpoint, and triggers reconfiguration.
41    // 6. During reconfiguration, we tear down consensus, reconfigure state (at which point we
42    //    opens up user certs), and start consensus again.
43    // 7. After reconfiguration, and eventually consensus starts successfully, at some point the
44    //    first checkpoint of the new epoch will be created.
45    // We introduce various metrics to cover the latency of above steps.
46    /// The duration from when the epoch is closed (i.e. validator halted) to
47    /// when all pending certificates are processed (i.e. ready to send
48    /// EndOfPublish message). This is the duration of (1) through (2)
49    /// above.
50    pub epoch_pending_certs_processed_time_since_epoch_close_ms: IntGauge,
51
52    /// The interval from when the epoch is closed to when we receive 2f+1
53    /// EndOfPublish messages. This is the duration of (1) through (3)
54    /// above.
55    pub epoch_end_of_publish_quorum_time_since_epoch_close_ms: IntGauge,
56
57    /// The interval from when the epoch is closed to when we created the last
58    /// checkpoint of the epoch.
59    /// This is the duration of (1) through (4) above.
60    pub epoch_last_checkpoint_created_time_since_epoch_close_ms: IntGauge,
61
62    /// The interval from when the epoch is closed to when we finished executing
63    /// the last transaction of the checkpoint (and hence triggering
64    /// reconfiguration process). This is the duration of (1) through (5)
65    /// above.
66    pub epoch_reconfig_start_time_since_epoch_close_ms: IntGauge,
67
68    /// The total duration when this validator is halted, and hence does not
69    /// accept certs from users. This is the duration of (1) through (6)
70    /// above, and is the most important latency metric reflecting
71    /// reconfiguration delay for each validator.
72    pub epoch_validator_halt_duration_ms: IntGauge,
73
74    /// The interval from when the epoch begins (i.e. right after state
75    /// reconfigure, when the new epoch_store is created), to when the first
76    /// checkpoint of the epoch is ready for creation locally. This is (7)
77    /// above, and is a good proxy to how long it takes for the validator to
78    /// become useful in the network after reconfiguration.
79    // TODO: This needs to be reported properly.
80    pub epoch_first_checkpoint_created_time_since_epoch_begin_ms: IntGauge,
81
82    /// Whether we are running in safe mode where reward distribution and
83    /// tokenomics are disabled.
84    pub is_safe_mode: IntGauge,
85
86    /// When building the last checkpoint of the epoch, we execute advance epoch
87    /// transaction once without committing results to the store. It's
88    /// useful to know whether this execution leads to safe_mode, since in
89    /// theory the result could be different from checkpoint executor.
90    pub checkpoint_builder_advance_epoch_is_safe_mode: IntGauge,
91
92    /// Buffer stake current in effect for this epoch
93    pub effective_buffer_stake: IntGauge,
94
95    /// Set to 1 if the random beacon DKG protocol failed for the most recent
96    /// epoch.
97    pub epoch_random_beacon_dkg_failed: IntGauge,
98
99    /// The number of shares held by this node after the random beacon DKG
100    /// protocol completed.
101    pub epoch_random_beacon_dkg_num_shares: IntGauge,
102
103    /// The amount of time taken from epoch start to completion of random beacon
104    /// DKG protocol, for the most recent epoch.
105    pub epoch_random_beacon_dkg_epoch_start_completion_time_ms: IntGauge,
106
107    /// The amount of time taken to complete random beacon DKG protocol from the
108    /// time it was started (which may be a bit after the epcoh began), for
109    /// the most recent epoch.
110    pub epoch_random_beacon_dkg_completion_time_ms: IntGauge,
111
112    /// The amount of time taken to start first phase of the random beacon DKG
113    /// protocol, at which point the node has submitted a DKG Message, for
114    /// the most recent epoch.
115    pub epoch_random_beacon_dkg_message_time_ms: IntGauge,
116
117    /// The amount of time taken to complete first phase of the random beacon
118    /// DKG protocol, at which point the node has submitted a DKG
119    /// Confirmation, for the most recent epoch.
120    pub epoch_random_beacon_dkg_confirmation_time_ms: IntGauge,
121
122    /// The number of consensus output items in the quarantine.
123    pub consensus_quarantine_queue_size: IntGauge,
124
125    /// The number of consensus commits that injected deny-rule update
126    /// transactions.
127    pub deny_rule_updates_injected: IntCounter,
128
129    /// The number of injected deny-rule update transactions (one per chunk
130    /// of the delta).
131    pub deny_rule_update_transactions_injected: IntCounter,
132
133    /// Whether deny-rule removals are unlocked: enough announced stake this
134    /// epoch and the grace round floor passed.
135    pub deny_rule_removals_unlocked: IntGauge,
136
137    /// Set to 1, and never cleared, when the `TransactionDenyRules` object
138    /// diverged from the mirrored state at an epoch boundary.
139    pub deny_rule_mirror_divergence: IntGauge,
140
141    /// The number of injected deny-rule update transactions whose execution
142    /// failed — always an invariant violation.
143    pub deny_rule_update_execution_failures: IntCounter,
144}
145
146impl EpochMetrics {
147    pub fn new(registry: &Registry) -> Arc<Self> {
148        let this = Self {
149            current_epoch: register_int_gauge_with_registry!(
150                "current_epoch",
151                "Current epoch ID",
152                registry;
153                MetricLevel::Warn,
154            )
155            .unwrap(),
156            current_voting_right: register_int_gauge_with_registry!(
157                "current_voting_right",
158                "Current voting right of the validator",
159                registry;
160                MetricLevel::Warn,
161            )
162            .unwrap(),
163            epoch_checkpoint_count: register_int_gauge_with_registry!(
164                "epoch_checkpoint_count",
165                "Number of checkpoints in the epoch",
166                registry
167            ).unwrap(),
168            epoch_total_duration: register_int_gauge_with_registry!(
169                "epoch_total_duration",
170                "Total duration of the epoch",
171                registry;
172                MetricLevel::Warn,
173            ).unwrap(),
174            epoch_transaction_count: register_int_gauge_with_registry!(
175                "epoch_transaction_count",
176                "Number of transactions in the epoch",
177                registry
178            ).unwrap(),
179            epoch_total_gas_reward: register_int_gauge_with_registry!(
180                "epoch_total_gas_reward",
181                "Total amount of gas rewards (i.e. computation gas cost) in the epoch",
182                registry;
183                MetricLevel::Warn,
184            ).unwrap(),
185            epoch_pending_certs_processed_time_since_epoch_close_ms: register_int_gauge_with_registry!(
186                "epoch_pending_certs_processed_time_since_epoch_close_ms",
187                "Time interval from when epoch was closed to when all pending certificates are processed",
188                registry
189            ).unwrap(),
190            epoch_end_of_publish_quorum_time_since_epoch_close_ms: register_int_gauge_with_registry!(
191                "epoch_end_of_publish_quorum_time_since_epoch_close_ms",
192                "Time interval from when epoch was closed to when 2f+1 EndOfPublish messages are received",
193                registry
194            ).unwrap(),
195            epoch_last_checkpoint_created_time_since_epoch_close_ms: register_int_gauge_with_registry!(
196                "epoch_last_checkpoint_created_time_since_epoch_close_ms",
197                "Time interval from when epoch was closed to when the last checkpoint of the epoch is created",
198                registry
199            ).unwrap(),
200            epoch_reconfig_start_time_since_epoch_close_ms: register_int_gauge_with_registry!(
201                "epoch_reconfig_start_time_since_epoch_close_ms",
202                "Total time duration from when epoch was closed to when we begin to reconfigure the validator",
203                registry
204            ).unwrap(),
205            epoch_validator_halt_duration_ms: register_int_gauge_with_registry!(
206                "epoch_validator_halt_duration_ms",
207                "Total time duration when the validator was halted (i.e. epoch closed)",
208                registry
209            ).unwrap(),
210            epoch_first_checkpoint_created_time_since_epoch_begin_ms: register_int_gauge_with_registry!(
211                "epoch_first_checkpoint_created_time_since_epoch_begin_ms",
212                "Time interval from when the epoch opens at new epoch to the first checkpoint is created locally",
213                registry
214            ).unwrap(),
215            is_safe_mode: register_int_gauge_with_registry!(
216                "is_safe_mode",
217                "Whether we are running in safe mode",
218                registry;
219                MetricLevel::Info,
220            ).unwrap(),
221            checkpoint_builder_advance_epoch_is_safe_mode: register_int_gauge_with_registry!(
222                "checkpoint_builder_advance_epoch_is_safe_mode",
223                "Whether the advance epoch execution leads to safe mode while building the last checkpoint",
224                registry,
225            ).unwrap(),
226            effective_buffer_stake: register_int_gauge_with_registry!(
227                "effective_buffer_stake",
228                "Buffer stake current in effect for this epoch",
229                registry,
230            ).unwrap(),
231            epoch_random_beacon_dkg_failed: register_int_gauge_with_registry!(
232                "epoch_random_beacon_dkg_failed",
233                "Set to 1 if the random beacon DKG protocol failed for the most recent epoch.",
234                registry
235            )
236            .unwrap(),
237            epoch_random_beacon_dkg_num_shares: register_int_gauge_with_registry!(
238                "epoch_random_beacon_dkg_num_shares",
239                "The number of shares held by this node after the random beacon DKG protocol completed",
240                registry
241            )
242            .unwrap(),
243            epoch_random_beacon_dkg_epoch_start_completion_time_ms: register_int_gauge_with_registry!(
244                "epoch_random_beacon_dkg_epoch_start_completion_time_ms",
245                "The amount of time taken from epoch start to completion of random beacon DKG protocol, for the most recent epoch",
246                registry
247            )
248            .unwrap(),
249            epoch_random_beacon_dkg_completion_time_ms: register_int_gauge_with_registry!(
250                "epoch_random_beacon_dkg_completion_time_ms",
251                "The amount of time taken to complete random beacon DKG protocol from the time it was started (which may be a bit after the epoch began), for the most recent epoch",
252                registry
253            )
254            .unwrap(),
255            epoch_random_beacon_dkg_message_time_ms: register_int_gauge_with_registry!(
256                "epoch_random_beacon_dkg_message_time_ms",
257                "The amount of time taken to start first phase of the random beacon DKG protocol, at which point the node has submitted a DKG Message, for the most recent epoch",
258                registry
259            )
260            .unwrap(),
261            epoch_random_beacon_dkg_confirmation_time_ms: register_int_gauge_with_registry!(
262                "epoch_random_beacon_dkg_confirmation_time_ms",
263                "The amount of time taken to complete first phase of the random beacon DKG protocol, at which point the node has submitted a DKG Confirmation, for the most recent epoch",
264                registry
265            )
266            .unwrap(),
267            consensus_quarantine_queue_size: register_int_gauge_with_registry!(
268                "consensus_quarantine_queue_size",
269                "The number of consensus output items in the quarantine",
270                registry;
271                MetricLevel::Warn,
272            )
273            .unwrap(),
274            deny_rule_updates_injected: register_int_counter_with_registry!(
275                "deny_rule_updates_injected",
276                "The number of consensus commits that injected deny-rule update transactions",
277                registry
278            )
279            .unwrap(),
280            deny_rule_update_transactions_injected: register_int_counter_with_registry!(
281                "deny_rule_update_transactions_injected",
282                "The number of injected deny-rule update transactions",
283                registry
284            )
285            .unwrap(),
286            deny_rule_removals_unlocked: register_int_gauge_with_registry!(
287                "deny_rule_removals_unlocked",
288                "Whether deny-rule removals are currently unlocked",
289                registry
290            )
291            .unwrap(),
292            deny_rule_mirror_divergence: register_int_gauge_with_registry!(
293                "deny_rule_mirror_divergence",
294                "Set to 1 when the TransactionDenyRules object diverged from the mirrored state \
295                 at an epoch boundary",
296                registry
297            )
298            .unwrap(),
299            deny_rule_update_execution_failures: register_int_counter_with_registry!(
300                "deny_rule_update_execution_failures",
301                "The number of injected deny-rule update transactions whose execution failed",
302                registry
303            )
304            .unwrap(),
305        };
306        Arc::new(this)
307    }
308}