use dashmap::DashMap; use serde::{Deserialize, Serialize}; use std::cell::UnsafeCell; use std::fmt; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::time::interval; use crate::common::scoped_task::ScopedTask; /// Predefined metric names for type safety #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum MetricName { /// RPC calls sent to peers PeerRpcClientTx, /// RPC calls received from peers PeerRpcClientRx, /// RPC calls sent to peers PeerRpcServerTx, /// RPC calls received from peers PeerRpcServerRx, /// RPC call duration in milliseconds PeerRpcDuration, /// RPC errors PeerRpcErrors, /// Traffic bytes sent TrafficBytesTx, /// Traffic bytes received TrafficBytesRx, /// Traffic bytes forwarded TrafficBytesForwarded, /// Traffic bytes sent to self TrafficBytesSelfTx, /// Traffic bytes received from self TrafficBytesSelfRx, /// Traffic bytes forwarded for foreign network, rx to local TrafficBytesForeignForwardRx, /// Traffic bytes forwarded for foreign network, tx from local TrafficBytesForeignForwardTx, /// Traffic bytes forwarded for foreign network, forward TrafficBytesForeignForwardForwarded, /// Traffic packets sent TrafficPacketsTx, /// Traffic packets received TrafficPacketsRx, /// Traffic packets forwarded TrafficPacketsForwarded, /// Traffic packets sent to self TrafficPacketsSelfTx, /// Traffic packets received from self TrafficPacketsSelfRx, /// Traffic packets forwarded for foreign network, rx to local TrafficPacketsForeignForwardRx, /// Traffic packets forwarded for foreign network, tx from local TrafficPacketsForeignForwardTx, /// Traffic packets forwarded for foreign network, forward TrafficPacketsForeignForwardForwarded, /// Compression bytes before compression CompressionBytesRxBefore, /// Compression bytes after compression CompressionBytesRxAfter, /// Compression bytes before compression CompressionBytesTxBefore, /// Compression bytes after compression CompressionBytesTxAfter, } impl fmt::Display for MetricName { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MetricName::PeerRpcClientTx => write!(f, "peer_rpc_client_tx"), MetricName::PeerRpcClientRx => write!(f, "peer_rpc_client_rx"), MetricName::PeerRpcServerTx => write!(f, "peer_rpc_server_tx"), MetricName::PeerRpcServerRx => write!(f, "peer_rpc_server_rx"), MetricName::PeerRpcDuration => write!(f, "peer_rpc_duration_ms"), MetricName::PeerRpcErrors => write!(f, "peer_rpc_errors"), MetricName::TrafficBytesTx => write!(f, "traffic_bytes_tx"), MetricName::TrafficBytesRx => write!(f, "traffic_bytes_rx"), MetricName::TrafficBytesForwarded => write!(f, "traffic_bytes_forwarded"), MetricName::TrafficBytesSelfTx => write!(f, "traffic_bytes_self_tx"), MetricName::TrafficBytesSelfRx => write!(f, "traffic_bytes_self_rx"), MetricName::TrafficBytesForeignForwardRx => { write!(f, "traffic_bytes_foreign_forward_rx") } MetricName::TrafficBytesForeignForwardTx => { write!(f, "traffic_bytes_foreign_forward_tx") } MetricName::TrafficBytesForeignForwardForwarded => { write!(f, "traffic_bytes_foreign_forward_forwarded") } MetricName::TrafficPacketsTx => write!(f, "traffic_packets_tx"), MetricName::TrafficPacketsRx => write!(f, "traffic_packets_rx"), MetricName::TrafficPacketsForwarded => write!(f, "traffic_packets_forwarded"), MetricName::TrafficPacketsSelfTx => write!(f, "traffic_packets_self_tx"), MetricName::TrafficPacketsSelfRx => write!(f, "traffic_packets_self_rx"), MetricName::TrafficPacketsForeignForwardRx => { write!(f, "traffic_packets_foreign_forward_rx") } MetricName::TrafficPacketsForeignForwardTx => { write!(f, "traffic_packets_foreign_forward_tx") } MetricName::TrafficPacketsForeignForwardForwarded => { write!(f, "traffic_packets_foreign_forward_forwarded") } MetricName::CompressionBytesRxBefore => write!(f, "compression_bytes_rx_before"), MetricName::CompressionBytesRxAfter => write!(f, "compression_bytes_rx_after"), MetricName::CompressionBytesTxBefore => write!(f, "compression_bytes_tx_before"), MetricName::CompressionBytesTxAfter => write!(f, "compression_bytes_tx_after"), } } } /// Predefined label types for type safety #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum LabelType { /// Network Name NetworkName(String), /// Source peer ID SrcPeerId(u32), /// Destination peer ID DstPeerId(u32), /// Service name ServiceName(String), /// Method name MethodName(String), /// Protocol type Protocol(String), /// Direction (tx/rx) Direction(String), /// Compression algorithm CompressionAlgo(String), /// Error type ErrorType(String), /// Status Status(String), } impl fmt::Display for LabelType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { LabelType::NetworkName(name) => write!(f, "network_name={}", name), LabelType::SrcPeerId(id) => write!(f, "src_peer_id={}", id), LabelType::DstPeerId(id) => write!(f, "dst_peer_id={}", id), LabelType::ServiceName(name) => write!(f, "service_name={}", name), LabelType::MethodName(name) => write!(f, "method_name={}", name), LabelType::Protocol(proto) => write!(f, "protocol={}", proto), LabelType::Direction(dir) => write!(f, "direction={}", dir), LabelType::CompressionAlgo(algo) => write!(f, "compression_algo={}", algo), LabelType::ErrorType(err) => write!(f, "error_type={}", err), LabelType::Status(status) => write!(f, "status={}", status), } } } impl LabelType { pub fn key(&self) -> &'static str { match self { LabelType::NetworkName(_) => "network_name", LabelType::SrcPeerId(_) => "src_peer_id", LabelType::DstPeerId(_) => "dst_peer_id", LabelType::ServiceName(_) => "service_name", LabelType::MethodName(_) => "method_name", LabelType::Protocol(_) => "protocol", LabelType::Direction(_) => "direction", LabelType::CompressionAlgo(_) => "compression_algo", LabelType::ErrorType(_) => "error_type", LabelType::Status(_) => "status", } } pub fn value(&self) -> String { match self { LabelType::NetworkName(name) => name.clone(), LabelType::SrcPeerId(id) => id.to_string(), LabelType::DstPeerId(id) => id.to_string(), LabelType::ServiceName(name) => name.clone(), LabelType::MethodName(name) => name.clone(), LabelType::Protocol(proto) => proto.clone(), LabelType::Direction(dir) => dir.clone(), LabelType::CompressionAlgo(algo) => algo.clone(), LabelType::ErrorType(err) => err.clone(), LabelType::Status(status) => status.clone(), } } } /// Label represents a key-value pair for metric identification #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Label { pub key: String, pub value: String, } impl Label { pub fn new(key: impl Into, value: impl Into) -> Self { Self { key: key.into(), value: value.into(), } } pub fn from_label_type(label_type: &LabelType) -> Self { Self { key: label_type.key().to_string(), value: label_type.value(), } } } /// LabelSet represents a collection of labels for a metric #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct LabelSet { labels: Vec