From 95cfac8dd1c05f22b2da2f2ed593c5f09017a8c3 Mon Sep 17 00:00:00 2001 From: Itay Tsabary Date: Sun, 22 Dec 2024 20:39:18 +0200 Subject: [PATCH] chore(starknet_http_server): add metrics tests, still partial commit-id:ce82f0b7 --- Cargo.lock | 4 + crates/starknet_http_server/Cargo.toml | 6 ++ .../src/http_server_test.rs | 81 ++++++++++++++++++- crates/starknet_http_server/src/metrics.rs | 7 +- 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c37a684168..b43234533c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10481,15 +10481,19 @@ name = "starknet_http_server" version = "0.0.0" dependencies = [ "axum", + "blockifier", "hyper 0.14.30", "infra_utils", + "mempool_test_utils", "metrics 0.21.1", + "metrics-exporter-prometheus", "papyrus_config", "reqwest 0.11.27", "serde", "serde_json", "starknet_api", "starknet_gateway_types", + "starknet_http_server", "starknet_sequencer_infra", "thiserror", "tokio", diff --git a/crates/starknet_http_server/Cargo.toml b/crates/starknet_http_server/Cargo.toml index 0ea77da072..c6bfa7598f 100644 --- a/crates/starknet_http_server/Cargo.toml +++ b/crates/starknet_http_server/Cargo.toml @@ -27,5 +27,11 @@ tracing.workspace = true validator.workspace = true [dev-dependencies] +blockifier = { workspace = true, features = ["testing"] } +mempool_test_utils.workspace = true +metrics-exporter-prometheus.workspace = true serde_json.workspace = true +starknet_api = { workspace = true, features = ["testing"] } +starknet_gateway_types = { workspace = true, features = ["testing"] } +starknet_http_server = { workspace = true, features = ["testing"] } tokio = { workspace = true, features = ["rt"] } diff --git a/crates/starknet_http_server/src/http_server_test.rs b/crates/starknet_http_server/src/http_server_test.rs index 787bed37f1..1e8c24e89c 100644 --- a/crates/starknet_http_server/src/http_server_test.rs +++ b/crates/starknet_http_server/src/http_server_test.rs @@ -1,9 +1,26 @@ +use std::net::SocketAddr; +use std::sync::Arc; + use axum::body::{Bytes, HttpBody}; use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; +use blockifier::test_utils::CairoVersion; +use infra_utils::metrics::parse_numeric_metric; +use mempool_test_utils::starknet_api_test_utils::invoke_tx; +use metrics_exporter_prometheus::PrometheusBuilder; use starknet_api::transaction::TransactionHash; +use starknet_gateway_types::communication::{GatewayClientError, MockGatewayClient}; +use starknet_sequencer_infra::component_client::ClientError; +use tokio::task; -use crate::http_server::add_tx_result_as_json; +use crate::config::HttpServerConfig; +use crate::http_server::{add_tx_result_as_json, HttpServer}; +use crate::metrics::{ + ADDED_TRANSACTIONS_FAILURE, + ADDED_TRANSACTIONS_SUCCESS, + ADDED_TRANSACTIONS_TOTAL, +}; +use crate::test_utils::HttpTestClient; #[tokio::test] async fn test_tx_hash_json_conversion() { @@ -20,3 +37,65 @@ async fn test_tx_hash_json_conversion() { async fn to_bytes(res: Response) -> Bytes { res.into_body().collect().await.unwrap().to_bytes() } + +#[tokio::test] +async fn get_metrics_test() { + let prometheus_handle = PrometheusBuilder::new() + .install_recorder() + .expect("should be able to build the recorder and install it globally"); + + // TODO(Tsabary): there is a bug in the http server where a failed gateway request crashes it. + // The current setup does not test that. Fix the bug and update this test accordingly. + // Create a mock gateway client that returns arbitrary responses. + let txs_to_send = 3; + let success_txs_to_send = txs_to_send; + let failure_txs_to_send = txs_to_send - success_txs_to_send; + let mut mock_gateway_client = MockGatewayClient::new(); + let mut i = 0; + mock_gateway_client.expect_add_tx().times(txs_to_send).returning(move |_| { + // TODO(Tsabary): the following discombobulated mechanism is a placeholder for the future + // test, where there will be failed requests as well. + i += 1; + match i { + 0 => Err(GatewayClientError::ClientError(ClientError::UnexpectedResponse( + "mock response".to_string(), + ))), + 1 => Ok(TransactionHash::default()), + _ => Ok(TransactionHash::default()), + } + }); + + // TODO(Tsabary): replace the const port with something that is not hardcoded. + // Create and run the server. + let http_server_config = HttpServerConfig { ip: "127.0.0.1".parse().unwrap(), port: 15123 }; + let mut http_server = + HttpServer::new(http_server_config.clone(), Arc::new(mock_gateway_client)); + tokio::spawn(async move { http_server.run().await }); + + let HttpServerConfig { ip, port } = http_server_config; + let add_tx_http_client = HttpTestClient::new(SocketAddr::from((ip, port))); + + // Ensure the server starts running. + task::yield_now().await; + + // Send transactions to the server. + for _ in std::iter::repeat(()).take(txs_to_send) { + let rpc_tx = invoke_tx(CairoVersion::default()); + add_tx_http_client.add_tx(rpc_tx).await; + } + + // Obtain metrics. + let metrics = prometheus_handle.render(); + + let added_transactions_total_count = + parse_numeric_metric::(&metrics, ADDED_TRANSACTIONS_SUCCESS.0); + let added_transactions_success_count = + parse_numeric_metric::(&metrics, ADDED_TRANSACTIONS_TOTAL.0); + let added_transactions_failure_count = + parse_numeric_metric::(&metrics, ADDED_TRANSACTIONS_FAILURE.0); + + // Ensure the metrics are as expected. + assert_eq!(added_transactions_total_count.unwrap(), txs_to_send); + assert_eq!(added_transactions_success_count.unwrap(), success_txs_to_send); + assert_eq!(added_transactions_failure_count.unwrap(), failure_txs_to_send); +} diff --git a/crates/starknet_http_server/src/metrics.rs b/crates/starknet_http_server/src/metrics.rs index 0c2a7003a8..d6c2b15e18 100644 --- a/crates/starknet_http_server/src/metrics.rs +++ b/crates/starknet_http_server/src/metrics.rs @@ -1,10 +1,11 @@ use metrics::{absolute_counter, describe_counter, register_counter}; -const ADDED_TRANSACTIONS_TOTAL: (&str, &str, u64) = +// TODO(Tsabary): add tests for metrics. +pub(crate) const ADDED_TRANSACTIONS_TOTAL: (&str, &str, u64) = ("ADDED_TRANSACTIONS_TOTAL", "Total number of transactions added", 0); -const ADDED_TRANSACTIONS_SUCCESS: (&str, &str, u64) = +pub(crate) const ADDED_TRANSACTIONS_SUCCESS: (&str, &str, u64) = ("ADDED_TRANSACTIONS_SUCCESS", "Number of successfully added transactions", 0); -const ADDED_TRANSACTIONS_FAILURE: (&str, &str, u64) = +pub(crate) const ADDED_TRANSACTIONS_FAILURE: (&str, &str, u64) = ("ADDED_TRANSACTIONS_FAILURE", "Number of faulty added transactions", 0); pub(crate) fn init_metrics() {