Skip to content

Commit aa1e977

Browse files
authored
feat: add derivation pipeline queue size metrics (#263)
* add derivation pipeline queue size metrics * lints * update docker tag for the rollup-node
1 parent fd0336c commit aa1e977

File tree

5 files changed

+131
-1
lines changed

5 files changed

+131
-1
lines changed

crates/derivation-pipeline/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ async-trait = { workspace = true, optional = true }
3030
futures.workspace = true
3131
metrics.workspace = true
3232
metrics-derive.workspace = true
33+
tokio.workspace = true
3334
thiserror.workspace = true
3435
tracing.workspace = true
3536

crates/derivation-pipeline/src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use rollup_node_providers::{BlockDataProvider, L1Provider};
3030
use scroll_alloy_rpc_types_engine::{BlockDataHint, ScrollPayloadAttributes};
3131
use scroll_codec::Codec;
3232
use scroll_db::{Database, DatabaseOperations};
33+
use tokio::time::Interval;
3334

3435
/// A future that resolves to a stream of [`ScrollPayloadAttributesWithBatchInfo`].
3536
type DerivationPipelineFuture = Pin<
@@ -43,6 +44,9 @@ type DerivationPipelineFuture = Pin<
4344
>,
4445
>;
4546

47+
/// The interval (in ms) at which the derivation pipeline should report queue size metrics.
48+
const QUEUE_METRICS_INTERVAL: u64 = 1000;
49+
4650
/// A structure holding the current unresolved futures for the derivation pipeline.
4751
pub struct DerivationPipeline<P> {
4852
/// The current derivation pipeline futures polled.
@@ -59,6 +63,8 @@ pub struct DerivationPipeline<P> {
5963
waker: Option<Waker>,
6064
/// The metrics of the pipeline.
6165
metrics: DerivationPipelineMetrics,
66+
/// The interval at which the derivation pipeline should report queue size metrics.
67+
queue_metrics_interval: Interval,
6268
}
6369

6470
impl<P: Debug> Debug for DerivationPipeline<P> {
@@ -92,6 +98,7 @@ where
9298
attributes_queue: Default::default(),
9399
waker: None,
94100
metrics: DerivationPipelineMetrics::default(),
101+
queue_metrics_interval: delayed_interval(QUEUE_METRICS_INTERVAL),
95102
}
96103
}
97104

@@ -160,6 +167,12 @@ where
160167
self.batch_queue.clear();
161168
self.pipeline_future = None;
162169
}
170+
171+
/// Emits the queue size metrics for the batch and payload attributes queues.
172+
fn emit_queue_gauges(&self) {
173+
self.metrics.batch_queue_size.set(self.batch_queue.len() as f64);
174+
self.metrics.payload_attributes_queue_size.set(self.attributes_queue.len() as f64);
175+
}
163176
}
164177

165178
impl<P> Stream for DerivationPipeline<P>
@@ -171,6 +184,11 @@ where
171184
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
172185
let this = self.get_mut();
173186

187+
// report queue size metrics if the interval has elapsed.
188+
while this.queue_metrics_interval.poll_tick(cx).is_ready() {
189+
this.emit_queue_gauges();
190+
}
191+
174192
// return attributes from the queue if any.
175193
if let Some(attribute) = this.attributes_queue.pop_front() {
176194
return Poll::Ready(Some(attribute.inner))
@@ -295,6 +313,14 @@ pub async fn derive<L1P: L1Provider + Sync + Send, L2P: BlockDataProvider + Sync
295313
Ok(attributes)
296314
}
297315

316+
/// Creates a delayed interval that will not skip ticks if the interval is missed but will delay
317+
/// the next tick until the interval has passed.
318+
fn delayed_interval(interval: u64) -> Interval {
319+
let mut interval = tokio::time::interval(tokio::time::Duration::from_millis(interval));
320+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
321+
interval
322+
}
323+
298324
#[cfg(test)]
299325
mod tests {
300326
use super::*;
@@ -388,6 +414,7 @@ mod tests {
388414
.into(),
389415
waker: None,
390416
metrics: Default::default(),
417+
queue_metrics_interval: delayed_interval(QUEUE_METRICS_INTERVAL),
391418
};
392419

393420
// flush and verify all relevant fields are emptied.
@@ -810,6 +837,7 @@ mod tests {
810837
attributes_queue: attributes,
811838
waker: None,
812839
metrics: Default::default(),
840+
queue_metrics_interval: delayed_interval(QUEUE_METRICS_INTERVAL),
813841
}
814842
}
815843

crates/derivation-pipeline/src/metrics.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ pub struct DerivationPipelineMetrics {
99
pub derived_blocks: Counter,
1010
/// The blocks per second derived by the pipeline.
1111
pub blocks_per_second: Gauge,
12+
/// The number of batches in the queue.
13+
pub batch_queue_size: Gauge,
14+
/// The number of payload attributes in the queue.
15+
pub payload_attributes_queue_size: Gauge,
1216
}

docker-compose/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ services:
1919
- scroll-network
2020

2121
rollup-node:
22-
image: scrolltech/rollup-node:v0.0.1-rc20
22+
image: scrolltech/rollup-node:v0.0.1-rc29
2323
container_name: rollup-node
2424
entrypoint: ["bash", "/launch_rollup_node.bash"]
2525
env_file:

docker-compose/resource/dashboards/rollup_node.json

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,103 @@
619619
"title": "Derived L2 payload attributes",
620620
"type": "timeseries"
621621
},
622+
{
623+
"datasource": {
624+
"type": "prometheus",
625+
"uid": "PBFA97CFB590B2093"
626+
},
627+
"description": "Live sizes of the derivation pipeline queues.",
628+
"fieldConfig": {
629+
"defaults": {
630+
"color": {
631+
"mode": "palette-classic"
632+
},
633+
"custom": {
634+
"axisBorderShow": false,
635+
"axisCenteredZero": false,
636+
"axisColorMode": "text",
637+
"axisPlacement": "auto",
638+
"barAlignment": 0,
639+
"drawStyle": "line",
640+
"fillOpacity": 10,
641+
"gradientMode": "none",
642+
"hideFrom": {
643+
"legend": false,
644+
"tooltip": false,
645+
"viz": false
646+
},
647+
"lineInterpolation": "linear",
648+
"lineWidth": 2,
649+
"pointSize": 3,
650+
"scaleDistribution": {
651+
"type": "linear"
652+
},
653+
"showPoints": "auto",
654+
"spanNulls": true,
655+
"stacking": {
656+
"group": "A",
657+
"mode": "none"
658+
},
659+
"thresholdsStyle": {
660+
"mode": "off"
661+
}
662+
},
663+
"mappings": [],
664+
"thresholds": {
665+
"mode": "absolute",
666+
"steps": [
667+
{
668+
"color": "green"
669+
},
670+
{
671+
"color": "red",
672+
"value": 40000
673+
}
674+
]
675+
},
676+
"unit": "items"
677+
},
678+
"overrides": []
679+
},
680+
"gridPos": {
681+
"h": 8,
682+
"w": 12,
683+
"x": 12,
684+
"y": 17
685+
},
686+
"id": 14,
687+
"options": {
688+
"legend": {
689+
"displayMode": "list",
690+
"placement": "bottom",
691+
"showLegend": true
692+
},
693+
"tooltip": {
694+
"hideZeros": false,
695+
"mode": "single",
696+
"sort": "none"
697+
}
698+
},
699+
"pluginVersion": "12.0.1",
700+
"targets": [
701+
{
702+
"editorMode": "code",
703+
"expr": "reth_derivation_pipeline_batch_queue_size",
704+
"legendFormat": "batch_queue_size",
705+
"range": true,
706+
"refId": "A"
707+
},
708+
{
709+
"editorMode": "code",
710+
"expr": "reth_derivation_pipeline_payload_attributes_queue_size",
711+
"legendFormat": "attributes_queue_size",
712+
"range": true,
713+
"refId": "B"
714+
}
715+
],
716+
"title": "Derivation queue sizes",
717+
"type": "timeseries"
718+
},
622719
{
623720
"collapsed": false,
624721
"gridPos": {

0 commit comments

Comments
 (0)