diff --git a/Cargo.lock b/Cargo.lock index f30f3cc..2e2e90e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,6 +43,7 @@ dependencies = [ "anyhow", "gumdrop", "serde", + "simplelog", "toml", ] @@ -78,7 +79,6 @@ dependencies = [ "quickcheck_macros", "rand", "serde", - "simplelog", "smartstring", "socket2", ] @@ -210,7 +210,6 @@ dependencies = [ "quickcheck_macros", "rand", "serde", - "simplelog", "socket2", "tungstenite", ] diff --git a/TODO.md b/TODO.md index f44361a..1c022ca 100644 --- a/TODO.md +++ b/TODO.md @@ -2,9 +2,6 @@ ## General -* init logging in cli helper crate? kind of tricky, requires cli helper - knowledge of config, such as config implementing a trait to get log - level * automatic tests running real clients in container? ## aquatic_http_load_test diff --git a/aquatic_cli_helpers/Cargo.toml b/aquatic_cli_helpers/Cargo.toml index 16cc90d..830a6a1 100644 --- a/aquatic_cli_helpers/Cargo.toml +++ b/aquatic_cli_helpers/Cargo.toml @@ -9,4 +9,5 @@ license = "Apache-2.0" anyhow = "1" gumdrop = "0.8" serde = { version = "1", features = ["derive"] } +simplelog = "0.8" toml = "0.5" \ No newline at end of file diff --git a/aquatic_cli_helpers/src/lib.rs b/aquatic_cli_helpers/src/lib.rs index ed4d66d..2511ddb 100644 --- a/aquatic_cli_helpers/src/lib.rs +++ b/aquatic_cli_helpers/src/lib.rs @@ -3,7 +3,34 @@ use std::io::Read; use anyhow::Context; use gumdrop::Options; -use serde::{Serialize, de::DeserializeOwned}; +use serde::{Serialize, Deserialize, de::DeserializeOwned}; +use simplelog::{ConfigBuilder, LevelFilter, TermLogger, TerminalMode}; + + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum LogLevel { + Off, + Error, + Warn, + Info, + Debug, + Trace +} + + +impl Default for LogLevel { + fn default() -> Self { + Self::Error + } +} + + +pub trait Config: Default + Serialize + DeserializeOwned { + fn get_log_level(&self) -> Option { + None + } +} #[derive(Debug, Options)] @@ -21,7 +48,7 @@ pub fn run_app_with_cli_and_config( title: &str, // Function that takes config file and runs application app_fn: fn(T) -> anyhow::Result<()>, -) where T: Default + Serialize + DeserializeOwned { +) where T: Config { ::std::process::exit(match run_inner(title, app_fn) { Ok(()) => 0, Err(err) => { @@ -37,7 +64,7 @@ fn run_inner( title: &str, // Function that takes config file and runs application app_fn: fn(T) -> anyhow::Result<()>, -) -> anyhow::Result<()> where T: Default + Serialize + DeserializeOwned { +) -> anyhow::Result<()> where T: Config { let args: Vec = ::std::env::args().collect(); let opts = AppOptions::parse_args_default(&args[1..])?; @@ -51,15 +78,36 @@ fn run_inner( Ok(()) } else if let Some(config_file) = opts.config_file { - let config = config_from_toml_file(config_file)?; + let config: T = config_from_toml_file(config_file)?; + + if let Some(log_level) = config.get_log_level(){ + start_logger(log_level)?; + } app_fn(config) } else { - app_fn(T::default()) + let config = T::default(); + + if let Some(log_level) = config.get_log_level(){ + start_logger(log_level)?; + } + + app_fn(config) } } +fn print_help(title: &str, opt_error: Option){ + println!("{}", title); + + if let Some(error) = opt_error { + println!("\nError: {:#}.", error); + } + + println!("\n{}", AppOptions::usage()); +} + + fn config_from_toml_file(path: String) -> anyhow::Result where T: DeserializeOwned { @@ -87,12 +135,27 @@ fn default_config_as_toml() -> String } -fn print_help(title: &str, opt_error: Option){ - println!("{}", title); +fn start_logger(log_level: LogLevel) -> ::anyhow::Result<()> { + let level_filter = match log_level{ + LogLevel::Off => LevelFilter::Off, + LogLevel::Error => LevelFilter::Error, + LogLevel::Warn => LevelFilter::Warn, + LogLevel::Info => LevelFilter::Info, + LogLevel::Debug => LevelFilter::Debug, + LogLevel::Trace => LevelFilter::Trace, + }; - if let Some(error) = opt_error { - println!("\nError: {:#}.", error); - } + // Note: logger doesn't seem to pick up thread names. Not a huge loss. + let simplelog_config = ConfigBuilder::new() + .set_time_to_local(true) + .set_location_level(LevelFilter::Off) + .build(); - println!("\n{}", AppOptions::usage()); -} + TermLogger::init( + level_filter, + simplelog_config, + TerminalMode::Stderr + ).context("Couldn't initialize logger")?; + + Ok(()) +} \ No newline at end of file diff --git a/aquatic_http/Cargo.toml b/aquatic_http/Cargo.toml index 4d8893a..0a77fa9 100644 --- a/aquatic_http/Cargo.toml +++ b/aquatic_http/Cargo.toml @@ -32,7 +32,6 @@ parking_lot = "0.11" privdrop = "0.3" rand = { version = "0.7", features = ["small_rng"] } serde = { version = "1", features = ["derive"] } -simplelog = "0.8" smartstring = "0.2" socket2 = { version = "0.3", features = ["reuseport"] } diff --git a/aquatic_http/src/bin/main.rs b/aquatic_http/src/bin/main.rs index 4d093fd..0b049cf 100644 --- a/aquatic_http/src/bin/main.rs +++ b/aquatic_http/src/bin/main.rs @@ -1,8 +1,5 @@ -use anyhow::Context; use aquatic_cli_helpers::run_app_with_cli_and_config; -use simplelog::{ConfigBuilder, LevelFilter, TermLogger, TerminalMode}; - -use aquatic_http::config::{Config, LogLevel}; +use aquatic_http::config::Config; #[global_allocator] @@ -12,33 +9,6 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; fn main(){ run_app_with_cli_and_config::( "aquatic: BitTorrent (HTTP/TLS) tracker", - run + aquatic_http::run ) -} - - -// almost identical to ws version -fn run(config: Config) -> anyhow::Result<()> { - let level_filter = match config.log_level { - LogLevel::Off => LevelFilter::Off, - LogLevel::Error => LevelFilter::Error, - LogLevel::Warn => LevelFilter::Warn, - LogLevel::Info => LevelFilter::Info, - LogLevel::Debug => LevelFilter::Debug, - LogLevel::Trace => LevelFilter::Trace, - }; - - // Note: logger doesn't seem to pick up thread names. Not a huge loss. - let simplelog_config = ConfigBuilder::new() - .set_time_to_local(true) - .set_location_level(LevelFilter::Off) - .build(); - - TermLogger::init( - level_filter, - simplelog_config, - TerminalMode::Stderr - ).context("Couldn't initialize logger")?; - - aquatic_http::run(config) } \ No newline at end of file diff --git a/aquatic_http/src/lib/config.rs b/aquatic_http/src/lib/config.rs index f0057d6..5b41595 100644 --- a/aquatic_http/src/lib/config.rs +++ b/aquatic_http/src/lib/config.rs @@ -2,24 +2,7 @@ use std::net::SocketAddr; use serde::{Serialize, Deserialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum LogLevel { - Off, - Error, - Warn, - Info, - Debug, - Trace -} - - -impl Default for LogLevel { - fn default() -> Self { - Self::Error - } -} +use aquatic_cli_helpers::LogLevel; #[derive(Clone, Debug, Serialize, Deserialize)] @@ -38,6 +21,13 @@ pub struct Config { } +impl aquatic_cli_helpers::Config for Config { + fn get_log_level(&self) -> Option{ + Some(self.log_level.clone()) + } +} + + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct TlsConfig { diff --git a/aquatic_http_load_test/src/config.rs b/aquatic_http_load_test/src/config.rs index f86804d..899f8bd 100644 --- a/aquatic_http_load_test/src/config.rs +++ b/aquatic_http_load_test/src/config.rs @@ -15,6 +15,9 @@ pub struct Config { } +impl aquatic_cli_helpers::Config for Config {} + + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct NetworkConfig { diff --git a/aquatic_udp/src/lib/config.rs b/aquatic_udp/src/lib/config.rs index 2296dca..ba451be 100644 --- a/aquatic_udp/src/lib/config.rs +++ b/aquatic_udp/src/lib/config.rs @@ -22,6 +22,9 @@ pub struct Config { } +impl aquatic_cli_helpers::Config for Config {} + + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct NetworkConfig { diff --git a/aquatic_udp_bench/src/config.rs b/aquatic_udp_bench/src/config.rs index a457663..0f9e112 100644 --- a/aquatic_udp_bench/src/config.rs +++ b/aquatic_udp_bench/src/config.rs @@ -23,4 +23,7 @@ impl Default for BenchConfig { num_hashes_per_scrape_request: 20, } } -} \ No newline at end of file +} + + +impl aquatic_cli_helpers::Config for BenchConfig {} \ No newline at end of file diff --git a/aquatic_udp_load_test/src/main.rs b/aquatic_udp_load_test/src/main.rs index a01f9b3..a70df74 100644 --- a/aquatic_udp_load_test/src/main.rs +++ b/aquatic_udp_load_test/src/main.rs @@ -32,6 +32,9 @@ pub fn main(){ } +impl aquatic_cli_helpers::Config for Config {} + + fn run(config: Config) -> ::anyhow::Result<()> { if config.handler.weight_announce + config.handler.weight_connect + config.handler.weight_scrape == 0 { panic!("Error: at least one weight must be larger than zero."); diff --git a/aquatic_ws/Cargo.toml b/aquatic_ws/Cargo.toml index f4c3a40..36594da 100644 --- a/aquatic_ws/Cargo.toml +++ b/aquatic_ws/Cargo.toml @@ -31,7 +31,6 @@ privdrop = "0.3" rand = { version = "0.7", features = ["small_rng"] } serde = { version = "1", features = ["derive"] } socket2 = { version = "0.3", features = ["reuseport"] } -simplelog = "0.8" tungstenite = "0.11" [dev-dependencies] diff --git a/aquatic_ws/src/bin/main.rs b/aquatic_ws/src/bin/main.rs index cf958f2..1750f60 100644 --- a/aquatic_ws/src/bin/main.rs +++ b/aquatic_ws/src/bin/main.rs @@ -1,8 +1,5 @@ -use anyhow::Context; use aquatic_cli_helpers::run_app_with_cli_and_config; -use simplelog::{ConfigBuilder, LevelFilter, TermLogger, TerminalMode}; - -use aquatic_ws::config::{Config, LogLevel}; +use aquatic_ws::config::Config; #[global_allocator] @@ -12,32 +9,6 @@ static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; fn main(){ run_app_with_cli_and_config::( "aquatic: webtorrent tracker", - run + aquatic_ws::run ) -} - - -fn run(config: Config) -> anyhow::Result<()> { - let level_filter = match config.log_level { - LogLevel::Off => LevelFilter::Off, - LogLevel::Error => LevelFilter::Error, - LogLevel::Warn => LevelFilter::Warn, - LogLevel::Info => LevelFilter::Info, - LogLevel::Debug => LevelFilter::Debug, - LogLevel::Trace => LevelFilter::Trace, - }; - - // Note: logger doesn't seem to pick up thread names. Not a huge loss. - let simplelog_config = ConfigBuilder::new() - .set_time_to_local(true) - .set_location_level(LevelFilter::Off) - .build(); - - TermLogger::init( - level_filter, - simplelog_config, - TerminalMode::Stderr - ).context("Couldn't initialize logger")?; - - aquatic_ws::run(config) } \ No newline at end of file diff --git a/aquatic_ws/src/lib/config.rs b/aquatic_ws/src/lib/config.rs index 38c4c23..b890db7 100644 --- a/aquatic_ws/src/lib/config.rs +++ b/aquatic_ws/src/lib/config.rs @@ -2,24 +2,7 @@ use std::net::SocketAddr; use serde::{Serialize, Deserialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "lowercase")] -pub enum LogLevel { - Off, - Error, - Warn, - Info, - Debug, - Trace -} - - -impl Default for LogLevel { - fn default() -> Self { - Self::Error - } -} +use aquatic_cli_helpers::LogLevel; #[derive(Clone, Debug, Serialize, Deserialize)] @@ -38,6 +21,13 @@ pub struct Config { } +impl aquatic_cli_helpers::Config for Config { + fn get_log_level(&self) -> Option { + Some(self.log_level.clone()) + } +} + + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct NetworkConfig { diff --git a/aquatic_ws_load_test/src/config.rs b/aquatic_ws_load_test/src/config.rs index 2caff37..9ebd547 100644 --- a/aquatic_ws_load_test/src/config.rs +++ b/aquatic_ws_load_test/src/config.rs @@ -15,6 +15,9 @@ pub struct Config { } +impl aquatic_cli_helpers::Config for Config {} + + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct NetworkConfig {