From bbf1ef4733e94c7c8edf0b22e1c70665fdb27154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Gr=C3=BCner?= <47506558+MegaRedHand@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:57:44 -0300 Subject: [PATCH 1/3] feat: add state transition counter metrics Add Group 2 metrics from the leanMetrics specification: - lean_state_transition_slots_processed_total: Count of processed slots - lean_state_transition_attestations_processed_total: Count of processed attestations - lean_finalizations_total: Total finalization events with result label The metrics module is added to the state_transition crate and instrumented in process_slots() and process_attestations(). --- Cargo.lock | 1 + crates/blockchain/state_transition/Cargo.toml | 1 + crates/blockchain/state_transition/src/lib.rs | 5 ++ .../state_transition/src/metrics.rs | 46 +++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 crates/blockchain/state_transition/src/metrics.rs diff --git a/Cargo.lock b/Cargo.lock index 6a40ffd7..e8f9e754 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 be1e343c..94ee8cb2 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 08fb7d8a..8d165563 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(()) } @@ -181,6 +184,7 @@ fn process_attestations( state: &mut State, attestations: &AggregatedAttestations, ) -> Result<(), Error> { + metrics::inc_attestations_processed(attestations.len() as u64); let validator_count = state.validators.len(); let mut justifications: HashMap> = state .justifications_roots @@ -292,6 +296,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; diff --git a/crates/blockchain/state_transition/src/metrics.rs b/crates/blockchain/state_transition/src/metrics.rs new file mode 100644 index 00000000..59785f5c --- /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(); +} From 349fee99834eb2bd12dd75e093f65646311ca8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Gr=C3=BCner?= <47506558+MegaRedHand@users.noreply.github.com> Date: Mon, 26 Jan 2026 10:28:13 -0300 Subject: [PATCH 2/3] fix: count only processed attestations --- crates/blockchain/state_transition/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/blockchain/state_transition/src/lib.rs b/crates/blockchain/state_transition/src/lib.rs index 8d165563..742ff67d 100644 --- a/crates/blockchain/state_transition/src/lib.rs +++ b/crates/blockchain/state_transition/src/lib.rs @@ -184,8 +184,8 @@ fn process_attestations( state: &mut State, attestations: &AggregatedAttestations, ) -> Result<(), Error> { - metrics::inc_attestations_processed(attestations.len() as u64); let validator_count = state.validators.len(); + let mut attestations_processed: u64 = 0; let mut justifications: HashMap> = state .justifications_roots .iter() @@ -263,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()); @@ -336,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(()) } From 7ad3ffc4b67e607fda2f6709f783e557d62eb1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Gr=C3=BCner?= <47506558+MegaRedHand@users.noreply.github.com> Date: Mon, 26 Jan 2026 10:37:55 -0300 Subject: [PATCH 3/3] docs: update metrics checklist with new metrics --- docs/metrics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/metrics.md b/docs/metrics.md index 00283bb3..3ab60245 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