use crate::LOG_TARGET;
use log::{debug, error};
use prometheus_endpoint::{register, Counter, Gauge, PrometheusError, Registry, U64};
pub(crate) trait PrometheusRegister<T: Sized = Self>: Sized {
const DESCRIPTION: &'static str;
fn register(registry: &Registry) -> Result<Self, PrometheusError>;
}
#[derive(Clone, Debug)]
pub struct VoterMetrics {
pub beefy_validator_set_id: Gauge<U64>,
pub beefy_votes_sent: Counter<U64>,
pub beefy_best_block: Gauge<U64>,
pub beefy_best_voted: Gauge<U64>,
pub beefy_should_vote_on: Gauge<U64>,
pub beefy_lagging_sessions: Counter<U64>,
pub beefy_no_authority_found_in_store: Counter<U64>,
pub beefy_good_votes_processed: Counter<U64>,
pub beefy_equivocation_votes: Counter<U64>,
pub beefy_invalid_votes: Counter<U64>,
pub beefy_stale_votes: Counter<U64>,
pub beefy_buffered_justifications: Gauge<U64>,
pub beefy_stale_justifications: Counter<U64>,
pub beefy_imported_justifications: Counter<U64>,
pub beefy_buffered_justifications_dropped: Counter<U64>,
}
impl PrometheusRegister for VoterMetrics {
const DESCRIPTION: &'static str = "voter";
fn register(registry: &Registry) -> Result<Self, PrometheusError> {
Ok(Self {
beefy_validator_set_id: register(
Gauge::new(
"substrate_beefy_validator_set_id",
"Current BEEFY active validator set id.",
)?,
registry,
)?,
beefy_votes_sent: register(
Counter::new("substrate_beefy_votes_sent", "Number of votes sent by this node")?,
registry,
)?,
beefy_best_block: register(
Gauge::new("substrate_beefy_best_block", "Best block finalized by BEEFY")?,
registry,
)?,
beefy_best_voted: register(
Gauge::new("substrate_beefy_best_voted", "Best block voted on by BEEFY")?,
registry,
)?,
beefy_should_vote_on: register(
Gauge::new("substrate_beefy_should_vote_on", "Next block, BEEFY should vote on")?,
registry,
)?,
beefy_lagging_sessions: register(
Counter::new(
"substrate_beefy_lagging_sessions",
"Number of sessions with lagging signed commitment on mandatory block",
)?,
registry,
)?,
beefy_no_authority_found_in_store: register(
Counter::new(
"substrate_beefy_no_authority_found_in_store",
"Number of times no Authority public key found in store",
)?,
registry,
)?,
beefy_good_votes_processed: register(
Counter::new(
"substrate_beefy_successful_handled_votes",
"Number of good votes successfully handled",
)?,
registry,
)?,
beefy_equivocation_votes: register(
Counter::new(
"substrate_beefy_equivocation_votes",
"Number of equivocation votes received",
)?,
registry,
)?,
beefy_invalid_votes: register(
Counter::new("substrate_beefy_invalid_votes", "Number of invalid votes received")?,
registry,
)?,
beefy_stale_votes: register(
Counter::new(
"substrate_beefy_stale_votes",
"Number of valid but stale votes received",
)?,
registry,
)?,
beefy_buffered_justifications: register(
Gauge::new(
"substrate_beefy_buffered_justifications",
"Number of currently buffered justifications",
)?,
registry,
)?,
beefy_stale_justifications: register(
Counter::new(
"substrate_beefy_stale_justifications",
"Number of valid but stale justifications received",
)?,
registry,
)?,
beefy_imported_justifications: register(
Counter::new(
"substrate_beefy_imported_justifications",
"Number of valid justifications successfully imported",
)?,
registry,
)?,
beefy_buffered_justifications_dropped: register(
Counter::new(
"substrate_beefy_buffered_justifications_dropped",
"Number of justifications dropped due to full buffers",
)?,
registry,
)?,
})
}
}
#[derive(Clone, Debug)]
pub struct BlockImportMetrics {
pub beefy_good_justification_imports: Counter<U64>,
pub beefy_bad_justification_imports: Counter<U64>,
}
impl PrometheusRegister for BlockImportMetrics {
const DESCRIPTION: &'static str = "block-import";
fn register(registry: &Registry) -> Result<Self, PrometheusError> {
Ok(Self {
beefy_good_justification_imports: register(
Counter::new(
"substrate_beefy_good_justification_imports",
"Number of good justifications on block-import",
)?,
registry,
)?,
beefy_bad_justification_imports: register(
Counter::new(
"substrate_beefy_bad_justification_imports",
"Number of bad justifications on block-import",
)?,
registry,
)?,
})
}
}
#[derive(Clone, Debug)]
pub struct OnDemandIncomingRequestsMetrics {
pub beefy_successful_justification_responses: Counter<U64>,
pub beefy_failed_justification_responses: Counter<U64>,
}
impl PrometheusRegister for OnDemandIncomingRequestsMetrics {
const DESCRIPTION: &'static str = "on-demand incoming justification requests";
fn register(registry: &Registry) -> Result<Self, PrometheusError> {
Ok(Self {
beefy_successful_justification_responses: register(
Counter::new(
"substrate_beefy_successful_justification_responses",
"Number of Successful Justification responses",
)?,
registry,
)?,
beefy_failed_justification_responses: register(
Counter::new(
"substrate_beefy_failed_justification_responses",
"Number of Failed Justification responses",
)?,
registry,
)?,
})
}
}
#[derive(Clone, Debug)]
pub struct OnDemandOutgoingRequestsMetrics {
pub beefy_on_demand_justification_no_peer_to_request_from: Counter<U64>,
pub beefy_on_demand_justification_peer_refused: Counter<U64>,
pub beefy_on_demand_justification_peer_error: Counter<U64>,
pub beefy_on_demand_justification_invalid_proof: Counter<U64>,
pub beefy_on_demand_justification_good_proof: Counter<U64>,
pub beefy_on_demand_live_peers: Gauge<U64>,
}
impl PrometheusRegister for OnDemandOutgoingRequestsMetrics {
const DESCRIPTION: &'static str = "on-demand outgoing justification requests";
fn register(registry: &Registry) -> Result<Self, PrometheusError> {
Ok(Self {
beefy_on_demand_justification_no_peer_to_request_from: register(
Counter::new(
"substrate_beefy_on_demand_justification_no_peer_to_request_from",
"Number of times there was no good peer to request justification from",
)?,
registry,
)?,
beefy_on_demand_justification_peer_refused: register(
Counter::new(
"beefy_on_demand_justification_peer_refused",
"Number of on-demand justification peer refused valid requests",
)?,
registry,
)?,
beefy_on_demand_justification_peer_error: register(
Counter::new(
"substrate_beefy_on_demand_justification_peer_error",
"Number of on-demand justification peer error",
)?,
registry,
)?,
beefy_on_demand_justification_invalid_proof: register(
Counter::new(
"substrate_beefy_on_demand_justification_invalid_proof",
"Number of on-demand justification invalid proof",
)?,
registry,
)?,
beefy_on_demand_justification_good_proof: register(
Counter::new(
"substrate_beefy_on_demand_justification_good_proof",
"Number of on-demand justification good proof",
)?,
registry,
)?,
beefy_on_demand_live_peers: register(
Gauge::new(
"substrate_beefy_on_demand_live_peers",
"Number of live beefy peers available for requests.",
)?,
registry,
)?,
})
}
}
pub(crate) fn register_metrics<T: PrometheusRegister>(
prometheus_registry: Option<prometheus_endpoint::Registry>,
) -> Option<T> {
prometheus_registry.as_ref().map(T::register).and_then(|result| match result {
Ok(metrics) => {
debug!(target: LOG_TARGET, "🥩 Registered {} metrics", T::DESCRIPTION);
Some(metrics)
},
Err(err) => {
error!(
target: LOG_TARGET,
"🥩 Failed to register {} metrics: {:?}",
T::DESCRIPTION,
err
);
None
},
})
}
#[macro_export]
macro_rules! metric_set {
($metrics:expr, $m:ident, $v:expr) => {{
let val: u64 = format!("{}", $v).parse().unwrap();
if let Some(metrics) = $metrics.as_ref() {
metrics.$m.set(val);
}
}};
}
#[macro_export]
macro_rules! metric_inc {
($metrics:expr, $m:ident) => {{
if let Some(metrics) = $metrics.as_ref() {
metrics.$m.inc();
}
}};
}
#[macro_export]
macro_rules! metric_get {
($metrics:expr, $m:ident) => {{
$metrics.as_ref().map(|metrics| metrics.$m.clone())
}};
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
#[test]
fn should_register_metrics() {
let registry = Some(Registry::new());
assert!(register_metrics::<VoterMetrics>(registry.clone()).is_some());
assert!(register_metrics::<BlockImportMetrics>(registry.clone()).is_some());
assert!(register_metrics::<OnDemandIncomingRequestsMetrics>(registry.clone()).is_some());
assert!(register_metrics::<OnDemandOutgoingRequestsMetrics>(registry.clone()).is_some());
}
}