diff --git a/crates/supervisor/core/src/chain_processor/chain.rs b/crates/supervisor/core/src/chain_processor/chain.rs index 480a29d835..624f10437f 100644 --- a/crates/supervisor/core/src/chain_processor/chain.rs +++ b/crates/supervisor/core/src/chain_processor/chain.rs @@ -19,8 +19,12 @@ pub struct ChainProcessor
{
// The chainId that this processor is associated with
chain_id: ChainId,
+ // The sender for chain events, used to communicate with the event loop
event_tx: Option ,
@@ -47,10 +51,10 @@ where
cancel_token: CancellationToken,
) -> Self {
// todo: validate chain_id against managed_node
-
Self {
chain_id,
event_tx: None,
+ metrics_enabled: None,
managed_node,
state_manager,
cancel_token,
@@ -58,6 +62,13 @@ where
}
}
+ /// Enables metrics on the database environment.
+ pub fn with_metrics(mut self) -> Self {
+ self.metrics_enabled = Some(true);
+ super::Metrics::init(self.chain_id);
+ self
+ }
+
/// Returns the [`ChainId`] associated with this processor.
pub const fn chain_id(&self) -> ChainId {
self.chain_id
@@ -81,13 +92,17 @@ where
self.event_tx = Some(event_tx.clone());
self.managed_node.start_subscription(event_tx.clone()).await?;
- let task = ChainProcessorTask::new(
+ let mut task = ChainProcessorTask::new(
self.chain_id,
self.managed_node.clone(),
self.state_manager.clone(),
self.cancel_token.clone(),
event_rx,
);
+ if self.metrics_enabled.unwrap_or(false) {
+ task = task.with_metrics();
+ }
+
let handle = tokio::spawn(async move {
task.run().await;
});
diff --git a/crates/supervisor/core/src/chain_processor/error.rs b/crates/supervisor/core/src/chain_processor/error.rs
index 403560250d..e5d4714af4 100644
--- a/crates/supervisor/core/src/chain_processor/error.rs
+++ b/crates/supervisor/core/src/chain_processor/error.rs
@@ -1,4 +1,5 @@
-use crate::syncnode::ManagedNodeError;
+use crate::{logindexer::LogIndexerError, syncnode::ManagedNodeError};
+use kona_supervisor_storage::StorageError;
use thiserror::Error;
/// Errors that may occur while processing chains in the supervisor core.
@@ -7,4 +8,12 @@ pub enum ChainProcessorError {
/// Represents an error that occurred while interacting with the managed node.
#[error(transparent)]
ManagedNode(#[from] ManagedNodeError),
+
+ /// Represents an error that occured while interacting with the storage layer.
+ #[error(transparent)]
+ StorageError(#[from] StorageError),
+
+ /// Represents an error that occured while indexing logs.
+ #[error(transparent)]
+ LogIndexerError(#[from] LogIndexerError),
}
diff --git a/crates/supervisor/core/src/chain_processor/metrics.rs b/crates/supervisor/core/src/chain_processor/metrics.rs
new file mode 100644
index 0000000000..6116ba0b9e
--- /dev/null
+++ b/crates/supervisor/core/src/chain_processor/metrics.rs
@@ -0,0 +1,75 @@
+use alloy_primitives::ChainId;
+
+#[derive(Debug)]
+pub(crate) struct Metrics;
+
+impl Metrics {
+ // --- Metric Names ---
+ /// Identifier for block processing success.
+ /// Labels: `chain_id`, `type`
+ pub(crate) const BLOCK_PROCESSING_SUCCESS_TOTAL: &'static str =
+ "supervisor_block_processing_success_total";
+
+ /// Identifier for block processing errors.
+ /// Labels: `chain_id`, `type`
+ pub(crate) const BLOCK_PROCESSING_ERROR_TOTAL: &'static str =
+ "supervisor_block_processing_error_total";
+
+ /// Identifier for block processing latency.
+ /// Labels: `chain_id`, `type`
+ pub(crate) const BLOCK_PROCESSING_LATENCY_SECONDS: &'static str =
+ "supervisor_block_processing_latency_seconds";
+
+ const TYPES: [&'static str; 5] =
+ ["local_unsafe", "cross_unsafe", "local_safe", "cross_safe", "finalized"];
+
+ pub(crate) fn init(chain_id: ChainId) {
+ Self::describe();
+ Self::zero(chain_id);
+ }
+
+ fn describe() {
+ metrics::describe_counter!(
+ Self::BLOCK_PROCESSING_SUCCESS_TOTAL,
+ metrics::Unit::Count,
+ "Total number of successfully processed blocks in the supervisor",
+ );
+
+ metrics::describe_counter!(
+ Self::BLOCK_PROCESSING_ERROR_TOTAL,
+ metrics::Unit::Count,
+ "Total number of errors encountered while processing blocks in the supervisor",
+ );
+
+ metrics::describe_histogram!(
+ Self::BLOCK_PROCESSING_LATENCY_SECONDS,
+ metrics::Unit::Seconds,
+ "Latency for processing in the supervisor",
+ );
+ }
+
+ fn zero(chain_id: ChainId) {
+ for &type_name in Self::TYPES.iter() {
+ metrics::counter!(
+ Self::BLOCK_PROCESSING_SUCCESS_TOTAL,
+ "type" => type_name,
+ "chain_id" => chain_id.to_string()
+ )
+ .increment(0);
+
+ metrics::counter!(
+ Self::BLOCK_PROCESSING_ERROR_TOTAL,
+ "type" => type_name,
+ "chain_id" => chain_id.to_string()
+ )
+ .increment(0);
+
+ metrics::histogram!(
+ Self::BLOCK_PROCESSING_LATENCY_SECONDS,
+ "type" => type_name,
+ "chain_id" => chain_id.to_string()
+ )
+ .record(0.0);
+ }
+ }
+}
diff --git a/crates/supervisor/core/src/chain_processor/mod.rs b/crates/supervisor/core/src/chain_processor/mod.rs
index d7cee8a67c..a9c7bedbfe 100644
--- a/crates/supervisor/core/src/chain_processor/mod.rs
+++ b/crates/supervisor/core/src/chain_processor/mod.rs
@@ -10,3 +10,6 @@ pub use error::ChainProcessorError;
mod task;
pub use task::ChainProcessorTask;
+
+mod metrics;
+pub(crate) use metrics::Metrics;
diff --git a/crates/supervisor/core/src/chain_processor/task.rs b/crates/supervisor/core/src/chain_processor/task.rs
index 53ae75d787..ae9dfff590 100644
--- a/crates/supervisor/core/src/chain_processor/task.rs
+++ b/crates/supervisor/core/src/chain_processor/task.rs
@@ -1,4 +1,5 @@
-use crate::{LogIndexer, event::ChainEvent, syncnode::ManagedNodeProvider};
+use super::Metrics;
+use crate::{ChainProcessorError, LogIndexer, event::ChainEvent, syncnode::ManagedNodeProvider};
use alloy_primitives::ChainId;
use kona_interop::{BlockReplacement, DerivedRefPair};
use kona_protocol::BlockInfo;
@@ -13,6 +14,7 @@ use tracing::{debug, error, info};
#[derive(Debug)]
pub struct ChainProcessorTask {
chain_id: ChainId,
+ metrics_enabled: Option ,
@@ -42,6 +44,7 @@ where
let log_indexer = LogIndexer::new(managed_node.clone(), state_manager.clone());
Self {
chain_id,
+ metrics_enabled: None,
cancel_token,
managed_node,
event_rx,
@@ -50,6 +53,73 @@ where
}
}
+ /// Enables metrics on the database environment.
+ pub const fn with_metrics(mut self) -> Self {
+ self.metrics_enabled = Some(true);
+ self
+ }
+
+ /// Observes an async call, recording metrics and latency for block processing.
+ /// The latecy is calculated as the difference between the current system time and the block's
+ /// timestamp.
+ async fn observe_block_processing