From fd2769a603246415e3c06c3a08c62cbf6739bcd7 Mon Sep 17 00:00:00 2001 From: Ruud van Asseldonk Date: Wed, 13 Jul 2022 12:59:40 +0200 Subject: [PATCH] Expose epoch schedule metrics in Prometheus With the epoch start slots and the number of slots in the epoch (and the current slot, which we already had), we can infer/estimate: * Epoch progress percentage * Slots left until the next epoch * Time left until the next epoch (from slot height increase) These are useful metrics to have about the network. --- prometheus/src/bank_metrics.rs | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/prometheus/src/bank_metrics.rs b/prometheus/src/bank_metrics.rs index 2bb28d6caf3689..c287b135722adb 100644 --- a/prometheus/src/bank_metrics.rs +++ b/prometheus/src/bank_metrics.rs @@ -3,6 +3,8 @@ use crate::{ utils::{write_metric, Metric, MetricFamily}, }; use std::io; +use solana_sdk::sysvar; +use solana_sdk::sysvar::epoch_schedule::EpochSchedule; pub fn write_bank_metrics( banks_with_commitments: &BanksWithCommitments, @@ -28,6 +30,46 @@ pub fn write_bank_metrics( .for_each_commitment(|bank| Some(Metric::new(bank.clock().epoch))), }, )?; + write_metric( + out, + &MetricFamily { + name: "solana_block_epoch_start_slot", + help: "The first slot in the current epoch", + type_: "gauge", + metrics: banks_with_commitments + .for_each_commitment(|bank| { + // Note, the bank actually has a field that holds the EpochSchedule, + // but it is not public, so we can't easily access it here. We could + // make it public, but to make our patches less invasive, load the + // epoch schedule from the sysvar instead. It should always exist. + let epoch_schedule: EpochSchedule = bank + .get_account(&sysvar::epoch_schedule::id())? + .deserialize_data().ok()?; + let clock = bank.clock(); + Some(Metric::new(epoch_schedule.get_first_slot_in_epoch(clock.epoch))) + }), + }, + )?; + write_metric( + out, + &MetricFamily { + name: "solana_block_epoch_slots_total", + help: "The duration of the current epoch, in slots.", + type_: "gauge", + metrics: banks_with_commitments + .for_each_commitment(|bank| { + // Note, the bank actually has a field that holds the EpochSchedule, + // but it is not public, so we can't easily access it here. We could + // make it public, but to make our patches less invasive, load the + // epoch schedule from the sysvar instead. It should always exist. + let epoch_schedule: EpochSchedule = bank + .get_account(&sysvar::epoch_schedule::id())? + .deserialize_data().ok()?; + let clock = bank.clock(); + Some(Metric::new(epoch_schedule.get_slots_in_epoch(clock.epoch))) + }), + }, + )?; write_metric( out, &MetricFamily {