diff --git a/Cargo.toml b/Cargo.toml index ff1fe7c89..ee547d225 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,6 +110,7 @@ ethers-middleware = { version = "2.0.8", default-features = false } ## misc bytes = "1.4" tracing = "0.1.0" +tracing-appender = "0.2" thiserror = "1.0.37" serde_json = "1.0.94" serde = { version = "1.0", default-features = false } diff --git a/bin/reth/src/cli.rs b/bin/reth/src/cli.rs index c32b1ae17..ce5d4a42c 100644 --- a/bin/reth/src/cli.rs +++ b/bin/reth/src/cli.rs @@ -14,31 +14,62 @@ use reth_tracing::{ BoxedLayer, FileWorkerGuard, }; -/// Parse CLI options, set up logging and run the chosen command. -pub fn run() -> eyre::Result<()> { - let opt = Cli::parse(); +/// The main reth cli interface. +/// +/// This is the entrypoint to the executable. +#[derive(Debug, Parser)] +#[command(author, version = SHORT_VERSION, long_version = LONG_VERSION, about = "Reth", long_about = None)] +pub struct Cli { + /// The command to run + #[clap(subcommand)] + command: Commands, - let mut layers = vec![reth_tracing::stdout(opt.verbosity.directive())]; - let _guard = opt.logs.layer()?.map(|(layer, guard)| { - layers.push(layer); - guard - }); + #[clap(flatten)] + logs: Logs, - reth_tracing::init(layers); + #[clap(flatten)] + verbosity: Verbosity, +} - let runner = CliRunner::default(); +impl Cli { + /// Execute the configured cli command. + pub fn run(self) -> eyre::Result<()> { + let _guard = self.init_tracing()?; - match opt.command { - Commands::Node(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), - Commands::Init(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Import(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Db(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::Stage(command) => runner.run_blocking_until_ctrl_c(command.execute()), - Commands::P2P(command) => runner.run_until_ctrl_c(command.execute()), - Commands::TestVectors(command) => runner.run_until_ctrl_c(command.execute()), - Commands::Config(command) => runner.run_until_ctrl_c(command.execute()), - Commands::Debug(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), + let runner = CliRunner::default(); + match self.command { + Commands::Node(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), + Commands::Init(command) => runner.run_blocking_until_ctrl_c(command.execute()), + Commands::Import(command) => runner.run_blocking_until_ctrl_c(command.execute()), + Commands::Db(command) => runner.run_blocking_until_ctrl_c(command.execute()), + Commands::Stage(command) => runner.run_blocking_until_ctrl_c(command.execute()), + Commands::P2P(command) => runner.run_until_ctrl_c(command.execute()), + Commands::TestVectors(command) => runner.run_until_ctrl_c(command.execute()), + Commands::Config(command) => runner.run_until_ctrl_c(command.execute()), + Commands::Debug(command) => runner.run_command_until_exit(|ctx| command.execute(ctx)), + } } + + /// Initializes tracing with the configured options. + /// + /// If file logging is enabled, this function returns a guard that must be kept alive to ensure + /// that all logs are flushed to disk. + pub fn init_tracing(&self) -> eyre::Result> { + let mut layers = vec![reth_tracing::stdout(self.verbosity.directive())]; + let guard = self.logs.layer()?.map(|(layer, guard)| { + layers.push(layer); + guard + }); + + reth_tracing::init(layers); + Ok(guard.flatten()) + } +} + +/// Convenience function for parsing CLI options, set up logging and run the chosen command. +#[inline] +pub fn run() -> eyre::Result<()> { + Cli::parse().run() } /// Commands to be executed @@ -73,20 +104,6 @@ pub enum Commands { Debug(debug_cmd::Command), } -#[derive(Debug, Parser)] -#[command(author, version = SHORT_VERSION, long_version = LONG_VERSION, about = "Reth", long_about = None)] -struct Cli { - /// The command to run - #[clap(subcommand)] - command: Commands, - - #[clap(flatten)] - logs: Logs, - - #[clap(flatten)] - verbosity: Verbosity, -} - /// The log configuration. #[derive(Debug, Args)] #[command(next_help_heading = "Logging")] diff --git a/crates/tracing/Cargo.toml b/crates/tracing/Cargo.toml index 444f1b23a..8f652da25 100644 --- a/crates/tracing/Cargo.toml +++ b/crates/tracing/Cargo.toml @@ -11,5 +11,5 @@ description = "tracing helpers" [dependencies] tracing.workspace = true tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } -tracing-appender = "0.2" +tracing-appender.workspace = true tracing-journald = "0.3" diff --git a/crates/tracing/src/lib.rs b/crates/tracing/src/lib.rs index 1695c336e..074b6dc9f 100644 --- a/crates/tracing/src/lib.rs +++ b/crates/tracing/src/lib.rs @@ -68,6 +68,7 @@ where /// /// The boxed layer and a guard is returned. When the guard is dropped the buffer for the log /// file is immediately flushed to disk. Any events after the guard is dropped may be missed. +#[must_use = "tracing guard must be kept alive to flush events to disk"] pub fn file( filter: EnvFilter, dir: impl AsRef,