Add uptime column to show-validators (#7441) (#7445)

automerge
This commit is contained in:
mergify[bot]
2019-12-12 08:27:50 -08:00
committed by Grimes
parent 5e4fe9c67b
commit ebf644ddef
5 changed files with 157 additions and 80 deletions

View File

@ -13,6 +13,7 @@ use solana_client::{rpc_client::RpcClient, rpc_request::RpcVoteAccountInfo};
use solana_sdk::{
clock::{self, Slot},
commitment_config::CommitmentConfig,
epoch_schedule::{Epoch, EpochSchedule},
hash::Hash,
pubkey::Pubkey,
signature::{Keypair, KeypairUtil},
@ -260,6 +261,20 @@ fn new_spinner_progress_bar() -> ProgressBar {
progress_bar
}
/// Aggregate epoch credit stats and return (total credits, total slots, total epochs)
pub fn aggregate_epoch_credits(
epoch_credits: &[(Epoch, u64, u64)],
epoch_schedule: &EpochSchedule,
) -> (u64, u64, u64) {
epoch_credits
.iter()
.fold((0, 0, 0), |acc, (epoch, credits, prev_credits)| {
let credits_earned = credits - prev_credits;
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
(acc.0 + credits_earned, acc.1 + slots_in_epoch, acc.2 + 1)
})
}
pub fn process_catchup(rpc_client: &RpcClient, node_pubkey: &Pubkey) -> ProcessResult {
let cluster_nodes = rpc_client.get_cluster_nodes()?;
@ -550,6 +565,7 @@ pub fn process_show_gossip(rpc_client: &RpcClient) -> ProcessResult {
}
pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool) -> ProcessResult {
let epoch_schedule = rpc_client.get_epoch_schedule()?;
let vote_accounts = rpc_client.get_vote_accounts()?;
let total_active_stake = vote_accounts
.current
@ -592,19 +608,21 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
println!(
"{}",
style(format!(
" {:<44} {:<44} {} {} {} {}",
" {:<44} {:<44} {} {} {} {:>7} {}",
"Identity Pubkey",
"Vote Account Pubkey",
"Commission",
"Last Vote",
"Root Block",
"Uptime",
"Active Stake",
))
.bold()
);
fn print_vote_account(
vote_account: &RpcVoteAccountInfo,
vote_account: RpcVoteAccountInfo,
epoch_schedule: &EpochSchedule,
total_active_stake: f64,
use_lamports_unit: bool,
delinquent: bool,
@ -616,8 +634,20 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
format!("{}", v)
}
}
fn uptime(epoch_credits: Vec<(Epoch, u64, u64)>, epoch_schedule: &EpochSchedule) -> String {
let (total_credits, total_slots, _) =
aggregate_epoch_credits(&epoch_credits, &epoch_schedule);
if total_slots > 0 {
let total_uptime = 100_f64 * total_credits as f64 / total_slots as f64;
format!("{:.2}%", total_uptime)
} else {
"-".into()
}
}
println!(
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>12}",
"{} {:<44} {:<44} {:>9}% {:>8} {:>10} {:>7} {}",
if delinquent {
WARNING.to_string()
} else {
@ -628,6 +658,7 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
vote_account.commission,
non_zero_or_dash(vote_account.last_vote),
non_zero_or_dash(vote_account.root_slot),
uptime(vote_account.epoch_credits, epoch_schedule),
if vote_account.activated_stake > 0 {
format!(
"{} ({:.2}%)",
@ -640,11 +671,23 @@ pub fn process_show_validators(rpc_client: &RpcClient, use_lamports_unit: bool)
);
}
for vote_account in vote_accounts.current.iter() {
print_vote_account(vote_account, total_active_stake, use_lamports_unit, false);
for vote_account in vote_accounts.current.into_iter() {
print_vote_account(
vote_account,
&epoch_schedule,
total_active_stake,
use_lamports_unit,
false,
);
}
for vote_account in vote_accounts.delinquent.iter() {
print_vote_account(vote_account, total_active_stake, use_lamports_unit, true);
for vote_account in vote_accounts.delinquent.into_iter() {
print_vote_account(
vote_account,
&epoch_schedule,
total_active_stake,
use_lamports_unit,
true,
);
}
Ok("".to_string())

View File

@ -1,6 +1,10 @@
use crate::cli::{
build_balance_message, check_account_for_fee, check_unique_pubkeys,
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError, ProcessResult,
use crate::{
cli::{
build_balance_message, check_account_for_fee, check_unique_pubkeys,
log_instruction_custom_error, CliCommand, CliCommandInfo, CliConfig, CliError,
ProcessResult,
},
cluster_query::aggregate_epoch_credits,
};
use clap::{value_t_or_exit, App, Arg, ArgMatches, SubCommand};
use solana_clap_utils::{input_parsers::*, input_validators::*};
@ -401,33 +405,37 @@ pub fn process_uptime(
if !vote_state.votes.is_empty() {
println!("Uptime:");
let epoch_credits_vec: Vec<(u64, u64, u64)> = vote_state.epoch_credits().copied().collect();
let epoch_credits = if let Some(x) = span {
epoch_credits_vec.iter().rev().take(x as usize)
let epoch_credits: Vec<(u64, u64, u64)> = if let Some(x) = span {
vote_state
.epoch_credits()
.iter()
.rev()
.take(x as usize)
.cloned()
.collect()
} else {
epoch_credits_vec.iter().rev().take(epoch_credits_vec.len())
vote_state.epoch_credits().iter().rev().cloned().collect()
};
if aggregate {
let (credits_earned, slots_in_epoch, epochs): (u64, u64, u64) =
epoch_credits.fold((0, 0, 0), |acc, (epoch, credits, prev_credits)| {
let credits_earned = credits - prev_credits;
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
(acc.0 + credits_earned, acc.1 + slots_in_epoch, acc.2 + 1)
});
let total_uptime = credits_earned as f64 / slots_in_epoch as f64;
println!("{:.2}% over {} epochs", total_uptime * 100_f64, epochs,);
let (total_credits, total_slots, epochs) =
aggregate_epoch_credits(&epoch_credits, &epoch_schedule);
if total_slots > 0 {
let total_uptime = 100_f64 * total_credits as f64 / total_slots as f64;
println!("{:.2}% over {} epochs", total_uptime, epochs);
} else {
println!("Insufficient voting history available");
}
} else {
for (epoch, credits, prev_credits) in epoch_credits {
let credits_earned = credits - prev_credits;
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(*epoch);
let slots_in_epoch = epoch_schedule.get_slots_in_epoch(epoch);
let uptime = credits_earned as f64 / slots_in_epoch as f64;
println!("- epoch: {} {:.2}% uptime", epoch, uptime * 100_f64,);
}
}
if let Some(x) = span {
if x > epoch_credits_vec.len() as u64 {
if x > vote_state.epoch_credits().len() as u64 {
println!("(span longer than available epochs)");
}
}