diff --git a/Cargo.lock b/Cargo.lock index c92a029..3fc72ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2595,6 +2595,28 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "metrics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae428771d17306715c5091d446327d1cfdedc82185c65ba8423ab404e45bf10" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3dbdd96ed57d565ec744cba02862d707acf373c5772d152abae6ec5c4e24f6c" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.77", +] + [[package]] name = "mime" version = "0.3.17" @@ -3506,7 +3528,7 @@ dependencies = [ "alloy-rlp", "futures-core", "futures-util", - "metrics", + "metrics 0.23.0", "reth-chainspec", "reth-metrics", "reth-payload-builder", @@ -3543,7 +3565,7 @@ dependencies = [ "alloy-primitives", "auto_impl", "derive_more", - "metrics", + "metrics 0.23.0", "parking_lot", "pin-project", "reth-chainspec", @@ -3639,7 +3661,7 @@ dependencies = [ "bytes", "derive_more", "eyre", - "metrics", + "metrics 0.23.0", "page_size", "paste", "reth-db-api", @@ -3669,7 +3691,7 @@ dependencies = [ "alloy-primitives", "bytes", "derive_more", - "metrics", + "metrics 0.23.0", "modular-bitfield", "parity-scale-codec", "reth-codecs", @@ -3781,7 +3803,7 @@ dependencies = [ "alloy-eips", "auto_impl", "futures-util", - "metrics", + "metrics 0.23.0", "reth-chainspec", "reth-execution-errors", "reth-execution-types", @@ -3884,7 +3906,7 @@ name = "reth-metrics" version = "1.0.7" source = "git+https://github.com/paradigmxyz/reth.git?tag=v1.0.7#75b7172cf77eb4fd65fe1a6924f75066fb09fcd1" dependencies = [ - "metrics", + "metrics 0.23.0", "reth-metrics-derive", ] @@ -4042,7 +4064,7 @@ source = "git+https://github.com/paradigmxyz/reth.git?tag=v1.0.7#75b7172cf77eb4f dependencies = [ "alloy-primitives", "futures-util", - "metrics", + "metrics 0.23.0", "pin-project", "reth-errors", "reth-ethereum-engine-primitives", @@ -4137,7 +4159,7 @@ dependencies = [ "auto_impl", "dashmap", "itertools 0.13.0", - "metrics", + "metrics 0.23.0", "notify", "parking_lot", "rayon", @@ -4308,7 +4330,7 @@ dependencies = [ "auto_impl", "dyn-clone", "futures-util", - "metrics", + "metrics 0.23.0", "reth-metrics", "thiserror", "tokio", @@ -4343,7 +4365,7 @@ dependencies = [ "auto_impl", "bitflags 2.6.0", "futures-util", - "metrics", + "metrics 0.23.0", "parking_lot", "reth-chain-state", "reth-chainspec", @@ -4375,7 +4397,7 @@ dependencies = [ "auto_impl", "derive_more", "itertools 0.13.0", - "metrics", + "metrics 0.23.0", "rayon", "reth-execution-errors", "reth-metrics", @@ -4417,7 +4439,7 @@ dependencies = [ "auto_impl", "derive_more", "itertools 0.13.0", - "metrics", + "metrics 0.23.0", "rayon", "reth-db", "reth-db-api", @@ -4579,6 +4601,8 @@ dependencies = [ "hyper", "hyper-util", "jsonrpsee", + "metrics 0.24.0", + "metrics-derive", "op-alloy-rpc-types", "op-alloy-rpc-types-engine", "predicates", diff --git a/Cargo.toml b/Cargo.toml index 9ffbd2d..e7f768c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,8 @@ serde_json = "1.0.96" reth-rpc-layer = { git = "https://github.com/paradigmxyz/reth.git", tag = "v1.0.7" } reth-optimism-payload-builder = { git = "https://github.com/paradigmxyz/reth.git", tag = "v1.0.7", features = ["optimism"] } futures = "0.3.31" +metrics-derive = "0.1" +metrics = "0.24.0" [dev-dependencies] anyhow = "1.0" diff --git a/src/main.rs b/src/main.rs index 6861070..d97132a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use jsonrpsee::http_client::transport::HttpBackend; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; use jsonrpsee::server::Server; use jsonrpsee::RpcModule; +use metrics::ServerMetrics; use proxy::ProxyLayer; use reth_rpc_layer::{AuthClientLayer, AuthClientService}; use server::{EngineApiServer, EthEngineApi}; @@ -16,6 +17,7 @@ use tracing::{info, Level}; use tracing_subscriber::EnvFilter; mod error; +mod metrics; mod proxy; mod selector; mod server; @@ -82,6 +84,8 @@ async fn main() -> Result<()> { .with_env_filter(EnvFilter::new(args.log_level.to_string())) // Set the log level .init(); + let metrics = ServerMetrics::default(); + // Handle JWT secret let jwt_secret = match (args.jwt_path, args.jwt_token) { (Some(file), None) => { @@ -127,6 +131,7 @@ async fn main() -> Result<()> { .map(|c| Arc::new(c.clone())) .collect(), args.boost_sync, + metrics, ); let mut module: RpcModule<()> = RpcModule::new(()); module diff --git a/src/metrics.rs b/src/metrics.rs new file mode 100644 index 0000000..c648252 --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,18 @@ +use metrics::Counter; +use metrics_derive::Metrics; + +#[derive(Metrics)] +#[metrics(scope = "metrics_custom")] +pub struct ServerMetrics { + #[metric(describe = "Count of fork_choice_updated_v3 calls proxied to the builder")] + pub fcu_count: Counter, + + #[metric(describe = "Count of new_payload_v3 calls proxied to the builder")] + pub new_payload_count: Counter, + + #[metric(describe = "Count of get_payload_v3 calls proxied to the builder")] + pub get_payload_count: Counter, + + #[metric(describe = "Count of send_raw_transaction calls proxied to the builder")] + pub send_raw_tx_count: Counter, +} diff --git a/src/server.rs b/src/server.rs index 0a148c1..3a09804 100644 --- a/src/server.rs +++ b/src/server.rs @@ -18,6 +18,7 @@ use reth_rpc_layer::AuthClientService; use std::sync::Arc; use tracing::{debug, error, info}; +use crate::metrics::ServerMetrics; use crate::selector::{DefaultPayloadSelector, PayloadSelector}; #[rpc(server, client, namespace = "engine")] @@ -55,6 +56,7 @@ pub struct EthEngineApi> { builder_clients: Vec>>, payload_selector: Arc, boost_sync: bool, + metrics: ServerMetrics, } impl EthEngineApi { @@ -62,11 +64,13 @@ impl EthEngineApi { l2_client: Arc>, builder_clients: Vec>>, boost_sync: bool, + metrics: ServerMetrics, ) -> Self { Self { l2_client, builder_clients, boost_sync, + metrics, payload_selector: Arc::new(DefaultPayloadSelector), } } @@ -79,13 +83,16 @@ impl EthApiServer for EthEngineApi { message = "received send_raw_transaction", "bytes_len" = bytes.len() ); - let builder = self.builder_client.clone(); - let tx_bytes = bytes.clone(); - tokio::spawn(async move { - builder.send_raw_transaction(tx_bytes).await.map_err(|e| { + for builder in self.builder_clients.iter() { + self.metrics.send_raw_tx_count.increment(1); + let builder = builder.clone(); + let tx_bytes = bytes.clone(); + tokio::spawn(async move { + builder.send_raw_transaction(tx_bytes).await.map_err(|e| { error!(message = "error calling send_raw_transaction for builder", "error" = %e); - }) - }); + }) + }); + } self.l2_client .send_raw_transaction(bytes) .await @@ -129,6 +136,7 @@ impl EngineApiServer for EthEngineApi { if should_send_to_builder { // async call to each builder to trigger payload building and sync for builder in self.builder_clients.iter() { + self.metrics.fcu_count.increment(1); let builder = builder.clone(); let attr = payload_attributes.clone(); tokio::spawn(async move { @@ -173,6 +181,7 @@ impl EngineApiServer for EthEngineApi { let builder_client_futures = self.builder_clients.iter().map(|builder| { let builder = builder.clone(); Box::pin(async move { + self.metrics.get_payload_count.increment(1); let payload = builder.get_payload_v3(payload_id).await.map_err(|e| { error!(message = "error calling get_payload_v3 from builder", "error" = %e, "payload_id" = %payload_id); e @@ -231,6 +240,7 @@ impl EngineApiServer for EthEngineApi { // async call to builder to sync the builder node if self.boost_sync { for builder in self.builder_clients.iter() { + self.metrics.new_payload_count.increment(1); let builder = builder.clone(); let builder_payload = payload.clone(); let builder_versioned_hashes = versioned_hashes.clone();