From 58cca78067740030642456e4ec2a19bb44b25390 Mon Sep 17 00:00:00 2001 From: Jeff Biseda Date: Fri, 11 Aug 2023 14:38:33 -0700 Subject: [PATCH] sanity check metrics configuration (#32799) --- Cargo.lock | 1 + core/src/validator.rs | 10 +++++-- metrics/Cargo.toml | 1 + metrics/src/metrics.rs | 62 +++++++++++++++++++++++++++++++---------- programs/sbf/Cargo.lock | 1 + 5 files changed, 59 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1097ee3fb20ad1..755cd9273999f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6411,6 +6411,7 @@ dependencies = [ "reqwest", "serial_test", "solana-sdk", + "thiserror", ] [[package]] diff --git a/core/src/validator.rs b/core/src/validator.rs index 7bc8a8f12cb460..32e2e9077530d5 100644 --- a/core/src/validator.rs +++ b/core/src/validator.rs @@ -65,7 +65,9 @@ use { use_snapshot_archives_at_startup::UseSnapshotArchivesAtStartup, }, solana_measure::measure::Measure, - solana_metrics::{datapoint_info, poh_timing_point::PohTimingSender}, + solana_metrics::{ + datapoint_info, metrics::metrics_config_sanity_check, poh_timing_point::PohTimingSender, + }, solana_poh::{ poh_recorder::PohRecorder, poh_service::{self, PohService}, @@ -1250,10 +1252,14 @@ impl Validator { config.generator_config.clone(), ); + let cluster_type = bank_forks.read().unwrap().root_bank().cluster_type(); + metrics_config_sanity_check(cluster_type)?; + datapoint_info!( "validator-new", ("id", id.to_string(), String), - ("version", solana_version::version!(), String) + ("version", solana_version::version!(), String), + ("cluster_type", cluster_type as u32, i64), ); *start_progress.write().unwrap() = ValidatorStartProgress::Running; diff --git a/metrics/Cargo.toml b/metrics/Cargo.toml index 0cb3041bab6639..80f94e417bf3e7 100644 --- a/metrics/Cargo.toml +++ b/metrics/Cargo.toml @@ -16,6 +16,7 @@ lazy_static = { workspace = true } log = { workspace = true } reqwest = { workspace = true, features = ["blocking", "brotli", "deflate", "gzip", "rustls-tls", "json"] } solana-sdk = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] env_logger = { workspace = true } diff --git a/metrics/src/metrics.rs b/metrics/src/metrics.rs index 59ea01e9a8b337..c4cde872398392 100644 --- a/metrics/src/metrics.rs +++ b/metrics/src/metrics.rs @@ -6,7 +6,7 @@ use { gethostname::gethostname, lazy_static::lazy_static, log::*, - solana_sdk::hash::hash, + solana_sdk::{genesis_config::ClusterType, hash::hash}, std::{ cmp, collections::HashMap, @@ -17,10 +17,31 @@ use { thread, time::{Duration, Instant, UNIX_EPOCH}, }, + thiserror::Error, }; type CounterMap = HashMap<(&'static str, u64), CounterPoint>; +#[derive(Debug, Error)] +pub enum MetricsError { + #[error(transparent)] + VarError(#[from] std::env::VarError), + #[error(transparent)] + ReqwestError(#[from] reqwest::Error), + #[error("SOLANA_METRICS_CONFIG is invalid: '{0}'")] + ConfigInvalid(String), + #[error("SOLANA_METRICS_CONFIG is incomplete")] + ConfigIncomplete, + #[error("SOLANA_METRICS_CONFIG database mismatch: {0}")] + DbMismatch(String), +} + +impl From for String { + fn from(error: MetricsError) -> Self { + error.to_string() + } +} + impl From<&CounterPoint> for DataPoint { fn from(counter_point: &CounterPoint) -> Self { let mut point = Self::new(counter_point.name); @@ -58,7 +79,7 @@ impl InfluxDbMetricsWriter { } } - fn build_write_url() -> Result { + fn build_write_url() -> Result { let config = get_metrics_config().map_err(|err| { info!("metrics disabled: {}", err); err @@ -381,16 +402,14 @@ impl MetricsConfig { } } -fn get_metrics_config() -> Result { +fn get_metrics_config() -> Result { let mut config = MetricsConfig::default(); - - let config_var = - env::var("SOLANA_METRICS_CONFIG").map_err(|err| format!("SOLANA_METRICS_CONFIG: {err}"))?; + let config_var = env::var("SOLANA_METRICS_CONFIG")?; for pair in config_var.split(',') { let nv: Vec<_> = pair.split('=').collect(); if nv.len() != 2 { - return Err(format!("SOLANA_METRICS_CONFIG is invalid: '{pair}'")); + return Err(MetricsError::ConfigInvalid(pair.to_string())); } let v = nv[1].to_string(); match nv[0] { @@ -398,27 +417,42 @@ fn get_metrics_config() -> Result { "db" => config.db = v, "u" => config.username = v, "p" => config.password = v, - _ => return Err(format!("SOLANA_METRICS_CONFIG is invalid: '{pair}'")), + _ => return Err(MetricsError::ConfigInvalid(pair.to_string())), } } if !config.complete() { - return Err("SOLANA_METRICS_CONFIG is incomplete".to_string()); + return Err(MetricsError::ConfigIncomplete); } + Ok(config) } -pub fn query(q: &str) -> Result { +pub fn metrics_config_sanity_check(cluster_type: ClusterType) -> Result<(), MetricsError> { + let config = match get_metrics_config() { + Ok(config) => config, + Err(MetricsError::VarError(std::env::VarError::NotPresent)) => return Ok(()), + Err(e) => return Err(e), + }; + match &config.db[..] { + "mainnet-beta" if cluster_type != ClusterType::MainnetBeta => (), + "tds" if cluster_type != ClusterType::Testnet => (), + "devnet" if cluster_type != ClusterType::Devnet => (), + _ => return Ok(()), + }; + let (host, db) = (&config.host, &config.db); + let msg = format!("cluster_type={cluster_type:?} host={host} database={db}"); + Err(MetricsError::DbMismatch(msg)) +} + +pub fn query(q: &str) -> Result { let config = get_metrics_config()?; let query_url = format!( "{}/query?u={}&p={}&q={}", &config.host, &config.username, &config.password, &q ); - let response = reqwest::blocking::get(query_url.as_str()) - .map_err(|err| err.to_string())? - .text() - .map_err(|err| err.to_string())?; + let response = reqwest::blocking::get(query_url.as_str())?.text()?; Ok(response) } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index b9a523ffa5c778..e5cfb1c8c5661b 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -5230,6 +5230,7 @@ dependencies = [ "log", "reqwest", "solana-sdk", + "thiserror", ] [[package]]