mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 21:38:31 +00:00
Health Endpoints for UI (#3668)
This PR adds some health endpoints for the beacon node and the validator client. Specifically it adds the endpoint: `/lighthouse/ui/health` These are not entirely stable yet. But provide a base for modification for our UI. These also may have issues with various platforms and may need modification.
This commit is contained in:
@@ -42,7 +42,7 @@ pub enum ClientGenesis {
|
||||
/// The core configuration of a Lighthouse beacon node.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
pub data_dir: PathBuf,
|
||||
data_dir: PathBuf,
|
||||
/// Name of the directory inside the data directory where the main "hot" DB is located.
|
||||
pub db_name: String,
|
||||
/// Path where the freezer database will be located.
|
||||
@@ -103,6 +103,17 @@ impl Default for Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Updates the data directory for the Client.
|
||||
pub fn set_data_dir(&mut self, data_dir: PathBuf) {
|
||||
self.data_dir = data_dir.clone();
|
||||
self.http_api.data_dir = data_dir;
|
||||
}
|
||||
|
||||
/// Gets the config's data_dir.
|
||||
pub fn data_dir(&self) -> &PathBuf {
|
||||
&self.data_dir
|
||||
}
|
||||
|
||||
/// Get the database path without initialising it.
|
||||
pub fn get_db_path(&self) -> PathBuf {
|
||||
self.get_data_dir().join(&self.db_name)
|
||||
|
||||
@@ -33,6 +33,9 @@ safe_arith = {path = "../../consensus/safe_arith"}
|
||||
task_executor = { path = "../../common/task_executor" }
|
||||
lru = "0.7.7"
|
||||
tree_hash = "0.4.1"
|
||||
sysinfo = "0.26.5"
|
||||
system_health = { path = "../../common/system_health" }
|
||||
directory = { path = "../../common/directory" }
|
||||
|
||||
[dev-dependencies]
|
||||
store = { path = "../store" }
|
||||
|
||||
@@ -26,12 +26,14 @@ use beacon_chain::{
|
||||
BeaconChainTypes, ProduceBlockVerification, WhenSlotSkipped,
|
||||
};
|
||||
pub use block_id::BlockId;
|
||||
use directory::DEFAULT_ROOT_DIR;
|
||||
use eth2::types::{
|
||||
self as api_types, EndpointVersion, SkipRandaoVerification, ValidatorId, ValidatorStatus,
|
||||
};
|
||||
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
||||
use lighthouse_version::version_with_platform;
|
||||
use network::{NetworkMessage, NetworkSenders, ValidatorSubscriptionMessage};
|
||||
use parking_lot::RwLock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use slog::{crit, debug, error, info, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
@@ -43,6 +45,8 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use sysinfo::{System, SystemExt};
|
||||
use system_health::observe_system_health_bn;
|
||||
use tokio::sync::mpsc::{Sender, UnboundedSender};
|
||||
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
|
||||
use types::{
|
||||
@@ -110,6 +114,7 @@ pub struct Config {
|
||||
pub tls_config: Option<TlsConfig>,
|
||||
pub allow_sync_stalled: bool,
|
||||
pub spec_fork_name: Option<ForkName>,
|
||||
pub data_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -122,6 +127,7 @@ impl Default for Config {
|
||||
tls_config: None,
|
||||
allow_sync_stalled: false,
|
||||
spec_fork_name: None,
|
||||
data_dir: PathBuf::from(DEFAULT_ROOT_DIR),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,6 +329,10 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
}
|
||||
});
|
||||
|
||||
// Create a `warp` filter for the data_dir.
|
||||
let inner_data_dir = ctx.config.data_dir.clone();
|
||||
let data_dir_filter = warp::any().map(move || inner_data_dir.clone());
|
||||
|
||||
// Create a `warp` filter that provides access to the beacon chain.
|
||||
let inner_ctx = ctx.clone();
|
||||
let chain_filter =
|
||||
@@ -431,6 +441,37 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
let inner_ctx = ctx.clone();
|
||||
let log_filter = warp::any().map(move || inner_ctx.log.clone());
|
||||
|
||||
// Create a `warp` filter that provides access to local system information.
|
||||
let system_info = Arc::new(RwLock::new(sysinfo::System::new()));
|
||||
{
|
||||
// grab write access for initialisation
|
||||
let mut system_info = system_info.write();
|
||||
system_info.refresh_disks_list();
|
||||
system_info.refresh_networks_list();
|
||||
system_info.refresh_cpu_specifics(sysinfo::CpuRefreshKind::everything());
|
||||
system_info.refresh_cpu();
|
||||
} // end lock
|
||||
|
||||
let system_info_filter =
|
||||
warp::any()
|
||||
.map(move || system_info.clone())
|
||||
.map(|sysinfo: Arc<RwLock<System>>| {
|
||||
{
|
||||
// refresh stats
|
||||
let mut sysinfo_lock = sysinfo.write();
|
||||
sysinfo_lock.refresh_memory();
|
||||
sysinfo_lock.refresh_cpu_specifics(sysinfo::CpuRefreshKind::everything());
|
||||
sysinfo_lock.refresh_cpu();
|
||||
sysinfo_lock.refresh_system();
|
||||
sysinfo_lock.refresh_networks();
|
||||
sysinfo_lock.refresh_disks();
|
||||
} // end lock
|
||||
sysinfo
|
||||
});
|
||||
|
||||
let app_start = std::time::Instant::now();
|
||||
let app_start_filter = warp::any().map(move || app_start);
|
||||
|
||||
/*
|
||||
*
|
||||
* Start of HTTP method definitions.
|
||||
@@ -2822,6 +2863,29 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
})
|
||||
});
|
||||
|
||||
// GET lighthouse/ui/health
|
||||
let get_lighthouse_ui_health = warp::path("lighthouse")
|
||||
.and(warp::path("ui"))
|
||||
.and(warp::path("health"))
|
||||
.and(warp::path::end())
|
||||
.and(system_info_filter)
|
||||
.and(app_start_filter)
|
||||
.and(data_dir_filter)
|
||||
.and(network_globals.clone())
|
||||
.and_then(
|
||||
|sysinfo, app_start: std::time::Instant, data_dir, network_globals| {
|
||||
blocking_json_task(move || {
|
||||
let app_uptime = app_start.elapsed().as_secs() as u64;
|
||||
Ok(api_types::GenericResponse::from(observe_system_health_bn(
|
||||
sysinfo,
|
||||
data_dir,
|
||||
app_uptime,
|
||||
network_globals,
|
||||
)))
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// GET lighthouse/syncing
|
||||
let get_lighthouse_syncing = warp::path("lighthouse")
|
||||
.and(warp::path("syncing"))
|
||||
@@ -3271,6 +3335,7 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
.or(get_validator_aggregate_attestation.boxed())
|
||||
.or(get_validator_sync_committee_contribution.boxed())
|
||||
.or(get_lighthouse_health.boxed())
|
||||
.or(get_lighthouse_ui_health.boxed())
|
||||
.or(get_lighthouse_syncing.boxed())
|
||||
.or(get_lighthouse_nat.boxed())
|
||||
.or(get_lighthouse_peers.boxed())
|
||||
|
||||
@@ -2,6 +2,7 @@ use beacon_chain::{
|
||||
test_utils::{BeaconChainHarness, EphemeralHarnessType},
|
||||
BeaconChain, BeaconChainTypes,
|
||||
};
|
||||
use directory::DEFAULT_ROOT_DIR;
|
||||
use eth2::{BeaconNodeHttpClient, Timeouts};
|
||||
use http_api::{Config, Context};
|
||||
use lighthouse_network::{
|
||||
@@ -142,6 +143,7 @@ pub async fn create_api_server_on_port<T: BeaconChainTypes>(
|
||||
allow_origin: None,
|
||||
tls_config: None,
|
||||
allow_sync_stalled: false,
|
||||
data_dir: std::path::PathBuf::from(DEFAULT_ROOT_DIR),
|
||||
spec_fork_name: None,
|
||||
},
|
||||
chain: Some(chain.clone()),
|
||||
|
||||
@@ -8,7 +8,6 @@ use libp2p::gossipsub::subscription_filter::{
|
||||
};
|
||||
use libp2p::gossipsub::Gossipsub as BaseGossipsub;
|
||||
use libp2p::identify::Identify;
|
||||
use libp2p::swarm::NetworkBehaviour;
|
||||
use libp2p::NetworkBehaviour;
|
||||
use types::EthSpec;
|
||||
|
||||
|
||||
@@ -34,13 +34,13 @@ pub fn get_config<E: EthSpec>(
|
||||
let spec = &context.eth2_config.spec;
|
||||
let log = context.log();
|
||||
|
||||
let mut client_config = ClientConfig {
|
||||
data_dir: get_data_dir(cli_args),
|
||||
..Default::default()
|
||||
};
|
||||
let mut client_config = ClientConfig::default();
|
||||
|
||||
// Update the client's data directory
|
||||
client_config.set_data_dir(get_data_dir(cli_args));
|
||||
|
||||
// If necessary, remove any existing database and configuration
|
||||
if client_config.data_dir.exists() && cli_args.is_present("purge-db") {
|
||||
if client_config.data_dir().exists() && cli_args.is_present("purge-db") {
|
||||
// Remove the chain_db.
|
||||
let chain_db = client_config.get_db_path();
|
||||
if chain_db.exists() {
|
||||
@@ -57,11 +57,11 @@ pub fn get_config<E: EthSpec>(
|
||||
}
|
||||
|
||||
// Create `datadir` and any non-existing parent directories.
|
||||
fs::create_dir_all(&client_config.data_dir)
|
||||
fs::create_dir_all(client_config.data_dir())
|
||||
.map_err(|e| format!("Failed to create data dir: {}", e))?;
|
||||
|
||||
// logs the chosen data directory
|
||||
let mut log_dir = client_config.data_dir.clone();
|
||||
let mut log_dir = client_config.data_dir().clone();
|
||||
// remove /beacon from the end
|
||||
log_dir.pop();
|
||||
info!(log, "Data directory initialised"; "datadir" => log_dir.into_os_string().into_string().expect("Datadir should be a valid os string"));
|
||||
@@ -69,10 +69,13 @@ pub fn get_config<E: EthSpec>(
|
||||
/*
|
||||
* Networking
|
||||
*/
|
||||
|
||||
let data_dir_ref = client_config.data_dir().clone();
|
||||
|
||||
set_network_config(
|
||||
&mut client_config.network,
|
||||
cli_args,
|
||||
&client_config.data_dir,
|
||||
&data_dir_ref,
|
||||
log,
|
||||
false,
|
||||
)?;
|
||||
@@ -303,7 +306,7 @@ pub fn get_config<E: EthSpec>(
|
||||
} else if let Some(jwt_secret_key) = cli_args.value_of("execution-jwt-secret-key") {
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
secret_file = client_config.data_dir.join(DEFAULT_JWT_FILE);
|
||||
secret_file = client_config.data_dir().join(DEFAULT_JWT_FILE);
|
||||
let mut jwt_secret_key_file = File::create(secret_file.clone())
|
||||
.map_err(|e| format!("Error while creating jwt_secret_key file: {:?}", e))?;
|
||||
jwt_secret_key_file
|
||||
@@ -332,7 +335,7 @@ pub fn get_config<E: EthSpec>(
|
||||
clap_utils::parse_optional(cli_args, "suggested-fee-recipient")?;
|
||||
el_config.jwt_id = clap_utils::parse_optional(cli_args, "execution-jwt-id")?;
|
||||
el_config.jwt_version = clap_utils::parse_optional(cli_args, "execution-jwt-version")?;
|
||||
el_config.default_datadir = client_config.data_dir.clone();
|
||||
el_config.default_datadir = client_config.data_dir().clone();
|
||||
el_config.builder_profit_threshold =
|
||||
clap_utils::parse_required(cli_args, "builder-profit-threshold")?;
|
||||
let execution_timeout_multiplier =
|
||||
@@ -573,7 +576,7 @@ pub fn get_config<E: EthSpec>(
|
||||
let slasher_dir = if let Some(slasher_dir) = cli_args.value_of("slasher-dir") {
|
||||
PathBuf::from(slasher_dir)
|
||||
} else {
|
||||
client_config.data_dir.join("slasher_db")
|
||||
client_config.data_dir().join("slasher_db")
|
||||
};
|
||||
|
||||
let mut slasher_config = slasher::Config::new(slasher_dir);
|
||||
|
||||
Reference in New Issue
Block a user