@@ -16,6 +16,7 @@ use linera_base::{
1616 data_types:: { ApplicationDescription , Blob , BlockHeight , Epoch , TimeDelta , Timestamp } ,
1717 hashed:: Hashed ,
1818 identifiers:: { ApplicationId , BlobId , ChainId } ,
19+ time:: Instant ,
1920} ;
2021use linera_chain:: {
2122 data_types:: { BlockProposal , MessageBundle , ProposedBlock } ,
@@ -39,6 +40,22 @@ use crate::{
3940 worker:: { NetworkActions , WorkerError } ,
4041} ;
4142
43+ #[ cfg( with_metrics) ]
44+ mod metrics {
45+ use std:: sync:: LazyLock ;
46+
47+ use linera_base:: prometheus_util:: { exponential_bucket_latencies, register_histogram} ;
48+ use prometheus:: Histogram ;
49+
50+ pub static CHAIN_WORKER_REQUEST_QUEUE_WAIT_TIME : LazyLock < Histogram > = LazyLock :: new ( || {
51+ register_histogram (
52+ "chain_worker_request_queue_wait_time" ,
53+ "Time (ms) a chain worker request waits in queue before being processed" ,
54+ exponential_bucket_latencies ( 10_000.0 ) ,
55+ )
56+ } ) ;
57+ }
58+
4259/// A request for the [`ChainWorkerActor`].
4360#[ derive( Debug ) ]
4461pub ( crate ) enum ChainWorkerRequest < Context >
@@ -261,6 +278,7 @@ where
261278 incoming_requests : mpsc:: UnboundedReceiver < (
262279 ChainWorkerRequest < StorageClient :: Context > ,
263280 tracing:: Span ,
281+ Instant ,
264282 ) > ,
265283 is_tracked : bool ,
266284 ) {
@@ -302,11 +320,19 @@ where
302320 mut incoming_requests : mpsc:: UnboundedReceiver < (
303321 ChainWorkerRequest < StorageClient :: Context > ,
304322 tracing:: Span ,
323+ Instant ,
305324 ) > ,
306325 ) -> Result < ( ) , WorkerError > {
307326 trace ! ( "Starting `ChainWorkerActor`" ) ;
308327
309- while let Some ( ( request, span) ) = incoming_requests. recv ( ) . await {
328+ while let Some ( ( request, span, _queued_at) ) = incoming_requests. recv ( ) . await {
329+ // Record how long the request waited in queue (in milliseconds)
330+ #[ cfg( with_metrics) ]
331+ {
332+ let queue_wait_time_ms = _queued_at. elapsed ( ) . as_secs_f64 ( ) * 1000.0 ;
333+ metrics:: CHAIN_WORKER_REQUEST_QUEUE_WAIT_TIME . observe ( queue_wait_time_ms) ;
334+ }
335+
310336 let ( _service_runtime_thread, service_runtime_task, service_runtime_endpoint) =
311337 if self . config . long_lived_services {
312338 let actor = ServiceRuntimeActor :: spawn ( self . chain_id ) . await ;
@@ -337,9 +363,17 @@ where
337363 futures:: select! {
338364 ( ) = self . sleep_until_timeout( ) . fuse( ) => break ,
339365 maybe_request = incoming_requests. recv( ) . fuse( ) => {
340- let Some ( ( request, span) ) = maybe_request else {
366+ let Some ( ( request, span, _queued_at ) ) = maybe_request else {
341367 break ; // Request sender was dropped.
342368 } ;
369+
370+ // Record how long the request waited in queue (in milliseconds)
371+ #[ cfg( with_metrics) ]
372+ {
373+ let queue_wait_time_ms = _queued_at. elapsed( ) . as_secs_f64( ) * 1000.0 ;
374+ metrics:: CHAIN_WORKER_REQUEST_QUEUE_WAIT_TIME . observe( queue_wait_time_ms) ;
375+ }
376+
343377 Box :: pin( worker. handle_request( request) ) . instrument( span) . await ;
344378 }
345379 }
0 commit comments