From 75fb90be9a04ba8161e6ba359a9912ea6275787e Mon Sep 17 00:00:00 2001 From: Bjerg Date: Sun, 18 Dec 2022 12:57:37 +0100 Subject: [PATCH] refactor: move metrics endpoint to node cmd (#505) * refactor: move metrics endpoint to node cmd * feat: value names * refactor: simplify db path parsing --- bin/reth/src/cli.rs | 21 ++------------------- bin/reth/src/db/mod.rs | 16 ++++++++-------- bin/reth/src/node/mod.rs | 34 ++++++++++++++++++++++++++++------ bin/reth/src/util/mod.rs | 13 +++++++++++-- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/bin/reth/src/cli.rs b/bin/reth/src/cli.rs index bd53e83ed..700ec361f 100644 --- a/bin/reth/src/cli.rs +++ b/bin/reth/src/cli.rs @@ -1,8 +1,6 @@ //! CLI definition and entrypoint to executable use clap::{ArgAction, Parser, Subcommand}; -use metrics_exporter_prometheus::PrometheusBuilder; -use metrics_util::layers::{PrefixLayer, Stack}; use tracing_subscriber::util::SubscriberInitExt; use crate::{ @@ -13,20 +11,8 @@ use crate::{ /// main function that parses cli and runs command pub async fn run() -> eyre::Result<()> { let opt = Cli::parse(); - - let tracing = if opt.silent { TracingMode::Silent } else { TracingMode::All }; - - reth_tracing::build_subscriber(tracing).init(); - - if opt.metrics { - let (recorder, exporter) = - PrometheusBuilder::new().build().expect("couldn't build Prometheus"); - tokio::task::spawn(exporter); - Stack::new(recorder) - .push(PrefixLayer::new("reth")) - .install() - .expect("couldn't install metrics recorder"); - } + reth_tracing::build_subscriber(if opt.silent { TracingMode::Silent } else { TracingMode::All }) + .init(); match opt.command { Commands::Node(command) => command.execute().await, @@ -63,7 +49,4 @@ struct Cli { /// Silence all output #[clap(long, global = true)] silent: bool, - - #[clap(long, global = true)] - metrics: bool, } diff --git a/bin/reth/src/db/mod.rs b/bin/reth/src/db/mod.rs index ebee2bdc1..465314b3e 100644 --- a/bin/reth/src/db/mod.rs +++ b/bin/reth/src/db/mod.rs @@ -1,5 +1,6 @@ //! Database debugging tool +use crate::util::parse_path; use clap::{Parser, Subcommand}; use eyre::{Result, WrapErr}; use reth_db::{ @@ -11,15 +12,16 @@ use reth_db::{ }; use reth_interfaces::test_utils::generators::random_block_range; use reth_provider::insert_canonical_block; -use std::path::Path; +use std::path::PathBuf; use tracing::info; /// `reth db` command #[derive(Debug, Parser)] pub struct Command { - /// Path to database folder - #[arg(long, default_value = "~/.reth/db")] - db: String, + /// The path to the database folder. + // TODO: This should use dirs-next + #[arg(long, value_name = "PATH", default_value = "~/.reth/db", value_parser = parse_path)] + db: PathBuf, #[clap(subcommand)] command: Subcommands, @@ -58,13 +60,11 @@ pub struct ListArgs { impl Command { /// Execute `db` command pub async fn execute(&self) -> eyre::Result<()> { - let path = shellexpand::full(&self.db)?.into_owned(); - let expanded_db_path = Path::new(&path); - std::fs::create_dir_all(expanded_db_path)?; + std::fs::create_dir_all(&self.db)?; // TODO: Auto-impl for Database trait let db = reth_db::mdbx::Env::::open( - expanded_db_path, + &self.db, reth_db::mdbx::EnvKind::RW, )?; diff --git a/bin/reth/src/node/mod.rs b/bin/reth/src/node/mod.rs index f59c3e4c7..7c10a2612 100644 --- a/bin/reth/src/node/mod.rs +++ b/bin/reth/src/node/mod.rs @@ -1,8 +1,11 @@ //! Main node command //! //! Starts the client -use crate::util::chainspec::Genesis; +use crate::util::{chainspec::Genesis, parse_path}; use clap::{crate_version, Parser}; +use eyre::WrapErr; +use metrics_exporter_prometheus::PrometheusBuilder; +use metrics_util::layers::{PrefixLayer, Stack}; use reth_consensus::EthConsensus; use reth_db::{ cursor::DbCursorRO, @@ -22,6 +25,7 @@ use reth_primitives::{hex_literal::hex, Account, Header, H256}; use reth_provider::{db_provider::ProviderImpl, BlockProvider, HeaderProvider}; use reth_stages::stages::{bodies::BodyStage, headers::HeaderStage, senders::SendersStage}; use std::{ + net::SocketAddr, path::{Path, PathBuf}, sync::Arc, }; @@ -35,8 +39,14 @@ const MAINNET_GENESIS: &str = include_str!("../../res/chainspec/mainnet.json"); pub struct Command { /// The path to the database folder. // TODO: This should use dirs-next - #[arg(long, default_value = "~/.reth/db")] - db: String, + #[arg(long, value_name = "PATH", default_value = "~/.reth/db", value_parser = parse_path)] + db: PathBuf, + + /// Enable Prometheus metrics. + /// + /// The metrics will be served at the given interface and port. + #[clap(long, value_name = "SOCKET")] + metrics: Option, } impl Command { @@ -45,11 +55,23 @@ impl Command { pub async fn execute(&self) -> eyre::Result<()> { info!("reth {} starting", crate_version!()); - let db_path = PathBuf::from(shellexpand::full(&self.db)?.into_owned()); - info!("Opening database at {}", db_path.display()); - let db = Arc::new(init_db(db_path)?); + info!("Opening database at {}", &self.db.display()); + let db = Arc::new(init_db(&self.db)?); info!("Database open"); + if let Some(listen_addr) = self.metrics { + info!("Starting metrics endpoint at {}", listen_addr); + let (recorder, exporter) = PrometheusBuilder::new() + .with_http_listener(listen_addr) + .build() + .wrap_err("Could not build Prometheus endpoint.")?; + tokio::task::spawn(exporter); + Stack::new(recorder) + .push(PrefixLayer::new("reth")) + .install() + .wrap_err("Couldn't set metrics recorder.")?; + } + // TODO: More info from chainspec (chain ID etc.) let consensus = Arc::new(EthConsensus::new(consensus_config())); let genesis_hash = diff --git a/bin/reth/src/util/mod.rs b/bin/reth/src/util/mod.rs index d17116621..1141e32ce 100644 --- a/bin/reth/src/util/mod.rs +++ b/bin/reth/src/util/mod.rs @@ -1,11 +1,14 @@ //! Utility functions. - -use std::path::{Path, PathBuf}; +use std::{ + env::VarError, + path::{Path, PathBuf}, +}; use walkdir::{DirEntry, WalkDir}; /// Utilities for parsing chainspecs pub mod chainspec; +/// Finds all files in a directory with a given postfix. pub(crate) fn find_all_files_with_postfix(path: &Path, postfix: &str) -> Vec { WalkDir::new(path) .into_iter() @@ -15,6 +18,12 @@ pub(crate) fn find_all_files_with_postfix(path: &Path, postfix: &str) -> Vec>() } +/// Parses a user-specified path with support for environment variables and common shorthands (e.g. +/// ~ for the user's home directory). +pub(crate) fn parse_path(value: &str) -> Result> { + shellexpand::full(value).map(|path| PathBuf::from(path.into_owned())) +} + /// Tracing utility pub mod reth_tracing { use tracing::Subscriber;