Skip to main content

sui_core/epoch/
epoch_metrics.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use prometheus::{
5    CounterVec, IntCounter, IntCounterVec, IntGauge, Registry, register_counter_vec_with_registry,
6    register_int_counter_vec_with_registry, register_int_counter_with_registry,
7    register_int_gauge_with_registry,
8};
9use std::sync::Arc;
10
11pub struct EpochMetrics {
12    /// The current epoch ID. This is updated only when the AuthorityState finishes reconfiguration.
13    pub current_epoch: IntGauge,
14
15    /// Current voting right of the validator in the protocol. Updated at the start of epochs.
16    pub current_voting_right: IntGauge,
17
18    /// Total duration of the epoch. This is measured from when the current epoch store is opened,
19    /// until the current epoch store is replaced with the next epoch store.
20    pub epoch_total_duration: IntGauge,
21
22    /// Number of checkpoints in the epoch.
23    pub epoch_checkpoint_count: IntGauge,
24
25    /// Number of transactions in the epoch.
26    pub epoch_transaction_count: IntGauge,
27
28    /// Total amount of gas rewards (i.e. computation gas cost) in the epoch.
29    pub epoch_total_gas_reward: IntGauge,
30
31    // An active validator reconfigures through the following steps:
32    // 1. Halt validator (a.k.a. close epoch) and stop accepting user transaction certs.
33    // 2. Finishes processing all pending certificates and then send EndOfPublish message.
34    // 3. Stop accepting messages from consensus after seeing 2f+1 EndOfPublish messages.
35    // 4. Creating the last checkpoint of the epoch by augmenting it with AdvanceEpoch transaction.
36    // 5. CheckpointExecutor finishes executing the last checkpoint, and triggers reconfiguration.
37    // 6. During reconfiguration, we tear down consensus, reconfigure state (at which point we opens
38    //    up user certs), and start consensus again.
39    // 7. After reconfiguration, and eventually consensus starts successfully, at some point the first
40    //    checkpoint of the new epoch will be created.
41    // We introduce various metrics to cover the latency of above steps.
42    /// The duration from when the epoch is closed (i.e. validator halted) to when all pending
43    /// certificates are processed (i.e. ready to send EndOfPublish message).
44    /// This is the duration of (1) through (2) above.
45    pub epoch_pending_certs_processed_time_since_epoch_close_ms: IntGauge,
46
47    /// The interval from when the epoch is closed to when we receive 2f+1 EndOfPublish messages.
48    /// This is the duration of (1) through (3) above.
49    pub epoch_end_of_publish_quorum_time_since_epoch_close_ms: IntGauge,
50
51    /// The interval from when the epoch is closed to when we created the last checkpoint of the
52    /// epoch.
53    /// This is the duration of (1) through (4) above.
54    pub epoch_last_checkpoint_created_time_since_epoch_close_ms: IntGauge,
55
56    /// The interval from when the epoch is closed to when we finished executing the last transaction
57    /// of the checkpoint (and hence triggering reconfiguration process).
58    /// This is the duration of (1) through (5) above.
59    pub epoch_reconfig_start_time_since_epoch_close_ms: IntGauge,
60
61    /// The total duration when this validator is halted, and hence does not accept certs from users.
62    /// This is the duration of (1) through (6) above, and is the most important latency metric
63    /// reflecting reconfiguration delay for each validator.
64    pub epoch_validator_halt_duration_ms: IntGauge,
65
66    /// The interval from when the epoch begins (i.e. right after state reconfigure, when the new
67    /// epoch_store is created), to when the first checkpoint of the epoch is ready for creation locally.
68    /// This is (7) above, and is a good proxy to how long it takes for the validator
69    /// to become useful in the network after reconfiguration.
70    // TODO: This needs to be reported properly.
71    pub epoch_first_checkpoint_created_time_since_epoch_begin_ms: IntGauge,
72
73    /// Whether we are running in safe mode where reward distribution and tokenomics are disabled.
74    pub is_safe_mode: IntGauge,
75
76    /// When building the last checkpoint of the epoch, we execute advance epoch transaction once
77    /// without committing results to the store. It's useful to know whether this execution leads
78    /// to safe_mode, since in theory the result could be different from checkpoint executor.
79    pub checkpoint_builder_advance_epoch_is_safe_mode: IntGauge,
80
81    /// Buffer stake current in effect for this epoch
82    pub effective_buffer_stake: IntGauge,
83
84    /// Set to 1 while the random beacon DKG protocol is unavailable after its timeout.
85    pub epoch_random_beacon_dkg_failed: IntGauge,
86
87    /// Set to 1 if the random beacon DKG protocol completed after its timeout.
88    /// Process-local: not restored after a mid-epoch restart.
89    pub epoch_random_beacon_dkg_completed_after_timeout: IntGauge,
90
91    /// The number of shares held by this node after the random beacon DKG protocol completed.
92    pub epoch_random_beacon_dkg_num_shares: IntGauge,
93
94    /// The amount of time taken from epoch start to completion of random beacon DKG protocol,
95    /// for the most recent epoch.
96    pub epoch_random_beacon_dkg_epoch_start_completion_time_ms: IntGauge,
97
98    /// The amount of time taken to complete random beacon DKG protocol from the time it was
99    /// started (which may be a bit after the epcoh began), for the most recent epoch.
100    pub epoch_random_beacon_dkg_completion_time_ms: IntGauge,
101
102    /// The amount of time taken to start first phase of the random beacon DKG protocol,
103    /// at which point the node has submitted a DKG Message, for the most recent epoch.
104    pub epoch_random_beacon_dkg_message_time_ms: IntGauge,
105
106    /// The amount of time taken to complete first phase of the random beacon DKG protocol,
107    /// at which point the node has submitted a DKG Confirmation, for the most recent epoch.
108    pub epoch_random_beacon_dkg_confirmation_time_ms: IntGauge,
109
110    /// The number of execution time observations messages shared by this node.
111    pub epoch_execution_time_observations_shared: IntCounter,
112
113    /// The number of execution time observations messages intended to be shared by this node, annotated with reason.
114    pub epoch_execution_time_observations_sharing_reason: IntCounterVec,
115
116    /// The number of execution time measurements dropped due to backpressure from the observer.
117    pub epoch_execution_time_measurements_dropped: IntCounter,
118
119    /// The number of execution time consensus messages dropped.
120    pub epoch_execution_time_observations_dropped: IntCounterVec,
121
122    /// The number of cached indebted objects in the execution time observer.
123    pub epoch_execution_time_observer_indebted_objects: IntGauge,
124
125    /// The number of objects tracked by the object utilization cache.
126    pub epoch_execution_time_observer_utilization_cache_size: IntGauge,
127
128    /// The number of objects determined by the execution time observer to be overutilized.
129    /// Note: this may overcount if objects are evicted from the cache before being computed
130    /// as not-overutilized.
131    pub epoch_execution_time_observer_overutilized_objects: IntGauge,
132
133    /// Per-object utilization for objects that were overutilized at least once at some
134    /// point in their lifetime.
135    /// Note: This metric is disabled by default as it may have very large cardinality.
136    pub epoch_execution_time_observer_object_utilization: CounterVec,
137
138    /// Utilization of the objects listed in
139    /// `ExecutionTimeObserverConfig::object_utilization_metric_tracked_ids`, labeled by full
140    /// object ID and configured name, reported regardless of whether the object is
141    /// overutilized.
142    pub epoch_execution_time_observer_tracked_object_utilization: CounterVec,
143
144    /// The number of execution time observations loaded at start of epoch.
145    pub epoch_execution_time_observations_loaded: IntGauge,
146
147    /// The number of consensus output items in the quarantine.
148    pub consensus_quarantine_queue_size: IntGauge,
149
150    /// The number of shared object assignments in the quarantine.
151    pub shared_object_assignments_size: IntGauge,
152}
153
154impl EpochMetrics {
155    pub fn new(registry: &Registry) -> Arc<Self> {
156        let this = Self {
157            current_epoch: register_int_gauge_with_registry!(
158                "current_epoch",
159                "Current epoch ID",
160                registry
161            )
162            .unwrap(),
163            current_voting_right: register_int_gauge_with_registry!(
164                "current_voting_right",
165                "Current voting right of the validator",
166                registry
167            )
168            .unwrap(),
169            epoch_checkpoint_count: register_int_gauge_with_registry!(
170                "epoch_checkpoint_count",
171                "Number of checkpoints in the epoch",
172                registry
173            ).unwrap(),
174            epoch_total_duration: register_int_gauge_with_registry!(
175                "epoch_total_duration",
176                "Total duration of the epoch",
177                registry
178            ).unwrap(),
179            epoch_transaction_count: register_int_gauge_with_registry!(
180                "epoch_transaction_count",
181                "Number of transactions in the epoch",
182                registry
183            ).unwrap(),
184            epoch_total_gas_reward: register_int_gauge_with_registry!(
185                "epoch_total_gas_reward",
186                "Total amount of gas rewards (i.e. computation gas cost) in the epoch",
187                registry
188            ).unwrap(),
189            epoch_pending_certs_processed_time_since_epoch_close_ms: register_int_gauge_with_registry!(
190                "epoch_pending_certs_processed_time_since_epoch_close_ms",
191                "Time interval from when epoch was closed to when all pending certificates are processed",
192                registry
193            ).unwrap(),
194            epoch_end_of_publish_quorum_time_since_epoch_close_ms: register_int_gauge_with_registry!(
195                "epoch_end_of_publish_quorum_time_since_epoch_close_ms",
196                "Time interval from when epoch was closed to when 2f+1 EndOfPublish messages are received",
197                registry
198            ).unwrap(),
199            epoch_last_checkpoint_created_time_since_epoch_close_ms: register_int_gauge_with_registry!(
200                "epoch_last_checkpoint_created_time_since_epoch_close_ms",
201                "Time interval from when epoch was closed to when the last checkpoint of the epoch is created",
202                registry
203            ).unwrap(),
204            epoch_reconfig_start_time_since_epoch_close_ms: register_int_gauge_with_registry!(
205                "epoch_reconfig_start_time_since_epoch_close_ms",
206                "Total time duration from when epoch was closed to when we begin to reconfigure the validator",
207                registry
208            ).unwrap(),
209            epoch_validator_halt_duration_ms: register_int_gauge_with_registry!(
210                "epoch_validator_halt_duration_ms",
211                "Total time duration when the validator was halted (i.e. epoch closed)",
212                registry
213            ).unwrap(),
214            epoch_first_checkpoint_created_time_since_epoch_begin_ms: register_int_gauge_with_registry!(
215                "epoch_first_checkpoint_created_time_since_epoch_begin_ms",
216                "Time interval from when the epoch opens at new epoch to the first checkpoint is created locally",
217                registry
218            ).unwrap(),
219            is_safe_mode: register_int_gauge_with_registry!(
220                "is_safe_mode",
221                "Whether we are running in safe mode",
222                registry,
223            ).unwrap(),
224            checkpoint_builder_advance_epoch_is_safe_mode: register_int_gauge_with_registry!(
225                "checkpoint_builder_advance_epoch_is_safe_mode",
226                "Whether the advance epoch execution leads to safe mode while building the last checkpoint",
227                registry,
228            ).unwrap(),
229            effective_buffer_stake: register_int_gauge_with_registry!(
230                "effective_buffer_stake",
231                "Buffer stake current in effect for this epoch",
232                registry,
233            ).unwrap(),
234            epoch_random_beacon_dkg_failed: register_int_gauge_with_registry!(
235                "epoch_random_beacon_dkg_failed",
236                "Set to 1 while the random beacon DKG protocol is unavailable after its timeout.",
237                registry
238            )
239            .unwrap(),
240            epoch_random_beacon_dkg_completed_after_timeout: register_int_gauge_with_registry!(
241                "epoch_random_beacon_dkg_completed_after_timeout",
242                "Set to 1 if the random beacon DKG protocol completed after its timeout.",
243                registry
244            )
245            .unwrap(),
246            epoch_random_beacon_dkg_num_shares: register_int_gauge_with_registry!(
247                "epoch_random_beacon_dkg_num_shares",
248                "The number of shares held by this node after the random beacon DKG protocol completed",
249                registry
250            )
251            .unwrap(),
252            epoch_random_beacon_dkg_epoch_start_completion_time_ms: register_int_gauge_with_registry!(
253                "epoch_random_beacon_dkg_epoch_start_completion_time_ms",
254                "The amount of time taken from epoch start to completion of random beacon DKG protocol, for the most recent epoch",
255                registry
256            )
257            .unwrap(),
258            epoch_random_beacon_dkg_completion_time_ms: register_int_gauge_with_registry!(
259                "epoch_random_beacon_dkg_completion_time_ms",
260                "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",
261                registry
262            )
263            .unwrap(),
264            epoch_random_beacon_dkg_message_time_ms: register_int_gauge_with_registry!(
265                "epoch_random_beacon_dkg_message_time_ms",
266                "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",
267                registry
268            )
269            .unwrap(),
270            epoch_random_beacon_dkg_confirmation_time_ms: register_int_gauge_with_registry!(
271                "epoch_random_beacon_dkg_confirmation_time_ms",
272                "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",
273                registry
274            )
275            .unwrap(),
276            epoch_execution_time_observations_shared: register_int_counter_with_registry!(
277                "epoch_execution_time_observations_shared",
278                "The number of execution time observations messages shared by this node",
279                registry
280            )
281            .unwrap(),
282            epoch_execution_time_observations_sharing_reason: register_int_counter_vec_with_registry!(
283                "epoch_execution_time_observations_sharing_reason",
284                "The number of execution time observations messages intended to be shared by this node, annotated with reason",
285                &["reason"],
286                registry
287            )
288            .unwrap(),
289            epoch_execution_time_measurements_dropped: register_int_counter_with_registry!(
290                "epoch_execution_time_measurements_dropped",
291                "The number of execution time measurements dropped due to backpressure from the observer",
292                registry
293            )
294            .unwrap(),
295            epoch_execution_time_observations_dropped: register_int_counter_vec_with_registry!(
296                "epoch_execution_time_observations_dropped",
297                "The number of execution time observations dropped",
298                &["reason"],
299                registry
300            )
301            .unwrap(),
302            epoch_execution_time_observer_indebted_objects: register_int_gauge_with_registry!(
303                "epoch_execution_time_observer_indebted_objects",
304                "The number of cached indebted objects in the execution time observer",
305                registry
306            )
307            .unwrap(),
308            epoch_execution_time_observer_utilization_cache_size: register_int_gauge_with_registry!(
309                "epoch_execution_time_observer_utilization_cache_size",
310                "The number of objects tracked by the object utilization cache",
311                registry
312            )
313            .unwrap(),
314            epoch_execution_time_observer_overutilized_objects: register_int_gauge_with_registry!(
315                "epoch_execution_time_observer_overutilized_objects",
316                "The number of objects determined by the execution time observer to be overutilized. Note: this may overcount if objects are evicted from the cache before being computed as not-overutilized.",
317                registry
318            )
319            .unwrap(),
320            epoch_execution_time_observer_object_utilization: register_counter_vec_with_registry!(
321                "epoch_execution_time_observer_object_utilization",
322                "Per-object utilization for objects that were overutilized at least once at some point in their lifetime",
323                &["object_id"],
324                registry
325            )
326            .unwrap(),
327            epoch_execution_time_observer_tracked_object_utilization: register_counter_vec_with_registry!(
328                "epoch_execution_time_observer_tracked_object_utilization",
329                "Utilization of objects explicitly listed in the execution time observer config, labeled by full object ID and configured name",
330                &["object_id", "name"],
331                registry
332            )
333            .unwrap(),
334            epoch_execution_time_observations_loaded: register_int_gauge_with_registry!(
335                "epoch_execution_time_observations_loaded",
336                "The number of execution time observations loaded at start of epoch",
337                registry
338            )
339            .unwrap(),
340            consensus_quarantine_queue_size: register_int_gauge_with_registry!(
341                "consensus_quarantine_queue_size",
342                "The number of consensus output items in the quarantine",
343                registry
344            )
345            .unwrap(),
346            shared_object_assignments_size: register_int_gauge_with_registry!(
347                "shared_object_assignments_size",
348                "The number of shared object assignments in the quarantine",
349                registry
350            )
351            .unwrap(),
352        };
353        Arc::new(this)
354    }
355}