Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework resource metrics (#472 #472

Merged
merged 10 commits into from
Apr 24, 2023
22 changes: 12 additions & 10 deletions crates/relayer-handlers/src/routes/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ pub async fn handle_evm_metric_info(
let typed_chain_id = TypedChainId::Evm(chain_id);
let resource_id = ResourceId::new(target_system, typed_chain_id);
// fetch metric for given resource_id
let resource_metric = metrics
.resource_metric_map
.entry(resource_id)
.or_insert_with(|| Metrics::register_resource_id_counters(resource_id));
let account_balance = metrics
.account_balance_entry(typed_chain_id)
.get()
.to_string();
let resource_metric = metrics.resource_metric_entry(resource_id);

Json(ResourceMetricResponse {
total_gas_spent: resource_metric.total_gas_spent.get().to_string(),
total_fee_earned: resource_metric.total_fee_earned.get().to_string(),
account_balance: resource_metric.account_balance.get().to_string(),
account_balance,
})
}

Expand All @@ -77,14 +78,15 @@ pub async fn handle_substrate_metric_info(
let resource_id = ResourceId::new(target_system, typed_chain_id);

// fetch metric for given resource_id
let resource_metric = metrics
.resource_metric_map
.entry(resource_id)
.or_insert_with(|| Metrics::register_resource_id_counters(resource_id));
let account_balance = metrics
.account_balance_entry(typed_chain_id)
.get()
.to_string();
let resource_metric = metrics.resource_metric_entry(resource_id);

Json(ResourceMetricResponse {
total_gas_spent: resource_metric.total_gas_spent.get().to_string(),
total_fee_earned: resource_metric.total_fee_earned.get().to_string(),
account_balance: resource_metric.account_balance.get().to_string(),
account_balance,
})
}
180 changes: 118 additions & 62 deletions crates/relayer-utils/src/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
use std::collections::HashMap;

use prometheus::core::{AtomicF64, GenericCounter, GenericGauge};
use prometheus::labels;
use prometheus::opts;
use prometheus::{register_counter, register_gauge, Encoder, TextEncoder};
use webb_proposals::ResourceId;
use webb_proposals::{ResourceId, TargetSystem, TypedChainId};

/// A struct for collecting metrics for particular resource.
#[derive(Debug, Clone)]
Expand All @@ -25,8 +27,6 @@ pub struct ResourceMetric {
pub total_gas_spent: GenericCounter<AtomicF64>,
/// Total fees earned on Resource.
pub total_fee_earned: GenericCounter<AtomicF64>,
/// Account Balance
pub account_balance: GenericGauge<AtomicF64>,
}

/// A struct definition for collecting metrics in the relayer.
Expand Down Expand Up @@ -59,97 +59,94 @@ pub struct Metrics {
/// Total amount of data stored metric
pub total_amount_of_data_stored: GenericGauge<AtomicF64>,
/// Resource metric
pub resource_metric_map: HashMap<ResourceId, ResourceMetric>,
resource_metric_map: HashMap<ResourceId, ResourceMetric>,
/// Metric for account balance (in gwei) on specific chain
account_balance: HashMap<TypedChainId, GenericGauge<AtomicF64>>,
}

impl Metrics {
/// Instantiates the various metrics and their counters, also creates a registry for the counters and
/// registers the counters
pub fn new() -> Result<Self, prometheus::Error> {
let bridge_watcher_back_off_counter = register_counter!(
let bridge_watcher_back_off = register_counter!(
"bridge_watcher_back_off",
"specifies how many times the bridge watcher backed off"
)?;

let total_transaction_made_counter = register_counter!(
let total_transaction_made = register_counter!(
"total_transaction_made",
"The total number of transaction made",
)?;

let anchor_update_proposals_counter = register_counter!(
let anchor_update_proposals = register_counter!(
"anchor_update_proposals",
"The total number of anchor update proposal proposed by relayer",
)?;

let proposals_signed_counter = register_counter!(
let proposals_signed = register_counter!(
"proposals_signed",
"The total number of proposal signed by dkg/mocked backend",
)?;

let proposals_processed_tx_queue_counter = register_counter!(
let proposals_processed_tx_queue = register_counter!(
"proposals_processed_tx_queue",
"Total number of signed proposals processed by transaction queue",
)?;

let proposals_processed_substrate_tx_queue_counter = register_counter!(
let proposals_processed_substrate_tx_queue = register_counter!(
"proposals_processed_substrate_tx_queue",
"Total number of signed proposals processed by substrate transaction queue",
)?;

let proposals_processed_evm_tx_queue_counter = register_counter!(
let proposals_processed_evm_tx_queue = register_counter!(
"proposals_processed_evm_tx_queue",
"Total number of signed proposals processed by evm transaction queue",
)?;

let transaction_queue_back_off_counter = register_counter!(
let transaction_queue_back_off = register_counter!(
"transaction_queue_back_off",
"How many times the transaction queue backed off",
)?;

let substrate_transaction_queue_back_off_counter = register_counter!(
let substrate_transaction_queue_back_off = register_counter!(
"substrate_transaction_queue_back_off",
"How many times the substrate transaction queue backed off",
)?;

let evm_transaction_queue_back_off_counter = register_counter!(
let evm_transaction_queue_back_off = register_counter!(
"evm_transaction_queue_back_off",
"How many times the evm transaction queue backed off",
)?;

let total_fee_earned_counter = register_counter!(
let total_fee_earned = register_counter!(
"total_fee_earned",
"The total number of fees earned",
)?;

let gas_spent_counter =
let gas_spent =
register_counter!("gas_spent", "The total number of gas spent")?;

let total_amount_of_data_stored_counter = register_gauge!(
let total_amount_of_data_stored = register_gauge!(
"total_amount_of_data_stored",
"The Total number of data stored",
)?;

let resource_metric_map = HashMap::new();

Ok(Self {
bridge_watcher_back_off: bridge_watcher_back_off_counter,
total_transaction_made: total_transaction_made_counter,
anchor_update_proposals: anchor_update_proposals_counter,
proposals_signed: proposals_signed_counter,
proposals_processed_tx_queue: proposals_processed_tx_queue_counter,
proposals_processed_substrate_tx_queue:
proposals_processed_substrate_tx_queue_counter,
proposals_processed_evm_tx_queue:
proposals_processed_evm_tx_queue_counter,
transaction_queue_back_off: transaction_queue_back_off_counter,
substrate_transaction_queue_back_off:
substrate_transaction_queue_back_off_counter,
evm_transaction_queue_back_off:
evm_transaction_queue_back_off_counter,
total_fee_earned: total_fee_earned_counter,
gas_spent: gas_spent_counter,
total_amount_of_data_stored: total_amount_of_data_stored_counter,
resource_metric_map,
bridge_watcher_back_off,
total_transaction_made,
anchor_update_proposals,
proposals_signed,
proposals_processed_tx_queue,
proposals_processed_substrate_tx_queue,
proposals_processed_evm_tx_queue,
transaction_queue_back_off,
substrate_transaction_queue_back_off,
evm_transaction_queue_back_off,
total_fee_earned,
gas_spent,
total_amount_of_data_stored,
resource_metric_map: Default::default(),
account_balance: Default::default(),
})
}

Expand All @@ -165,38 +162,97 @@ impl Metrics {
Ok(String::from_utf8(buffer.clone())?)
}

// TODO: move this to webb-proposals
fn chain_name(chain: TypedChainId) -> &'static str {
match chain {
TypedChainId::None => "None",
TypedChainId::Evm(_) => "Evm",
TypedChainId::Substrate(_) => "Substrate",
TypedChainId::PolkadotParachain(_) => "PolkadotParachain",
TypedChainId::KusamaParachain(_) => "KusamaParachain",
TypedChainId::RococoParachain(_) => "RococoParachain",
TypedChainId::Cosmos(_) => "Cosmos",
TypedChainId::Solana(_) => "Solana",
TypedChainId::Ink(_) => "Ink",
}
}

pub fn resource_metric_entry(
&mut self,
resource_id: ResourceId,
) -> &mut ResourceMetric {
self.resource_metric_map
.entry(resource_id)
.or_insert_with(|| {
Metrics::register_resource_id_counters(resource_id)
})
}

pub fn account_balance_entry(
&mut self,
chain: TypedChainId,
) -> &mut GenericGauge<AtomicF64> {
self.account_balance.entry(chain).or_insert_with(|| {
let chain_id = chain.underlying_chain_id().to_string();
register_gauge!(opts!(
"chain_account_balance",
"Total account balance on chain",
labels!(
"chain_type" => Self::chain_name(chain),
"chain_id" => &chain_id,
)
))
.expect("create gauge for account balance")
})
}

/// Registers new counters to track metric for individual resources.
pub fn register_resource_id_counters(
fn register_resource_id_counters(
resource_id: ResourceId,
) -> ResourceMetric {
let resource_hex = hex::encode(resource_id.to_bytes().as_ref());
// Total gas fee spent on particular resource.
let total_gas_spent_counter = register_counter!(
format!("resource_{resource_hex}_total_gas_spent"),
format!(
"The total number of gas (in gwei) spent on resource : {resource_hex}"
)
let chain_id = resource_id
.typed_chain_id()
.underlying_chain_id()
.to_string();
let (target_system_type, target_system_value) =
match resource_id.target_system() {
TargetSystem::ContractAddress(address) => {
("contract", hex::encode(address))
}
TargetSystem::Substrate(system) => (
"tree_id",
format!(
"{}, pallet_index: {}",
system.tree_id, system.pallet_index
),
),
};
let labels = labels!(
"chain_type" => Self::chain_name(resource_id.typed_chain_id()),
"chain_id" => &chain_id,
"target_system_type" => target_system_type,
"target_system_value" => &target_system_value
);

// Total gas fee spent on particular resource.
let total_gas_spent = register_counter!(opts!(
"resource_total_gas_spent",
"Total number of gas spent on resource",
labels
))
.expect("create counter for gas spent");

// Total fee earned on particular resource.
let total_fee_earned_counter = register_counter!(
format!("resource_{resource_hex}_total_fees_earned"),
format!(
"The total number of fees earned on resource : {resource_hex}"
)
);
// Account Balance
let account_balance_counter = register_gauge!(
format!("resource_{resource_hex}_account_balance"),
format!("Total account balance : {resource_hex}")
);
let total_fee_earned = register_counter!(opts!(
"resource_total_fees_earned",
"Total number of fees earned on resource",
labels
))
.expect("create counter for fees earned");

ResourceMetric {
total_gas_spent: total_gas_spent_counter
.expect("create counter for gas spent"),
total_fee_earned: total_fee_earned_counter
.expect("create counter for fees earned"),
account_balance: account_balance_counter
.expect("create gauge for account balance"),
total_gas_spent,
total_fee_earned,
}
}
}
Expand Down
24 changes: 13 additions & 11 deletions crates/tx-relay/src/evm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ethereum_types::U256;
use std::{sync::Arc, time::Duration};

use tokio::sync::Mutex;
Expand All @@ -10,7 +11,7 @@ use webb_proposals::ResourceId;
use webb_relayer_handler_utils::{
into_withdraw_error, CommandResponse, CommandStream, WithdrawStatus,
};
use webb_relayer_utils::metric::{self, Metrics};
use webb_relayer_utils::metric::{self};

pub mod fees;
/// Variable Anchor transaction relayer.
Expand Down Expand Up @@ -96,7 +97,6 @@ where
finalized = true,
tx_hash = %receipt.transaction_hash,
);
// send the finalized status to the client.
let _ = stream
.send(Withdraw(WithdrawStatus::Finalized {
tx_hash: receipt.transaction_hash,
Expand All @@ -105,17 +105,19 @@ where
// gas spent by relayer on particular resource.
let gas_used = receipt.gas_used.unwrap_or_default();
let mut metrics = metrics.lock().await;
let resource_metric = metrics
.resource_metric_map
.entry(resource_id)
.or_insert_with(|| Metrics::register_resource_id_counters(resource_id));
// convert gas used to gwei.
let gas_used = ethers::utils::format_units(gas_used, "gwei")
metrics
.resource_metric_entry(resource_id)
.total_gas_spent
.inc_by(wei_to_gwei(gas_used));
Ok(())
}

fn wei_to_gwei(wei: U256) -> f64 {
ethers::utils::format_units(wei, "gwei")
.and_then(|gas| {
gas.parse::<f64>()
// TODO: this error is pointless as it is silently dropped
.map_err(|_| ethers::utils::ConversionError::ParseOverflow)
})
.unwrap_or_default();
resource_metric.total_gas_spent.inc_by(gas_used);
Ok(())
.unwrap_or_default()
}
Loading