diff --git a/Cargo.lock b/Cargo.lock index 6a40ffd..e8f9e75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1994,6 +1994,7 @@ dependencies = [ "datatest-stable 0.3.3", "ethlambda-types", "hex", + "prometheus", "serde", "serde_json", "thiserror 2.0.17", diff --git a/crates/blockchain/state_transition/Cargo.toml b/crates/blockchain/state_transition/Cargo.toml index be1e343..94ee8cb 100644 --- a/crates/blockchain/state_transition/Cargo.toml +++ b/crates/blockchain/state_transition/Cargo.toml @@ -13,6 +13,7 @@ version.workspace = true ethlambda-types.workspace = true thiserror.workspace = true +prometheus.workspace = true [dev-dependencies] serde.workspace = true diff --git a/crates/blockchain/state_transition/src/lib.rs b/crates/blockchain/state_transition/src/lib.rs index 08fb7d8..742ff67 100644 --- a/crates/blockchain/state_transition/src/lib.rs +++ b/crates/blockchain/state_transition/src/lib.rs @@ -7,6 +7,7 @@ use ethlambda_types::{ }; mod justified_slots_ops; +pub mod metrics; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -65,7 +66,9 @@ pub fn process_slots(state: &mut State, target_slot: u64) -> Result<(), Error> { // Special case: cache the state root if not already set. state.latest_block_header.state_root = state.tree_hash_root(); } + let slots_processed = target_slot - state.slot; state.slot = target_slot; + metrics::inc_slots_processed(slots_processed); Ok(()) } @@ -182,6 +185,7 @@ fn process_attestations( attestations: &AggregatedAttestations, ) -> Result<(), Error> { let validator_count = state.validators.len(); + let mut attestations_processed: u64 = 0; let mut justifications: HashMap> = state .justifications_roots .iter() @@ -259,6 +263,7 @@ fn process_attestations( } // Record the vote + attestations_processed += 1; let votes = justifications .entry(target.root) .or_insert_with(|| std::iter::repeat_n(false, validator_count).collect()); @@ -292,6 +297,7 @@ fn process_attestations( { let old_finalized_slot = state.latest_finalized.slot; state.latest_finalized = source; + metrics::inc_finalizations("success"); // Shift window to drop finalized slots from the front let delta = (state.latest_finalized.slot - old_finalized_slot) as usize; @@ -331,6 +337,7 @@ fn process_attestations( .try_into() .expect("justifications_roots limit exceeded"); state.justifications_validators = justifications_validators; + metrics::inc_attestations_processed(attestations_processed); Ok(()) } diff --git a/crates/blockchain/state_transition/src/metrics.rs b/crates/blockchain/state_transition/src/metrics.rs new file mode 100644 index 0000000..59785f5 --- /dev/null +++ b/crates/blockchain/state_transition/src/metrics.rs @@ -0,0 +1,46 @@ +//! Prometheus metrics for state transition. + +use std::sync::LazyLock; + +use prometheus::{IntCounter, IntCounterVec, register_int_counter, register_int_counter_vec}; + +static LEAN_STATE_TRANSITION_SLOTS_PROCESSED_TOTAL: LazyLock = LazyLock::new(|| { + register_int_counter!( + "lean_state_transition_slots_processed_total", + "Count of processed slots" + ) + .unwrap() +}); + +static LEAN_STATE_TRANSITION_ATTESTATIONS_PROCESSED_TOTAL: LazyLock = + LazyLock::new(|| { + register_int_counter!( + "lean_state_transition_attestations_processed_total", + "Count of processed attestations" + ) + .unwrap() + }); + +static LEAN_FINALIZATIONS_TOTAL: LazyLock = LazyLock::new(|| { + register_int_counter_vec!( + "lean_finalizations_total", + "Total number of finalization attempts", + &["result"] + ) + .unwrap() +}); + +/// Increment the slots processed counter by the given amount. +pub fn inc_slots_processed(count: u64) { + LEAN_STATE_TRANSITION_SLOTS_PROCESSED_TOTAL.inc_by(count); +} + +/// Increment the attestations processed counter by the given amount. +pub fn inc_attestations_processed(count: u64) { + LEAN_STATE_TRANSITION_ATTESTATIONS_PROCESSED_TOTAL.inc_by(count); +} + +/// Increment the finalization counter with the given result. +pub fn inc_finalizations(result: &str) { + LEAN_FINALIZATIONS_TOTAL.with_label_values(&[result]).inc(); +} diff --git a/docs/metrics.md b/docs/metrics.md index 00283bb..3ab6024 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -47,12 +47,12 @@ The exposed metrics follow [the leanMetrics specification](https://github.com/le |--------|-------|-------|-------------------------|--------|---------|-----------| | `lean_latest_justified_slot` | Gauge | Latest justified slot | On state transition | | | ✅ | | `lean_latest_finalized_slot` | Gauge | Latest finalized slot | On state transition | | | ✅ | -| `lean_finalizations_total` | Counter | Total number of finalization attempts | On finalization attempt | result=success,error | | □ | +| `lean_finalizations_total` | Counter | Total number of finalization attempts | On finalization attempt | result=success,error | | ✅ | |`lean_state_transition_time_seconds`| Histogram | Time to process state transition | On state transition | | 0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3, 4 | □ | -|`lean_state_transition_slots_processed_total`| Counter | Total number of processed slots | On state transition process slots | | | □ | +|`lean_state_transition_slots_processed_total`| Counter | Total number of processed slots | On state transition process slots | | | ✅ | |`lean_state_transition_slots_processing_time_seconds`| Histogram | Time taken to process slots | On state transition process slots | | 0.005, 0.01, 0.025, 0.05, 0.1, 1 | □ | |`lean_state_transition_block_processing_time_seconds`| Histogram | Time taken to process block | On state transition process block | | 0.005, 0.01, 0.025, 0.05, 0.1, 1 | □ | -|`lean_state_transition_attestations_processed_total`| Counter | Total number of processed attestations | On state transition process attestations | | | □ | +|`lean_state_transition_attestations_processed_total`| Counter | Total number of processed attestations | On state transition process attestations | | | ✅ | |`lean_state_transition_attestations_processing_time_seconds`| Histogram | Time taken to process attestations | On state transition process attestations | | 0.005, 0.01, 0.025, 0.05, 0.1, 1 | □ | ## Validator Metrics