diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index d4d06330..96426201 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -21,12 +21,13 @@ jobs: - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@clippy with: + toolchain: nightly-2026-01-05 components: clippy - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true - name: Run clippy - run: cargo clippy --workspace --lib --examples --tests --benches --all-features --locked + run: cargo clean && cargo clippy --workspace --lib --examples --tests --benches --all-features --locked env: RUSTFLAGS: -D warnings @@ -38,6 +39,7 @@ jobs: - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@nightly with: + toolchain: nightly-2026-01-05 components: rustfmt - name: Run fmt run: cargo fmt --all --check @@ -59,6 +61,8 @@ jobs: - uses: actions/checkout@v6 - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2026-01-05 - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true @@ -88,6 +92,8 @@ jobs: - uses: actions/checkout@v6 - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2026-01-05 - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 800b624b..a1df785b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,7 @@ jobs: - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@nightly with: - toolchain: 'nightly' + toolchain: nightly-2026-01-05 - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true @@ -43,7 +43,7 @@ jobs: - uses: rui314/setup-mold@v1 - uses: dtolnay/rust-toolchain@nightly with: - toolchain: 'nightly' + toolchain: nightly-2026-01-05 - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true diff --git a/crates/chain-orchestrator/src/lib.rs b/crates/chain-orchestrator/src/lib.rs index 64d5d657..fb3383f6 100644 --- a/crates/chain-orchestrator/src/lib.rs +++ b/crates/chain-orchestrator/src/lib.rs @@ -292,13 +292,17 @@ impl< } } SequencerEvent::PayloadReady(payload_id) => { - if let Some(block) = self + let block = self .sequencer .as_mut() .expect("sequencer must be present") .finalize_payload_building(payload_id, &mut self.engine) - .await? - { + .await?; + + self.metric_handler.finish_all_block_building_recording(); + self.metric_handler.finish_block_building_interval_recording(); + + if let Some(block) = block { let block_info: L2BlockInfoWithL1Messages = (&block).into(); self.database .update_l1_messages_from_l2_blocks(vec![block_info.clone()]) @@ -307,7 +311,7 @@ impl< .as_mut() .expect("signer must be present") .sign_block(block.clone())?; - self.metric_handler.finish_block_building_recording(); + self.metric_handler.finish_no_empty_block_building_recording(); return Ok(Some(ChainOrchestratorEvent::BlockSequenced(block))); } } diff --git a/crates/chain-orchestrator/src/metrics.rs b/crates/chain-orchestrator/src/metrics.rs index 8859712f..d041da21 100644 --- a/crates/chain-orchestrator/src/metrics.rs +++ b/crates/chain-orchestrator/src/metrics.rs @@ -20,19 +20,52 @@ impl MetricsHandler { /// Starts tracking a new block building task. pub(crate) fn start_block_building_recording(&mut self) { - if self.block_building_meter.start.is_some() { + if self.block_building_meter.block_building_start.is_some() { tracing::warn!(target: "scroll::chain_orchestrator", "block building recording is already ongoing, overwriting"); } - self.block_building_meter.start = Some(Instant::now()); + self.block_building_meter.block_building_start = Some(Instant::now()); } /// The duration of the current block building task if any. - pub(crate) fn finish_block_building_recording(&mut self) { - let duration = self.block_building_meter.start.take().map(|start| start.elapsed()); + pub(crate) fn finish_no_empty_block_building_recording(&mut self) { + let duration = self + .block_building_meter + .block_building_start + .take() + .map(|block_building_start| block_building_start.elapsed()); if let Some(duration) = duration { self.block_building_meter.metric.block_building_duration.record(duration.as_secs_f64()); } } + + pub(crate) fn finish_all_block_building_recording(&mut self) { + let duration = self + .block_building_meter + .block_building_start + .take() + .map(|block_building_start| block_building_start.elapsed()); + if let Some(duration) = duration { + self.block_building_meter + .metric + .all_block_building_duration + .record(duration.as_secs_f64()); + } + } + + pub(crate) fn finish_block_building_interval_recording(&mut self) { + let interval = self + .block_building_meter + .last_block_building_time + .take() + .map(|last_block_building_time| last_block_building_time.elapsed()); + if let Some(interval) = interval { + self.block_building_meter + .metric + .consecutive_block_interval + .record(interval.as_secs_f64()); + } + self.block_building_meter.last_block_building_time = Some(Instant::now()); + } } impl Default for MetricsHandler { @@ -104,13 +137,18 @@ pub(crate) struct ChainOrchestratorMetrics { #[derive(Debug, Default)] pub(crate) struct BlockBuildingMeter { metric: BlockBuildingMetric, - start: Option, + block_building_start: Option, + last_block_building_time: Option, } /// Block building related metric. #[derive(Metrics, Clone)] #[metrics(scope = "chain_orchestrator")] pub(crate) struct BlockBuildingMetric { - /// The duration of the block building task. + /// The duration of the block building task without empty block block_building_duration: Histogram, + /// The duration of the block building task for all blocks include empty block + all_block_building_duration: Histogram, + /// The duration of the block interval include empty block + consecutive_block_interval: Histogram, }