use std::collections::HashMap;
use substrate_prometheus_endpoint::{
exponential_buckets, prometheus::HistogramTimer, register, CounterVec, Histogram,
HistogramOpts, Opts, PrometheusError, Registry, U64,
};
use crate::Protocol;
fn protocol_name(protocol: Protocol) -> &'static str {
use Protocol::*;
match protocol {
Authentication => "authentication",
BlockSync => "block_sync",
}
}
#[derive(Clone)]
pub enum Metrics {
Prometheus {
send_times: HashMap<Protocol, Histogram>,
peer_sender_queue_size: CounterVec<U64>,
},
Noop,
}
impl Metrics {
pub fn new(registry: Option<Registry>) -> Result<Self, PrometheusError> {
use Protocol::*;
let registry = match registry {
Some(registry) => registry,
None => return Ok(Metrics::Noop),
};
let mut send_times = HashMap::new();
for protocol in [Authentication, BlockSync] {
send_times.insert(
protocol,
register(
Histogram::with_opts(HistogramOpts {
common_opts: Opts {
namespace: "gossip_network".to_string(),
subsystem: protocol_name(protocol).to_string(),
name: "send_duration".to_string(),
help: "How long did it take for substrate to send a message."
.to_string(),
const_labels: Default::default(),
variable_labels: Default::default(),
},
buckets: exponential_buckets(0.001, 1.26, 30)?,
})?,
®istry,
)?,
);
}
let peer_sender_queue_size = register(CounterVec::new(
Opts::new(
"gossip_network_peer_sender_queue",
"Total number of messages sent and received by peer sender queues for all peers, for a given protocol",
),
&["protocol", "action"],
)?, ®istry)?;
Ok(Metrics::Prometheus {
send_times,
peer_sender_queue_size,
})
}
pub fn noop() -> Self {
Metrics::Noop
}
pub fn start_sending_in(&self, protocol: Protocol) -> Option<HistogramTimer> {
match self {
Metrics::Prometheus { send_times, .. } => send_times
.get(&protocol)
.map(|histogram| histogram.start_timer()),
Metrics::Noop => None,
}
}
pub fn report_message_pushed_to_peer_sender_queue(&self, protocol: Protocol) {
match self {
Metrics::Prometheus {
peer_sender_queue_size,
..
} => {
peer_sender_queue_size
.with_label_values(&[protocol_name(protocol), "send"])
.inc();
}
Metrics::Noop => {}
}
}
pub fn report_message_popped_from_peer_sender_queue(&self, protocol: Protocol) {
match self {
Metrics::Prometheus {
peer_sender_queue_size,
..
} => {
peer_sender_queue_size
.with_label_values(&[protocol_name(protocol), "received"])
.inc();
}
Metrics::Noop => {}
}
}
}