diff --git a/Cargo.lock b/Cargo.lock index 0845433a0..37fad6383 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1061,8 +1061,10 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.48.5", ] @@ -6169,6 +6171,7 @@ dependencies = [ name = "reth-tracing" version = "0.1.0-alpha.8" dependencies = [ + "rolling-file", "tracing", "tracing-appender", "tracing-journald", @@ -6366,6 +6369,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rolling-file" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8395b4f860856b740f20a296ea2cd4d823e81a2658cf05ef61be22916026a906" +dependencies = [ + "chrono", +] + [[package]] name = "route-recognizer" version = "0.3.1" diff --git a/bin/reth/src/cli/mod.rs b/bin/reth/src/cli/mod.rs index 79b0ab00a..440a45d10 100644 --- a/bin/reth/src/cli/mod.rs +++ b/bin/reth/src/cli/mod.rs @@ -158,10 +158,6 @@ pub enum Commands { #[derive(Debug, Args)] #[command(next_help_heading = "Logging")] pub struct Logs { - /// The flag to enable persistent logs. - #[arg(long = "log.persistent", global = true, conflicts_with = "journald")] - persistent: bool, - /// The path to put log files in. #[arg( long = "log.directory", @@ -172,6 +168,15 @@ pub struct Logs { )] log_directory: PlatformPath, + /// The maximum size (in MB) of log files. + #[arg(long = "log.max-size", value_name = "SIZE", global = true, default_value_t = 200)] + log_max_size: u64, + + /// The maximum amount of log files that will be stored. If set to 0, background file logging + /// is disabled. + #[arg(long = "log.max-files", value_name = "COUNT", global = true, default_value_t = 5)] + log_max_files: usize, + /// Log events to journald. #[arg(long = "log.journald", global = true, conflicts_with = "log_directory")] journald: bool, @@ -191,6 +196,9 @@ pub struct Logs { color: ColorMode, } +/// Constant to convert megabytes to bytes +const MB_TO_BYTES: u64 = 1024 * 1024; + impl Logs { /// Builds a tracing layer from the current log options. pub fn layer(&self) -> eyre::Result, Option)>> @@ -202,8 +210,14 @@ impl Logs { if self.journald { Ok(Some((reth_tracing::journald(filter).expect("Could not connect to journald"), None))) - } else if self.persistent { - let (layer, guard) = reth_tracing::file(filter, &self.log_directory, "reth.log"); + } else if self.log_max_files > 0 { + let (layer, guard) = reth_tracing::file( + filter, + &self.log_directory, + "reth.log", + self.log_max_size * MB_TO_BYTES, + self.log_max_files, + ); Ok(Some((layer, Some(guard)))) } else { Ok(None) @@ -305,14 +319,12 @@ mod tests { /// name #[test] fn parse_logs_path() { - let mut reth = Cli::<()>::try_parse_from(["reth", "node", "--log.persistent"]).unwrap(); + let mut reth = Cli::<()>::try_parse_from(["reth", "node"]).unwrap(); reth.logs.log_directory = reth.logs.log_directory.join(reth.chain.chain.to_string()); let log_dir = reth.logs.log_directory; assert!(log_dir.as_ref().ends_with("reth/logs/mainnet"), "{:?}", log_dir); - let mut reth = - Cli::<()>::try_parse_from(["reth", "node", "--chain", "sepolia", "--log.persistent"]) - .unwrap(); + let mut reth = Cli::<()>::try_parse_from(["reth", "node", "--chain", "sepolia"]).unwrap(); reth.logs.log_directory = reth.logs.log_directory.join(reth.chain.chain.to_string()); let log_dir = reth.logs.log_directory; assert!(log_dir.as_ref().ends_with("reth/logs/sepolia"), "{:?}", log_dir); diff --git a/crates/tracing/Cargo.toml b/crates/tracing/Cargo.toml index 8f652da25..424545b98 100644 --- a/crates/tracing/Cargo.toml +++ b/crates/tracing/Cargo.toml @@ -13,3 +13,4 @@ tracing.workspace = true tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } tracing-appender.workspace = true tracing-journald = "0.3" +rolling-file = "0.2.0" diff --git a/crates/tracing/src/lib.rs b/crates/tracing/src/lib.rs index e6c3caacc..8ad0d70e1 100644 --- a/crates/tracing/src/lib.rs +++ b/crates/tracing/src/lib.rs @@ -19,6 +19,7 @@ //! - [`journald()`] //! //! As well as a simple way to initialize a subscriber: [`init`]. +use rolling_file::{RollingConditionBasic, RollingFileAppender}; use std::path::Path; use tracing::Subscriber; use tracing_subscriber::{ @@ -74,13 +75,28 @@ pub fn file( filter: EnvFilter, dir: impl AsRef, file_name: impl AsRef, + max_size_bytes: u64, + max_files: usize, ) -> (BoxedLayer, tracing_appender::non_blocking::WorkerGuard) where S: Subscriber, for<'a> S: LookupSpan<'a>, { - let (writer, guard) = - tracing_appender::non_blocking(tracing_appender::rolling::never(dir, file_name)); + // Create log dir if it doesn't exist (RFA doesn't do this for us) + let log_dir = dir.as_ref(); + if !log_dir.exists() { + std::fs::create_dir_all(log_dir).expect("Could not create log directory"); + } + + // Create layer + let (writer, guard) = tracing_appender::non_blocking( + RollingFileAppender::new( + log_dir.join(file_name.as_ref()), + RollingConditionBasic::new().max_size(max_size_bytes), + max_files, + ) + .expect("Could not initialize file logging"), + ); let layer = tracing_subscriber::fmt::layer() .with_ansi(false) .with_writer(writer)