use crate::{
message_lane::MessageLane,
message_lane_loop::{SourceClientState, TargetClientState},
};
use bp_messages::{HashedLaneId, LegacyLaneId, MessageNonce};
use finality_relay::SyncLoopMetrics;
use relay_utils::metrics::{
metric_name, register, GaugeVec, Metric, Opts, PrometheusError, Registry, U64,
};
#[derive(Clone)]
pub struct MessageLaneLoopMetrics {
source_to_target_finality_metrics: SyncLoopMetrics,
target_to_source_finality_metrics: SyncLoopMetrics,
lane_state_nonces: GaugeVec<U64>,
}
impl MessageLaneLoopMetrics {
pub fn new(prefix: Option<&str>) -> Result<Self, PrometheusError> {
Ok(MessageLaneLoopMetrics {
source_to_target_finality_metrics: SyncLoopMetrics::new(
prefix,
"source",
"source_at_target",
)?,
target_to_source_finality_metrics: SyncLoopMetrics::new(
prefix,
"target",
"target_at_source",
)?,
lane_state_nonces: GaugeVec::new(
Opts::new(metric_name(prefix, "lane_state_nonces"), "Nonces of the lane state"),
&["type"],
)?,
})
}
pub fn update_source_state<P: MessageLane>(&self, source_client_state: SourceClientState<P>) {
self.source_to_target_finality_metrics
.update_best_block_at_source(source_client_state.best_self.0);
if let Some(best_finalized_peer_at_best_self) =
source_client_state.best_finalized_peer_at_best_self
{
self.target_to_source_finality_metrics
.update_best_block_at_target(best_finalized_peer_at_best_self.0);
if let Some(actual_best_finalized_peer_at_best_self) =
source_client_state.actual_best_finalized_peer_at_best_self
{
self.target_to_source_finality_metrics.update_using_same_fork(
best_finalized_peer_at_best_self.1 == actual_best_finalized_peer_at_best_self.1,
);
}
}
}
pub fn update_target_state<P: MessageLane>(&self, target_client_state: TargetClientState<P>) {
self.target_to_source_finality_metrics
.update_best_block_at_source(target_client_state.best_self.0);
if let Some(best_finalized_peer_at_best_self) =
target_client_state.best_finalized_peer_at_best_self
{
self.source_to_target_finality_metrics
.update_best_block_at_target(best_finalized_peer_at_best_self.0);
if let Some(actual_best_finalized_peer_at_best_self) =
target_client_state.actual_best_finalized_peer_at_best_self
{
self.source_to_target_finality_metrics.update_using_same_fork(
best_finalized_peer_at_best_self.1 == actual_best_finalized_peer_at_best_self.1,
);
}
}
}
pub fn update_source_latest_generated_nonce(
&self,
source_latest_generated_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["source_latest_generated"])
.set(source_latest_generated_nonce);
}
pub fn update_source_latest_confirmed_nonce(
&self,
source_latest_confirmed_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["source_latest_confirmed"])
.set(source_latest_confirmed_nonce);
}
pub fn update_target_latest_received_nonce(&self, target_latest_generated_nonce: MessageNonce) {
self.lane_state_nonces
.with_label_values(&["target_latest_received"])
.set(target_latest_generated_nonce);
}
pub fn update_target_latest_confirmed_nonce(
&self,
target_latest_confirmed_nonce: MessageNonce,
) {
self.lane_state_nonces
.with_label_values(&["target_latest_confirmed"])
.set(target_latest_confirmed_nonce);
}
}
impl Metric for MessageLaneLoopMetrics {
fn register(&self, registry: &Registry) -> Result<(), PrometheusError> {
self.source_to_target_finality_metrics.register(registry)?;
self.target_to_source_finality_metrics.register(registry)?;
register(self.lane_state_nonces.clone(), registry)?;
Ok(())
}
}
pub trait Labeled {
fn label(&self) -> String;
}
impl Labeled for LegacyLaneId {
fn label(&self) -> String {
hex::encode(self.0)
}
}
impl Labeled for HashedLaneId {
fn label(&self) -> String {
format!("{:?}", self.inner())
}
}
#[test]
fn lane_to_label_works() {
assert_eq!(
"0x0101010101010101010101010101010101010101010101010101010101010101",
HashedLaneId::from_inner(sp_core::H256::from([1u8; 32])).label(),
);
assert_eq!("00000001", LegacyLaneId([0, 0, 0, 1]).label());
}