Repository: paradigmxyz/reth (language: rust)

Issue:
Add metrics for `engine_getBlobsV1`
### Describe the feature

We have metrics for the other engine methods:
https://github.com/paradigmxyz/reth/blob/1804bbea6e53ec35606b8b6e87c4f0f624ee75fc/crates/rpc/rpc-engine-api/src/metrics.rs#L19-L53

But we do not have one for `engine_getBlobsV1`, this should be added to the metrics struct and implemented in the same way we do for the `newPayload` metrics for example:
https://github.com/paradigmxyz/reth/blob/1804bbea6e53ec35606b8b6e87c4f0f624ee75fc/crates/rpc/rpc-engine-api/src/engine_api.rs#L244-L251

### Additional context

_No response_


Discussion / hints:
@Rjected can I take this one ? 
@Haxry Sure! assigned
@Rjected correct me if I am wrong  
I have to implement a function `get_blobs_v1_metered`, right?  

For example:  

```rust
async fn get_blobs_v1_metered(
    &self,
    versioned_hashes: Vec<B256>,
) -> RpcResult<Vec<Option<BlobAndProofV1>>> {
    let start = Instant::now();
    
    let res = Self::get_blobs_v1(self, versioned_hashes).await;
    
    let elapsed = start.elapsed();
    self.inner.metrics.latency.get_blobs_v1.record(elapsed);
    
    if let Ok(blobs) = &res {
        self.inner.metrics.blob_count.record(blobs.len() as u64);
    }

    Ok(res?)
}

yep that looks about right,

ideally we also want to track misses like how many blobs we actually found (diff between versioned_hashes and result.filter(is_some).count)

Fix patch:
diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs
index 41141018d28b..8a860f80e068 100644
--- a/crates/rpc/rpc-engine-api/src/engine_api.rs
+++ b/crates/rpc/rpc-engine-api/src/engine_api.rs
@@ -1006,15 +1006,30 @@ where
         versioned_hashes: Vec<B256>,
     ) -> RpcResult<Vec<Option<BlobAndProofV1>>> {
         trace!(target: "rpc::engine", "Serving engine_getBlobsV1");
+        let start = Instant::now();
+
         if versioned_hashes.len() > MAX_BLOB_LIMIT {
             return Err(EngineApiError::BlobRequestTooLarge { len: versioned_hashes.len() }.into())
         }
 
-        Ok(self
+        let res = self
             .inner
             .tx_pool
             .get_blobs_for_versioned_hashes(&versioned_hashes)
-            .map_err(|err| EngineApiError::Internal(Box::new(err)))?)
+            .map_err(|err| EngineApiError::Internal(Box::new(err)).into());
+
+        let elapsed = start.elapsed();
+        self.inner.metrics.latency.get_blobs_v1.record(elapsed);
+
+        if let Ok(blobs) = &res {
+            let blobs_found = blobs.iter().flatten().count();
+            let blobs_missed = versioned_hashes.len() - blobs_found;
+
+            self.inner.metrics.blob_metrics.blob_count.increment(blobs_found as u64);
+            self.inner.metrics.blob_metrics.blob_misses.increment(blobs_missed as u64);
+        }
+
+        res
     }
 }
 
diff --git a/crates/rpc/rpc-engine-api/src/metrics.rs b/crates/rpc/rpc-engine-api/src/metrics.rs
index 6a7cf7ce3c84..86cfe4f921e7 100644
--- a/crates/rpc/rpc-engine-api/src/metrics.rs
+++ b/crates/rpc/rpc-engine-api/src/metrics.rs
@@ -14,6 +14,8 @@ pub(crate) struct EngineApiMetrics {
     pub(crate) fcu_response: ForkchoiceUpdatedResponseMetrics,
     /// Engine API newPayload response type metrics
     pub(crate) new_payload_response: NewPayloadStatusResponseMetrics,
+    /// Blob-related metrics
+    pub(crate) blob_metrics: BlobMetrics,
 }
 
 /// Beacon consensus engine latency metrics.
@@ -50,6 +52,8 @@ pub(crate) struct EngineApiLatencyMetrics {
     pub(crate) get_payload_bodies_by_hash_v1: Histogram,
     /// Latency for `engine_exchangeTransitionConfigurationV1`
     pub(crate) exchange_transition_configuration: Histogram,
+    /// Latency for `engine_getBlobsV1`
+    pub(crate) get_blobs_v1: Histogram,
 }
 
 /// Metrics for engine API forkchoiceUpdated responses.
@@ -104,6 +108,15 @@ pub(crate) struct NewPayloadStatusResponseMetrics {
     pub(crate) new_payload_last: Gauge,
 }
 
+#[derive(Metrics)]
+#[metrics(scope = "engine.rpc.blobs")]
+pub(crate) struct BlobMetrics {
+    /// Count of blobs successfully retrieved
+    pub(crate) blob_count: Counter,
+    /// Count of blob misses
+    pub(crate) blob_misses: Counter,
+}
+
 impl NewPayloadStatusResponseMetrics {
     /// Increment the newPayload counter based on the given rpc result
     pub(crate) fn update_response_metrics(


Test patch: