From 093621ffa796860c3f8bb366f6007e54736aed4e Mon Sep 17 00:00:00 2001 From: Derek Cofausper <256792747+decofe@users.noreply.github.com> Date: Thu, 12 Mar 2026 02:17:38 -0700 Subject: [PATCH] feat(payload): add resolve and job-creation latency histograms (#22978) Co-authored-by: Georgios Konstantopoulos <17802178+gakonst@users.noreply.github.com> Co-authored-by: YK <46377366+yongkangc@users.noreply.github.com> --- .changelog/fair-wolves-smile.md | 5 +++++ crates/payload/builder/src/metrics.rs | 6 +++++- crates/payload/builder/src/service.rs | 8 +++++++- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 .changelog/fair-wolves-smile.md diff --git a/.changelog/fair-wolves-smile.md b/.changelog/fair-wolves-smile.md new file mode 100644 index 0000000000..5202857e79 --- /dev/null +++ b/.changelog/fair-wolves-smile.md @@ -0,0 +1,5 @@ +--- +reth-payload-builder: minor +--- + +Added observability metrics for payload resolve latency and new payload job creation latency to the payload builder service. diff --git a/crates/payload/builder/src/metrics.rs b/crates/payload/builder/src/metrics.rs index 57e751c1fd..c6779914c6 100644 --- a/crates/payload/builder/src/metrics.rs +++ b/crates/payload/builder/src/metrics.rs @@ -1,7 +1,7 @@ //! Payload builder service metrics. use reth_metrics::{ - metrics::{Counter, Gauge}, + metrics::{Counter, Gauge, Histogram}, Metrics, }; @@ -23,6 +23,10 @@ pub(crate) struct PayloadBuilderServiceMetrics { pub(crate) resolved_revenue: Gauge, /// Current block returned as the resolved payload pub(crate) resolved_block: Gauge, + /// Histogram of payload resolve latency in seconds + pub(crate) resolve_duration_seconds: Histogram, + /// Histogram of new payload job creation latency in seconds + pub(crate) new_job_duration_seconds: Histogram, } impl PayloadBuilderServiceMetrics { diff --git a/crates/payload/builder/src/service.rs b/crates/payload/builder/src/service.rs index 40dee95e0e..33700c7c4c 100644 --- a/crates/payload/builder/src/service.rs +++ b/crates/payload/builder/src/service.rs @@ -14,7 +14,7 @@ use futures_util::{future::FutureExt, Stream, StreamExt}; use reth_chain_state::CanonStateNotification; use reth_payload_builder_primitives::{Events, PayloadBuilderError, PayloadEvents}; use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes, PayloadKind, PayloadTypes}; -use reth_primitives_traits::NodePrimitives; +use reth_primitives_traits::{FastInstant as Instant, NodePrimitives}; use std::{ fmt, future::Future, @@ -301,11 +301,13 @@ where id: PayloadId, kind: PayloadKind, ) -> Option> { + let start = Instant::now(); debug!(target: "payload_builder", %id, "resolving payload job"); if let Some((cached, _, payload)) = &*self.cached_payload_rx.borrow() && *cached == id { + self.metrics.resolve_duration_seconds.record(start.elapsed()); return Some(Box::pin(core::future::ready(Ok(payload.clone())))); } @@ -326,6 +328,7 @@ where let fut = async move { let res = fut.await; + resolved_metrics.resolve_duration_seconds.record(start.elapsed()); if let Ok(payload) = &res { if payload_events.receiver_count() > 0 { payload_events.send(Events::BuiltPayload(payload.clone().into())).ok(); @@ -427,6 +430,7 @@ where debug!(target: "payload_builder",%id, parent = %attr.parent(), "Payload job already in progress, ignoring."); } else { let parent = attr.parent(); + let start = Instant::now(); let job_result = { let _entered = job_span.enter(); this.generator.new_payload_job(attr.clone()) @@ -434,6 +438,7 @@ where match job_result { Ok(job) => { + this.metrics.new_job_duration_seconds.record(start.elapsed()); info!(target: "payload_builder", %id, %parent, "New payload job created"); this.metrics.inc_initiated_jobs(); new_job = true; @@ -454,6 +459,7 @@ where } } Err(err) => { + this.metrics.new_job_duration_seconds.record(start.elapsed()); this.metrics.inc_failed_jobs(); warn!(target: "payload_builder", %err, %id, "Failed to create payload builder job"); res = Err(err);