diff --git a/crates/op-rbuilder/src/builders/flashblocks/payload.rs b/crates/op-rbuilder/src/builders/flashblocks/payload.rs index b92e35c7..79a68e7e 100644 --- a/crates/op-rbuilder/src/builders/flashblocks/payload.rs +++ b/crates/op-rbuilder/src/builders/flashblocks/payload.rs @@ -529,9 +529,16 @@ where ); // Process flashblocks - block on async channel receive + let mut wait_start: Option = None; loop { // Wait for signal before building flashblock. if let Ok(new_fb_cancel) = rx.recv() { + if let Some(start) = wait_start { + ctx.metrics.record_flashblock_wait_for_next_tick( + ctx.flashblock_index(), + start.elapsed(), + ); + } debug!( target: "payload_builder", id = %fb_payload.payload_id, @@ -585,6 +592,7 @@ where } }; + wait_start = Some(Instant::now()); ctx = ctx.with_extra_ctx(next_flashblocks_ctx); } } @@ -759,15 +767,18 @@ where best_payload.set(new_payload); // Record flashblock build duration + let flashblock_build_duration = flashblock_build_start_time.elapsed(); ctx.metrics .flashblock_build_duration - .record(flashblock_build_start_time.elapsed()); + .record(flashblock_build_duration); ctx.metrics .flashblock_byte_size_histogram .record(flashblock_byte_size as f64); ctx.metrics .flashblock_num_tx_histogram .record(info.executed_transactions.len() as f64); + ctx.metrics + .record_flashblock_indexed_metrics(flashblock_index, flashblock_build_duration); // Update bundle_state for next iteration if let Some(da_limit) = ctx.extra_ctx.da_per_batch { diff --git a/crates/op-rbuilder/src/metrics.rs b/crates/op-rbuilder/src/metrics.rs index cd974e52..3f687928 100644 --- a/crates/op-rbuilder/src/metrics.rs +++ b/crates/op-rbuilder/src/metrics.rs @@ -1,8 +1,10 @@ +use std::time::Duration; + use alloy_primitives::{Address, hex}; use metrics::IntoF64; use reth_metrics::{ Metrics, - metrics::{Counter, Gauge, Histogram, gauge}, + metrics::{Counter, Gauge, Histogram, SharedString, counter, gauge, histogram}, }; use crate::{ @@ -194,6 +196,40 @@ impl OpRBuilderMetrics { self.bundles_reverted.record(num_bundles_reverted); self.payload_reverted_tx_gas_used.set(reverted_gas_used); } + + /// Record per-flashblock-index metrics for build duration and emission. + pub fn record_flashblock_indexed_metrics( + &self, + flashblock_index: u64, + build_duration: Duration, + ) { + let index_label: SharedString = flashblock_index.to_string().into(); + histogram!( + "op_rbuilder_flashblock_build_duration_seconds_by_index", + "flashblock_index" => index_label.clone() + ) + .record(build_duration.as_secs_f64()); + counter!( + "op_rbuilder_flashblock_emitted_total", + "flashblock_index" => index_label + ) + .increment(1); + } + + /// Record the time spent waiting between finishing a flashblock build and + /// receiving the next tick from the scheduler. + pub fn record_flashblock_wait_for_next_tick( + &self, + flashblock_index: u64, + wait_duration: Duration, + ) { + let index_label: SharedString = flashblock_index.to_string().into(); + histogram!( + "op_rbuilder_flashblock_wait_for_next_tick_duration_seconds", + "flashblock_index" => index_label + ) + .record(wait_duration.as_secs_f64()); + } } /// Set gauge metrics for some flags so we can inspect which ones are set