From ecd20d9d2457cd7a54d90ea000749b5ebff721c0 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 29 Jun 2021 14:24:54 +0300 Subject: [PATCH] Shared reference to conversion rate metric value (#1034) * shared conversion rate metric value * clippy --- bridges/relays/bin-ethereum/Cargo.toml | 1 + .../bin-ethereum/src/ethereum_exchange.rs | 4 +- .../bin-ethereum/src/ethereum_sync_loop.rs | 2 +- .../bin-ethereum/src/substrate_sync_loop.rs | 2 +- .../src/chains/millau_messages_to_rialto.rs | 59 +++++------- .../relays/bin-substrate/src/chains/mod.rs | 56 ++++++------ .../src/chains/rialto_messages_to_millau.rs | 59 +++++------- .../src/chains/rococo_messages_to_wococo.rs | 40 ++++---- .../src/chains/wococo_messages_to_rococo.rs | 40 ++++---- .../src/cli/relay_headers_and_messages.rs | 18 +++- .../relays/bin-substrate/src/messages_lane.rs | 91 ++++++++++++++++++- bridges/relays/exchange/Cargo.toml | 1 + bridges/relays/exchange/src/exchange_loop.rs | 2 +- bridges/relays/finality/Cargo.toml | 1 + bridges/relays/finality/src/finality_loop.rs | 2 +- bridges/relays/headers/Cargo.toml | 1 + bridges/relays/headers/src/sync_loop.rs | 2 +- bridges/relays/messages/Cargo.toml | 1 + .../relays/messages/src/message_lane_loop.rs | 2 +- bridges/relays/utils/Cargo.toml | 1 + bridges/relays/utils/src/metrics.rs | 4 + .../utils/src/metrics/float_json_value.rs | 15 ++- bridges/relays/utils/src/relay_loop.rs | 17 ++-- 23 files changed, 260 insertions(+), 161 deletions(-) diff --git a/bridges/relays/bin-ethereum/Cargo.toml b/bridges/relays/bin-ethereum/Cargo.toml index efd9c0194b..e4620efe32 100644 --- a/bridges/relays/bin-ethereum/Cargo.toml +++ b/bridges/relays/bin-ethereum/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" +anyhow = "1.0" async-std = "1.9.0" async-trait = "0.1.42" clap = { version = "2.33.3", features = ["yaml"] } diff --git a/bridges/relays/bin-ethereum/src/ethereum_exchange.rs b/bridges/relays/bin-ethereum/src/ethereum_exchange.rs index 3111aa2de4..73a107cb40 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_exchange.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_exchange.rs @@ -355,7 +355,7 @@ async fn run_single_transaction_relay(params: EthereumExchangeParams, eth_tx_has async fn run_auto_transactions_relay_loop( params: EthereumExchangeParams, eth_start_with_block_number: Option, -) -> Result<(), String> { +) -> anyhow::Result<()> { let EthereumExchangeParams { eth_params, sub_params, @@ -375,7 +375,7 @@ async fn run_auto_transactions_relay_loop( .best_ethereum_finalized_block() .await .map_err(|err| { - format!( + anyhow::format_err!( "Error retrieving best finalized Ethereum block from Substrate node: {:?}", err ) diff --git a/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs b/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs index 111abcd86e..c4a5f5102a 100644 --- a/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs +++ b/bridges/relays/bin-ethereum/src/ethereum_sync_loop.rs @@ -292,7 +292,7 @@ pub async fn run(params: EthereumSyncParams) -> Result<(), RpcError> { futures::future::pending(), ) .await - .map_err(RpcError::SyncLoop)?; + .map_err(|e| RpcError::SyncLoop(e.to_string()))?; Ok(()) } diff --git a/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs b/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs index 542fd41f72..7924661244 100644 --- a/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs +++ b/bridges/relays/bin-ethereum/src/substrate_sync_loop.rs @@ -194,7 +194,7 @@ pub async fn run(params: SubstrateSyncParams) -> Result<(), RpcError> { futures::future::pending(), ) .await - .map_err(RpcError::SyncLoop)?; + .map_err(|e| RpcError::SyncLoop(e.to_string()))?; Ok(()) } diff --git a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs index 9932d16a42..5231aaa9a2 100644 --- a/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs +++ b/bridges/relays/bin-substrate/src/chains/millau_messages_to_rialto.rs @@ -17,7 +17,8 @@ //! Millau-to-Rialto messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -30,10 +31,8 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - Chain, TransactionSignScheme, -}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -136,7 +135,7 @@ type RialtoTargetClient = /// Run Millau-to-Rialto messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_millau = (*params.source_sign.public().as_array_ref()).into(); @@ -172,6 +171,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -202,36 +202,25 @@ pub async fn run( MILLAU_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - MillauMessagesToRialto, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "millau_storage_proof_overhead".into(), - "Millau storage proof overhead".into(), - ) - })? - .standalone_metric(|registry, prefix| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - registry, - prefix, - source_client, - sp_core::storage::StorageKey( - millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec(), - ), - Some(millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE), - "millau_rialto_to_millau_conversion_rate".into(), - "Rialto to Millau tokens conversion rate (used by Rialto)".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Millau -> Rialto messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + Some(( + sp_core::storage::StorageKey(millau_runtime::rialto_messages::RialtoToMillauConversionRate::key().to_vec()), + millau_runtime::rialto_messages::INITIAL_RIALTO_TO_MILLAU_CONVERSION_RATE, + )), + ) +} diff --git a/bridges/relays/bin-substrate/src/chains/mod.rs b/bridges/relays/bin-substrate/src/chains/mod.rs index 09d3c3e9c0..7c624179b9 100644 --- a/bridges/relays/bin-substrate/src/chains/mod.rs +++ b/bridges/relays/bin-substrate/src/chains/mod.rs @@ -32,38 +32,38 @@ mod rococo; mod westend; mod wococo; -use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams}; +use relay_utils::metrics::{FloatJsonValueMetric, MetricsParams, PrometheusError, Registry}; pub(crate) fn add_polkadot_kusama_price_metrics( params: MetricsParams, ) -> anyhow::Result { - Ok( - relay_utils::relay_metrics(Some(finality_relay::metrics_prefix::()), params) - // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama - // relays, but we want to test metrics/dashboards in advance - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Polkadot&vs_currencies=btc".into(), - "$.polkadot.btc".into(), - "polkadot_to_base_conversion_rate".into(), - "Rate used to convert from DOT to some BASE tokens".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .standalone_metric(|registry, prefix| { - FloatJsonValueMetric::new( - registry, - prefix, - "https://api.coingecko.com/api/v3/simple/price?ids=Kusama&vs_currencies=btc".into(), - "$.kusama.btc".into(), - "kusama_to_base_conversion_rate".into(), - "Rate used to convert from KSM to some BASE tokens".into(), - ) - }) - .map_err(|e| anyhow::format_err!("{}", e))? - .into_params(), + // Polkadot/Kusama prices are added as metrics here, because atm we don't have Polkadot <-> Kusama + // relays, but we want to test metrics/dashboards in advance + Ok(relay_utils::relay_metrics(None, params) + .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "polkadot"))? + .standalone_metric(|registry, prefix| token_price_metric(registry, prefix, "kusama"))? + .into_params()) +} + +/// Creates standalone token price metric. +pub(crate) fn token_price_metric( + registry: &Registry, + prefix: Option<&str>, + token_id: &str, +) -> Result { + FloatJsonValueMetric::new( + registry, + prefix, + format!( + "https://api.coingecko.com/api/v3/simple/price?ids={}&vs_currencies=btc", + token_id + ), + format!("$.{}.btc", token_id), + format!("{}_to_base_conversion_rate", token_id.replace("-", "_")), + format!( + "Rate used to convert from {} to some BASE tokens", + token_id.to_uppercase() + ), ) } diff --git a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs index f472703993..e491a14caf 100644 --- a/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs +++ b/bridges/relays/bin-substrate/src/chains/rialto_messages_to_millau.rs @@ -17,7 +17,8 @@ //! Rialto-to-Millau messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -30,10 +31,8 @@ use frame_support::dispatch::GetDispatchInfo; use messages_relay::message_lane::MessageLane; use relay_millau_client::{HeaderId as MillauHeaderId, Millau, SigningParams as MillauSigningParams}; use relay_rialto_client::{HeaderId as RialtoHeaderId, Rialto, SigningParams as RialtoSigningParams}; -use relay_substrate_client::{ - metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, - Chain, TransactionSignScheme, -}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -136,7 +135,7 @@ type MillauTargetClient = /// Run Rialto-to-Millau messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rialto = (*params.source_sign.public().as_array_ref()).into(); @@ -171,6 +170,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -201,36 +201,25 @@ pub async fn run( RIALTO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - RialtoMessagesToMillau, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "rialto_storage_proof_overhead".into(), - "Rialto storage proof overhead".into(), - ) - })? - .standalone_metric(|registry, prefix| { - FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( - registry, - prefix, - source_client, - sp_core::storage::StorageKey( - rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec(), - ), - Some(rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE), - "rialto_millau_to_rialto_conversion_rate".into(), - "Millau to Rialto tokens conversion rate (used by Millau)".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Rialto -> Millau messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + Some(( + sp_core::storage::StorageKey(rialto_runtime::millau_messages::MillauToRialtoConversionRate::key().to_vec()), + rialto_runtime::millau_messages::INITIAL_MILLAU_TO_RIALTO_CONVERSION_RATE, + )), + ) +} diff --git a/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs b/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs index f8da60cf17..e30896dd5f 100644 --- a/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs +++ b/bridges/relays/bin-substrate/src/chains/rococo_messages_to_wococo.rs @@ -17,7 +17,8 @@ //! Rococo-to-Wococo messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -28,7 +29,8 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -142,7 +144,7 @@ type WococoTargetClient = SubstrateMessagesTarget< /// Run Rococo-to-Wococo messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_rococo = (*params.source_sign.public().as_array_ref()).into(); @@ -183,6 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -213,23 +216,22 @@ pub async fn run( ROCOCO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - RococoMessagesToWococo, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "rococo_storage_proof_overhead".into(), - "Rococo storage proof overhead".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Rococo -> Wococo messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + None, + ) +} diff --git a/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs b/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs index 2e65328831..3c280c3f5b 100644 --- a/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs +++ b/bridges/relays/bin-substrate/src/chains/wococo_messages_to_rococo.rs @@ -17,7 +17,8 @@ //! Wococo-to-Rococo messages sync entrypoint. use crate::messages_lane::{ - select_delivery_transaction_limits, MessagesRelayParams, SubstrateMessageLane, SubstrateMessageLaneToSubstrate, + select_delivery_transaction_limits, MessagesRelayParams, StandaloneMessagesMetrics, SubstrateMessageLane, + SubstrateMessageLaneToSubstrate, }; use crate::messages_source::SubstrateMessagesSource; use crate::messages_target::SubstrateMessagesTarget; @@ -28,7 +29,8 @@ use bridge_runtime_common::messages::target::FromBridgedChainMessagesProof; use codec::Encode; use messages_relay::message_lane::MessageLane; use relay_rococo_client::{HeaderId as RococoHeaderId, Rococo, SigningParams as RococoSigningParams}; -use relay_substrate_client::{metrics::StorageProofOverheadMetric, Chain, TransactionSignScheme}; +use relay_substrate_client::{Chain, Client, TransactionSignScheme}; +use relay_utils::metrics::MetricsParams; use relay_wococo_client::{HeaderId as WococoHeaderId, SigningParams as WococoSigningParams, Wococo}; use sp_core::{Bytes, Pair}; use std::{ops::RangeInclusive, time::Duration}; @@ -142,7 +144,7 @@ type RococoTargetClient = SubstrateMessagesTarget< /// Run Wococo-to-Rococo messages sync. pub async fn run( params: MessagesRelayParams, -) -> Result<(), String> { +) -> anyhow::Result<()> { let stall_timeout = Duration::from_secs(5 * 60); let relayer_id_at_wococo = (*params.source_sign.public().as_array_ref()).into(); @@ -183,6 +185,7 @@ pub async fn run( max_messages_weight_in_single_batch, ); + let (metrics_params, _) = add_standalone_metrics(params.metrics_params, source_client.clone())?; messages_relay::message_lane_loop::run( messages_relay::message_lane_loop::Params { lane: lane_id, @@ -213,23 +216,22 @@ pub async fn run( WOCOCO_CHAIN_ID, params.source_to_target_headers_relay, ), - relay_utils::relay_metrics( - Some(messages_relay::message_lane_loop::metrics_prefix::< - WococoMessagesToRococo, - >(&lane_id)), - params.metrics_params, - ) - .standalone_metric(|registry, prefix| { - StorageProofOverheadMetric::new( - registry, - prefix, - source_client.clone(), - "wococo_storage_proof_overhead".into(), - "Wococo storage proof overhead".into(), - ) - })? - .into_params(), + metrics_params, futures::future::pending(), ) .await } + +/// Add standalone metrics for the Wococo -> Rococo messages loop. +pub(crate) fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + crate::messages_lane::add_standalone_metrics::( + metrics_params, + source_client, + None, + None, + None, + ) +} diff --git a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs index e71ea6aeaa..31accb15a4 100644 --- a/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs +++ b/bridges/relays/bin-substrate/src/cli/relay_headers_and_messages.rs @@ -100,8 +100,12 @@ macro_rules! select_bridge { const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_millau::BlockNumber = bp_millau::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_rialto::BlockNumber = bp_rialto::SESSION_LENGTH; - use crate::chains::millau_messages_to_rialto::run as left_to_right_messages; - use crate::chains::rialto_messages_to_millau::run as right_to_left_messages; + use crate::chains::millau_messages_to_rialto::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + }; + use crate::chains::rialto_messages_to_millau::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + }; $generic } @@ -120,8 +124,12 @@ macro_rules! select_bridge { const MAX_MISSING_LEFT_HEADERS_AT_RIGHT: bp_rococo::BlockNumber = bp_rococo::SESSION_LENGTH; const MAX_MISSING_RIGHT_HEADERS_AT_LEFT: bp_wococo::BlockNumber = bp_wococo::SESSION_LENGTH; - use crate::chains::rococo_messages_to_wococo::run as left_to_right_messages; - use crate::chains::wococo_messages_to_rococo::run as right_to_left_messages; + use crate::chains::rococo_messages_to_wococo::{ + add_standalone_metrics as add_left_to_right_standalone_metrics, run as left_to_right_messages, + }; + use crate::chains::wococo_messages_to_rococo::{ + add_standalone_metrics as add_right_to_left_standalone_metrics, run as right_to_left_messages, + }; $generic } @@ -153,6 +161,8 @@ impl RelayHeadersAndMessages { let metrics_params: MetricsParams = params.shared.prometheus_params.into(); let metrics_params = relay_utils::relay_metrics(None, metrics_params).into_params(); + let (metrics_params, _) = add_left_to_right_standalone_metrics(metrics_params, left_client.clone())?; + let (metrics_params, _) = add_right_to_left_standalone_metrics(metrics_params, right_client.clone())?; let left_to_right_on_demand_headers = OnDemandHeadersRelay::new( left_client.clone(), diff --git a/bridges/relays/bin-substrate/src/messages_lane.rs b/bridges/relays/bin-substrate/src/messages_lane.rs index 7efea545f9..7954319a75 100644 --- a/bridges/relays/bin-substrate/src/messages_lane.rs +++ b/bridges/relays/bin-substrate/src/messages_lane.rs @@ -21,9 +21,16 @@ use crate::on_demand_headers::OnDemandHeadersRelay; use bp_messages::{LaneId, MessageNonce}; use frame_support::weights::Weight; use messages_relay::message_lane::{MessageLane, SourceHeaderIdOf, TargetHeaderIdOf}; -use relay_substrate_client::{BlockNumberOf, Chain, Client, HashOf}; -use relay_utils::{metrics::MetricsParams, BlockNumberBase}; -use sp_core::Bytes; +use relay_substrate_client::{ + metrics::{FloatStorageValueMetric, StorageProofOverheadMetric}, + BlockNumberOf, Chain, Client, HashOf, +}; +use relay_utils::{ + metrics::{F64SharedRef, MetricsParams}, + BlockNumberBase, +}; +use sp_core::{storage::StorageKey, Bytes}; +use sp_runtime::FixedU128; use std::ops::RangeInclusive; /// Substrate <-> Substrate messages relay parameters. @@ -185,6 +192,84 @@ pub fn select_delivery_transaction_limits chain token conversion rate. + pub target_to_base_conversion_rate: Option, + /// Shared reference to the actual source -> chain token conversion rate. + pub source_to_base_conversion_rate: Option, +} + +/// Add general standalone metrics for the message lane relay loop. +pub fn add_standalone_metrics( + metrics_params: MetricsParams, + source_client: Client, + source_chain_token_id: Option<&str>, + target_chain_token_id: Option<&str>, + target_to_source_conversion_rate_params: Option<(StorageKey, FixedU128)>, +) -> anyhow::Result<(MetricsParams, StandaloneMessagesMetrics)> { + let mut source_to_base_conversion_rate = None; + let mut target_to_base_conversion_rate = None; + let mut metrics_params = + relay_utils::relay_metrics(None, metrics_params).standalone_metric(|registry, prefix| { + StorageProofOverheadMetric::new( + registry, + prefix, + source_client.clone(), + format!("{}_storage_proof_overhead", P::SourceChain::NAME.to_lowercase()), + format!("{} storage proof overhead", P::SourceChain::NAME), + ) + })?; + if let Some((target_to_source_conversion_rate_storage_key, initial_target_to_source_conversion_rate)) = + target_to_source_conversion_rate_params + { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = FloatStorageValueMetric::<_, sp_runtime::FixedU128>::new( + registry, + prefix, + source_client, + target_to_source_conversion_rate_storage_key, + Some(initial_target_to_source_conversion_rate), + format!( + "{}_{}_to_{}_conversion_rate", + P::SourceChain::NAME, + P::TargetChain::NAME, + P::SourceChain::NAME + ), + format!( + "{} to {} tokens conversion rate (used by {})", + P::TargetChain::NAME, + P::SourceChain::NAME, + P::SourceChain::NAME + ), + )?; + Ok(metric) + })?; + } + if let Some(source_chain_token_id) = source_chain_token_id { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = crate::chains::token_price_metric(registry, prefix, source_chain_token_id)?; + source_to_base_conversion_rate = Some(metric.shared_value_ref()); + Ok(metric) + })?; + } + if let Some(target_chain_token_id) = target_chain_token_id { + metrics_params = metrics_params.standalone_metric(|registry, prefix| { + let metric = crate::chains::token_price_metric(registry, prefix, target_chain_token_id)?; + target_to_base_conversion_rate = Some(metric.shared_value_ref()); + Ok(metric) + })?; + } + Ok(( + metrics_params.into_params(), + StandaloneMessagesMetrics { + source_to_base_conversion_rate, + target_to_base_conversion_rate, + }, + )) +} + #[cfg(test)] mod tests { use super::*; diff --git a/bridges/relays/exchange/Cargo.toml b/bridges/relays/exchange/Cargo.toml index 62e7a029bb..b8bb8481f6 100644 --- a/bridges/relays/exchange/Cargo.toml +++ b/bridges/relays/exchange/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/bridges/relays/exchange/src/exchange_loop.rs b/bridges/relays/exchange/src/exchange_loop.rs index 8da4c3f456..0c13f1b5e5 100644 --- a/bridges/relays/exchange/src/exchange_loop.rs +++ b/bridges/relays/exchange/src/exchange_loop.rs @@ -90,7 +90,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) diff --git a/bridges/relays/finality/Cargo.toml b/bridges/relays/finality/Cargo.toml index 944da9837f..3ecda234db 100644 --- a/bridges/relays/finality/Cargo.toml +++ b/bridges/relays/finality/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" description = "Finality proofs relay" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/bridges/relays/finality/src/finality_loop.rs b/bridges/relays/finality/src/finality_loop.rs index 3ea729d123..462632fa3f 100644 --- a/bridges/relays/finality/src/finality_loop.rs +++ b/bridges/relays/finality/src/finality_loop.rs @@ -104,7 +104,7 @@ pub async fn run( sync_params: FinalitySyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/bridges/relays/headers/Cargo.toml b/bridges/relays/headers/Cargo.toml index 31d3166a99..8eda40e935 100644 --- a/bridges/relays/headers/Cargo.toml +++ b/bridges/relays/headers/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/bridges/relays/headers/src/sync_loop.rs b/bridges/relays/headers/src/sync_loop.rs index b204932056..5ccec4bbab 100644 --- a/bridges/relays/headers/src/sync_loop.rs +++ b/bridges/relays/headers/src/sync_loop.rs @@ -126,7 +126,7 @@ pub async fn run>( sync_params: HeadersSyncParams, metrics_params: MetricsParams, exit_signal: impl Future + 'static + Send, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .with_metrics(Some(metrics_prefix::

()), metrics_params) diff --git a/bridges/relays/messages/Cargo.toml b/bridges/relays/messages/Cargo.toml index ea5d46845c..8fc0e7c4f1 100644 --- a/bridges/relays/messages/Cargo.toml +++ b/bridges/relays/messages/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +anyhow = "1.0" async-std = { version = "1.6.5", features = ["attributes"] } async-trait = "0.1.40" futures = "0.3.5" diff --git a/bridges/relays/messages/src/message_lane_loop.rs b/bridges/relays/messages/src/message_lane_loop.rs index c87c024f39..7ad5952603 100644 --- a/bridges/relays/messages/src/message_lane_loop.rs +++ b/bridges/relays/messages/src/message_lane_loop.rs @@ -258,7 +258,7 @@ pub async fn run( target_client: impl TargetClient

, metrics_params: MetricsParams, exit_signal: impl Future + Send + 'static, -) -> Result<(), String> { +) -> anyhow::Result<()> { let exit_signal = exit_signal.shared(); relay_utils::relay_loop(source_client, target_client) .reconnect_delay(params.reconnect_delay) diff --git a/bridges/relays/utils/Cargo.toml b/bridges/relays/utils/Cargo.toml index ff80cab533..ea5f33b77e 100644 --- a/bridges/relays/utils/Cargo.toml +++ b/bridges/relays/utils/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] ansi_term = "0.12" +anyhow = "1.0" async-std = "1.6.5" async-trait = "0.1.40" backoff = "0.2" diff --git a/bridges/relays/utils/src/metrics.rs b/bridges/relays/utils/src/metrics.rs index c0eaeae337..4855dba8ea 100644 --- a/bridges/relays/utils/src/metrics.rs +++ b/bridges/relays/utils/src/metrics.rs @@ -21,12 +21,16 @@ pub use substrate_prometheus_endpoint::{ register, Counter, CounterVec, Gauge, GaugeVec, Opts, PrometheusError, Registry, F64, U64, }; +use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use std::{fmt::Debug, time::Duration}; mod float_json_value; mod global; +/// Shared reference to `f64` value that is updated by the metric. +pub type F64SharedRef = Arc>>; + /// Unparsed address that needs to be used to expose Prometheus metrics. #[derive(Debug, Clone)] pub struct MetricsAddress { diff --git a/bridges/relays/utils/src/metrics/float_json_value.rs b/bridges/relays/utils/src/metrics/float_json_value.rs index d61f9cac7c..2a18df2aac 100644 --- a/bridges/relays/utils/src/metrics/float_json_value.rs +++ b/bridges/relays/utils/src/metrics/float_json_value.rs @@ -14,8 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity Bridges Common. If not, see . -use crate::metrics::{metric_name, register, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use crate::metrics::{metric_name, register, F64SharedRef, Gauge, PrometheusError, Registry, StandaloneMetrics, F64}; +use async_std::sync::{Arc, RwLock}; use async_trait::async_trait; use std::time::Duration; @@ -28,6 +29,7 @@ pub struct FloatJsonValueMetric { url: String, json_path: String, metric: Gauge, + shared_value_ref: F64SharedRef, } impl FloatJsonValueMetric { @@ -40,13 +42,20 @@ impl FloatJsonValueMetric { name: String, help: String, ) -> Result { + let shared_value_ref = Arc::new(RwLock::new(None)); Ok(FloatJsonValueMetric { url, json_path, metric: register(Gauge::new(metric_name(prefix, &name), help)?, registry)?, + shared_value_ref, }) } + /// Get shared reference to metric value. + pub fn shared_value_ref(&self) -> F64SharedRef { + self.shared_value_ref.clone() + } + /// Read value from HTTP service. async fn read_value(&self) -> Result { use isahc::{AsyncReadResponseExt, HttpClient, Request}; @@ -79,7 +88,9 @@ impl StandaloneMetrics for FloatJsonValueMetric { } async fn update(&self) { - crate::metrics::set_gauge_value(&self.metric, self.read_value().await.map(Some)); + let value = self.read_value().await; + crate::metrics::set_gauge_value(&self.metric, value.clone().map(Some)); + *self.shared_value_ref.write().await = value.ok(); } } diff --git a/bridges/relays/utils/src/relay_loop.rs b/bridges/relays/utils/src/relay_loop.rs index 938136658b..ea9d627521 100644 --- a/bridges/relays/utils/src/relay_loop.rs +++ b/bridges/relays/utils/src/relay_loop.rs @@ -105,7 +105,7 @@ impl Loop { /// This function represents an outer loop, which in turn calls provided `run_loop` function to do /// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source, /// target or both) and calls `run_loop` again. - pub async fn run(mut self, loop_name: String, run_loop: R) -> Result<(), String> + pub async fn run(mut self, loop_name: String, run_loop: R) -> anyhow::Result<()> where R: 'static + Send + Fn(SC, TC, Option) -> F, F: 'static + Send + Future>, @@ -151,8 +151,8 @@ impl LoopMetrics { pub fn loop_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> Result, String> { - let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref()).map_err(|e| e.to_string())?; + ) -> anyhow::Result> { + let loop_metric = create_metric(&self.registry, self.metrics_prefix.as_deref())?; Ok(LoopMetrics { relay_loop: self.relay_loop, @@ -167,13 +167,13 @@ impl LoopMetrics { pub fn standalone_metric( self, create_metric: impl FnOnce(&Registry, Option<&str>) -> Result, - ) -> Result { + ) -> anyhow::Result { // since standalone metrics are updating themselves, we may just ignore the fact that the same // standalone metric is exposed by several loops && only spawn single metric match create_metric(&self.registry, self.metrics_prefix.as_deref()) { Ok(standalone_metrics) => standalone_metrics.spawn(), Err(PrometheusError::AlreadyReg) => (), - Err(e) => return Err(e.to_string()), + Err(e) => anyhow::bail!(e), } Ok(self) @@ -191,13 +191,14 @@ impl LoopMetrics { /// Expose metrics using address passed at creation. /// /// If passed `address` is `None`, metrics are not exposed. - pub async fn expose(self) -> Result, String> { + pub async fn expose(self) -> anyhow::Result> { if let Some(address) = self.address { let socket_addr = SocketAddr::new( address.host.parse().map_err(|err| { - format!( + anyhow::format_err!( "Invalid host {} is used to expose Prometheus metrics: {}", - address.host, err, + address.host, + err, ) })?, address.port,