diff --git a/crates/optimism/trie/src/prune/error.rs b/crates/optimism/trie/src/prune/error.rs index 6eb2b8c30ed..8f46f29d20d 100644 --- a/crates/optimism/trie/src/prune/error.rs +++ b/crates/optimism/trie/src/prune/error.rs @@ -16,6 +16,10 @@ pub type OpProofStoragePrunerResult = Result; pub struct PrunerOutput { /// Total elapsed wall time for this run (fetch + apply). pub duration: Duration, + /// Time elapsed during the stat diff fetch phase(non-blocking). + pub fetch_duration: Duration, + /// Time elapsed during the prune phase. + pub prune_duration: Duration, /// Earliest block at the start of the run. pub start_block: u64, /// New earliest block at the end of the run. @@ -64,6 +68,8 @@ mod tests { fn test_pruner_output_display() { let pruner_output = PrunerOutput { duration: Duration::from_secs(10), + fetch_duration: Duration::from_secs(5), + prune_duration: Duration::from_secs(5), start_block: 1, end_block: 2, total_entries_pruned: 3, diff --git a/crates/optimism/trie/src/prune/metrics.rs b/crates/optimism/trie/src/prune/metrics.rs new file mode 100644 index 00000000000..62c51fd82b0 --- /dev/null +++ b/crates/optimism/trie/src/prune/metrics.rs @@ -0,0 +1,30 @@ +use crate::PrunerOutput; +use reth_metrics::{ + metrics::{Gauge, Histogram}, + Metrics, +}; + +#[derive(Metrics)] +#[metrics(scope = "optimism_trie.pruner")] +pub(crate) struct Metrics { + /// Pruning duration + pub(crate) total_duration_seconds: Histogram, + /// Duration spent fetching state diffs (non-blocking) + pub(crate) state_diff_fetch_duration_seconds: Histogram, + /// Duration spent pruning + pub(crate) prune_duration_seconds: Histogram, + /// Number of pruned blocks + pub(crate) pruned_blocks: Gauge, +} + +impl Metrics { + pub(crate) fn record_prune_result(&self, result: PrunerOutput) { + let blocks_pruned = result.end_block - result.start_block; + if blocks_pruned > 0 { + self.total_duration_seconds.record(result.duration.as_secs_f64()); + self.state_diff_fetch_duration_seconds.record(result.fetch_duration.as_secs_f64()); + self.prune_duration_seconds.record(result.prune_duration.as_secs_f64()); + self.pruned_blocks.set(blocks_pruned as f64); + } + } +} diff --git a/crates/optimism/trie/src/prune/mod.rs b/crates/optimism/trie/src/prune/mod.rs index 51af623c3d4..fd0a837459a 100644 --- a/crates/optimism/trie/src/prune/mod.rs +++ b/crates/optimism/trie/src/prune/mod.rs @@ -4,5 +4,6 @@ pub use error::{OpProofStoragePrunerResult, PrunerError, PrunerOutput}; mod pruner; pub use pruner::OpProofStoragePruner; +mod metrics; mod task; pub use task::OpProofStoragePrunerTask; diff --git a/crates/optimism/trie/src/prune/pruner.rs b/crates/optimism/trie/src/prune/pruner.rs index a4f49a48bd0..0305ca65d66 100644 --- a/crates/optimism/trie/src/prune/pruner.rs +++ b/crates/optimism/trie/src/prune/pruner.rs @@ -1,15 +1,17 @@ use crate::{ - prune::error::{OpProofStoragePrunerResult, PrunerError, PrunerOutput}, + prune::{ + error::{OpProofStoragePrunerResult, PrunerError, PrunerOutput}, + metrics::Metrics, + }, BlockStateDiff, OpProofsStore, }; use alloy_eips::{eip1898::BlockWithParent, BlockNumHash}; -use derive_more::Constructor; use reth_provider::BlockHashReader; use tokio::time::Instant; use tracing::{error, info, trace}; /// Prunes the proof storage by calling `prune_earliest_state` on the storage provider. -#[derive(Debug, Constructor)] +#[derive(Debug)] pub struct OpProofStoragePruner { // Database provider for the prune provider: P, @@ -18,7 +20,15 @@ pub struct OpProofStoragePruner { /// Keep at least these many recent blocks min_block_interval: u64, // TODO: add timeout - Maximum time for one pruner run. If `None`, no timeout. - // TODO: metrics + #[doc(hidden)] + metrics: Metrics, +} + +impl OpProofStoragePruner { + /// Create a new pruner. + pub fn new(provider: P, block_hash_reader: H, min_block_interval: u64) -> Self { + Self { provider, block_hash_reader, min_block_interval, metrics: Metrics::default() } + } } impl OpProofStoragePruner @@ -70,6 +80,7 @@ where let diff = self.provider.fetch_trie_updates(i).await?; final_diff.extend(diff); } + let stat_diff_fetch_duration = t.elapsed(); let new_earliest_block_hash = self .block_hash_reader @@ -89,12 +100,18 @@ where self.provider.prune_earliest_state(block_with_parent, final_diff).await?; - Ok(PrunerOutput { - duration: t.elapsed(), + let total_duration = t.elapsed(); + let prune_output = PrunerOutput { + duration: total_duration, + fetch_duration: stat_diff_fetch_duration, + prune_duration: total_duration.saturating_sub(stat_diff_fetch_duration), start_block: earliest_block, - end_block: new_earliest_block - 1, + end_block: new_earliest_block.saturating_sub(1), total_entries_pruned: 0, // TODO: get it from the prune_earliest_state - }) + }; + self.metrics.record_prune_result(prune_output.clone()); + + Ok(prune_output) } /// Run the pruner diff --git a/crates/optimism/trie/src/prune/task.rs b/crates/optimism/trie/src/prune/task.rs index 35b120bd846..b47abe1e25d 100644 --- a/crates/optimism/trie/src/prune/task.rs +++ b/crates/optimism/trie/src/prune/task.rs @@ -21,7 +21,7 @@ where H: BlockHashReader, { /// Initialize a new [`OpProofStoragePrunerTask`] - pub const fn new( + pub fn new( provider: P, hash_reader: H, min_block_interval: u64,