Skip to content

Commit

Permalink
feat: put metrics behind compilation feature-flag (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
dinhani-cw authored Apr 3, 2024
1 parent 1c3cdde commit 35979c3
Show file tree
Hide file tree
Showing 15 changed files with 227 additions and 74 deletions.
17 changes: 13 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ reqwest = { version = "=0.11.24", features = ["json"] }
tower = "=0.4.13"

# observability
metrics = "=0.21.1"
metrics-exporter-prometheus = "=0.12.2"
metrics = { version = "=0.21.1", optional = true }
metrics-exporter-prometheus = { version = "=0.12.2", optional = true }
tracing = "=0.1.40"
tracing-subscriber = { version = "=0.3.18", features = ["env-filter", "json"] }

Expand Down Expand Up @@ -132,6 +132,15 @@ semicolon_if_nothing_returned = "warn"

[features]
default = ["rocks"]
dev = [] # Application is running in develoment mode.
perf = [] # Application is running in performance test mode.

# Application is running in develoment mode.
dev = []

# Application is running in performance test mode.
perf = []

# Enable metrics dependencies and code for metrics collection.
metrics = ["dep:metrics", "dep:metrics-exporter-prometheus"]

# Enable RocksDB dependencies.
rocks = ["rocksdb", "bincode"]
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ test-unit name="":

# Test: Execute Rust integration tests
test-int name="":
cargo test --test '*' {{name}} -- --nocapture
cargo test --test '*' {{name}} --features metrics -- --nocapture

# ------------------------------------------------------------------------------
# E2E tasks
Expand Down
6 changes: 4 additions & 2 deletions src/bin/importer_offline.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::cmp::min;
use std::sync::Arc;
use std::time::Instant;

use anyhow::anyhow;
use futures::try_join;
Expand All @@ -16,6 +15,7 @@ use stratus::eth::storage::ExternalRpcStorage;
use stratus::eth::storage::StratusStorage;
use stratus::eth::EthExecutor;
use stratus::ext::not;
#[cfg(feature = "metrics")]
use stratus::infra::metrics;
use stratus::init_global_services;
use stratus::log_and_err;
Expand Down Expand Up @@ -123,7 +123,8 @@ async fn execute_block_importer(
tracing::info!(%block_start, %block_end, receipts = %receipts.len(), "importing blocks");
let block_last_index = blocks.len() - 1;
for (block_index, block) in blocks.into_iter().enumerate() {
let start = Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

match csv {
// when exporting to csv, only persist temporary changes because permanent will be bulk loaded at the end of the process
Expand Down Expand Up @@ -156,6 +157,7 @@ async fn execute_block_importer(
}
}

#[cfg(feature = "metrics")]
metrics::inc_import_offline(start.elapsed());
}
};
Expand Down
7 changes: 6 additions & 1 deletion src/bin/importer_online.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use stratus::eth::primitives::ExternalBlock;
use stratus::eth::primitives::ExternalReceipt;
use stratus::eth::primitives::ExternalReceipts;
use stratus::eth::primitives::Hash;
#[cfg(feature = "metrics")]
use stratus::infra::metrics;
use stratus::infra::BlockchainClient;
use stratus::init_global_services;
Expand All @@ -33,7 +34,9 @@ async fn run(config: ImporterOnlineConfig) -> anyhow::Result<()> {

// keep importing forever
loop {
let start = std::time::Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

number = number.next();

// fetch block and receipts
Expand All @@ -49,6 +52,8 @@ async fn run(config: ImporterOnlineConfig) -> anyhow::Result<()> {
// import block
let mut receipts: ExternalReceipts = receipts.into();
executor.import_external_to_perm(block, &mut receipts).await?;

#[cfg(feature = "metrics")]
metrics::inc_import_online(start.elapsed());
}
}
Expand Down
18 changes: 12 additions & 6 deletions src/eth/evm/revm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//! of the `Evm` trait, serving as a bridge between Ethereum's abstract operations and Stratus's storage mechanisms.
use std::sync::Arc;
use std::time::Instant;

use anyhow::anyhow;
use anyhow::Context;
Expand Down Expand Up @@ -47,6 +46,7 @@ use crate::eth::primitives::SlotIndex;
use crate::eth::storage::StratusStorage;
use crate::ext::not;
use crate::ext::OptionExt;
#[cfg(feature = "metrics")]
use crate::infra::metrics;

/// Implementation of EVM using [`revm`](https://crates.io/crates/revm).
Expand Down Expand Up @@ -82,7 +82,8 @@ impl Revm {

impl Evm for Revm {
fn execute(&mut self, input: EvmInput) -> anyhow::Result<EvmExecutionResult> {
let start = Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

// configure session
let evm = &mut self.evm;
Expand Down Expand Up @@ -114,9 +115,11 @@ impl Evm for Revm {
// parse result and track metrics
let session = evm.db_mut();
let session_input = std::mem::take(&mut session.input);
let session_point_in_time = std::mem::take(&mut session.input.point_in_time);

let session_storage_changes = std::mem::take(&mut session.storage_changes);
let session_metrics = std::mem::take(&mut session.metrics);
#[cfg(feature = "metrics")]
let session_point_in_time = std::mem::take(&mut session.input.point_in_time);

let execution = match evm_result {
Ok(result) => Ok(parse_revm_execution(result, session_input, session_storage_changes)),
Expand All @@ -126,9 +129,12 @@ impl Evm for Revm {
}
};

metrics::inc_evm_execution(start.elapsed(), &session_point_in_time, execution.is_ok());
metrics::inc_evm_execution_account_reads(session_metrics.account_reads);
metrics::inc_evm_execution_slot_reads(session_metrics.slot_reads);
#[cfg(feature = "metrics")]
{
metrics::inc_evm_execution(start.elapsed(), &session_point_in_time, execution.is_ok());
metrics::inc_evm_execution_account_reads(session_metrics.account_reads);
metrics::inc_evm_execution_slot_reads(session_metrics.slot_reads);
}

execution.map(|x| (x, session_metrics))
}
Expand Down
33 changes: 25 additions & 8 deletions src/eth/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use std::io::Write;
use std::sync::Arc;
use std::time::Instant;

use anyhow::anyhow;
use tokio::sync::broadcast;
Expand All @@ -31,6 +30,7 @@ use crate::eth::storage::InMemoryPermanentStorage;
use crate::eth::storage::StorageError;
use crate::eth::storage::StratusStorage;
use crate::eth::BlockMiner;
#[cfg(feature = "metrics")]
use crate::infra::metrics;

/// Number of events in the backlog.
Expand Down Expand Up @@ -90,7 +90,9 @@ impl EthExecutor {

/// Re-executes an external block locally and imports it to the temporary storage.
pub async fn import_external_to_temp(&self, block: ExternalBlock, receipts: &mut ExternalReceipts) -> anyhow::Result<Block> {
let start = Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

let mut block_metrics = ExecutionMetrics::default();
tracing::info!(number = %block.number(), "importing external block");

Expand All @@ -100,7 +102,8 @@ impl EthExecutor {
// re-execute transactions
let mut executions: Vec<ExternalTransactionExecution> = Vec::with_capacity(block.transactions.len());
for tx in block.transactions.clone() {
let tx_start = Instant::now();
#[cfg(feature = "metrics")]
let tx_start = metrics::now();

// re-execute transaction or create a fake execution the external transaction failed
let receipt = receipts.try_take(&tx.hash())?;
Expand Down Expand Up @@ -134,6 +137,7 @@ impl EthExecutor {
executions.push((tx, receipt, execution.clone()));

// track metrics
#[cfg(feature = "metrics")]
metrics::inc_executor_external_transaction(tx_start.elapsed());
block_metrics.account_reads += execution_metrics.account_reads;
block_metrics.slot_reads += execution_metrics.slot_reads;
Expand Down Expand Up @@ -161,16 +165,21 @@ impl EthExecutor {
};

// track metrics
metrics::inc_executor_external_block(start.elapsed());
metrics::inc_executor_external_block_account_reads(block_metrics.account_reads);
metrics::inc_executor_external_block_slot_reads(block_metrics.slot_reads);
#[cfg(feature = "metrics")]
{
metrics::inc_executor_external_block(start.elapsed());
metrics::inc_executor_external_block_account_reads(block_metrics.account_reads);
metrics::inc_executor_external_block_slot_reads(block_metrics.slot_reads);
}

Ok(block)
}

/// Executes a transaction persisting state changes.
pub async fn transact(&self, transaction: TransactionInput) -> anyhow::Result<Execution> {
let start = Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

tracing::info!(
hash = %transaction.hash,
nonce = %transaction.nonce,
Expand Down Expand Up @@ -205,6 +214,7 @@ impl EthExecutor {
continue;
}
Err(e) => {
#[cfg(feature = "metrics")]
metrics::inc_executor_transact(start.elapsed(), false);
return Err(e.into());
}
Expand All @@ -226,13 +236,17 @@ impl EthExecutor {
}
}

#[cfg(feature = "metrics")]
metrics::inc_executor_transact(start.elapsed(), true);

Ok(execution)
}

/// Executes a transaction without persisting state changes.
pub async fn call(&self, input: CallInput, point_in_time: StoragePointInTime) -> anyhow::Result<Execution> {
let start = Instant::now();
#[cfg(feature = "metrics")]
let start = metrics::now();

tracing::info!(
from = ?input.from,
to = ?input.to,
Expand All @@ -243,7 +257,10 @@ impl EthExecutor {

let evm_input = EvmInput::from_eth_call(input, point_in_time);
let result = self.execute_in_evm(evm_input).await;

#[cfg(feature = "metrics")]
metrics::inc_executor_call(start.elapsed(), result.is_ok());

result.map(|x| x.0)
}

Expand Down
2 changes: 2 additions & 0 deletions src/eth/primitives/storage_point_in_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! block number, facilitating temporal queries in Ethereum.
use crate::eth::primitives::BlockNumber;
#[cfg(feature = "metrics")]
use crate::infra::metrics::LabelValue;

/// EVM storage point-in-time indicator.
Expand All @@ -23,6 +24,7 @@ pub enum StoragePointInTime {
// -----------------------------------------------------------------------------
// Conversions: Other -> Self
// -----------------------------------------------------------------------------
#[cfg(feature = "metrics")]
impl From<&StoragePointInTime> for LabelValue {
fn from(value: &StoragePointInTime) -> Self {
match value {
Expand Down
3 changes: 3 additions & 0 deletions src/eth/rpc/rpc_middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::eth::primitives::SoliditySignature;
use crate::eth::primitives::TransactionInput;
use crate::eth::rpc::next_rpc_param;
use crate::eth::rpc::parse_rpc_rlp;
#[cfg(feature = "metrics")]
use crate::infra::metrics;

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -55,6 +56,7 @@ where
);

// metrify request
#[cfg(feature = "metrics")]
metrics::inc_rpc_requests_started(method, function);

RpcResponse {
Expand Down Expand Up @@ -129,6 +131,7 @@ impl<F: Future<Output = MethodResponse>> Future for RpcResponse<F> {
);

// metrify response
#[cfg(feature = "metrics")]
metrics::inc_rpc_requests_finished(elapsed, proj.method.clone(), *proj.function, response.success_or_error.is_success());
}

Expand Down
2 changes: 1 addition & 1 deletion src/eth/storage/hybrid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ mod hybrid_state;
mod query_executor;
mod rocks_db;

use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;

use anyhow::Context;
use async_trait::async_trait;
use futures::future::join_all;
use metrics::atomics::AtomicU64;
use num_traits::cast::ToPrimitive;
use sqlx::postgres::PgPoolOptions;
use sqlx::types::Json;
Expand Down
2 changes: 1 addition & 1 deletion src/eth/storage/inmemory/inmemory_permanent.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! In-memory storage implementations.
use std::collections::HashMap;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::sync::Arc;

use async_trait::async_trait;
use indexmap::IndexMap;
use metrics::atomics::AtomicU64;
use rand::rngs::StdRng;
use rand::seq::IteratorRandom;
use rand::SeedableRng;
Expand Down
Loading

0 comments on commit 35979c3

Please sign in to comment.