From 27bb3e59f85abed728834261c3a0ab5454809d6f Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Mon, 6 Mar 2023 00:05:51 -0500 Subject: [PATCH 01/16] Add internal/external log levels --- cursive-core/Cargo.toml | 2 +- cursive-core/src/logger.rs | 83 +++++++++++++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/cursive-core/Cargo.toml b/cursive-core/Cargo.toml index 80bb55bb..7075d409 100644 --- a/cursive-core/Cargo.toml +++ b/cursive-core/Cargo.toml @@ -24,7 +24,7 @@ repository = "gyscos/cursive" [dependencies] enum-map = "2.0" enumset = "1.0.4" -log = "0.4" +log = { version = "0.4", features = ["std"] } owning_ref = "0.4" unicode-segmentation = "1" unicode-width = "0.1" diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 0fea40f9..3cabda82 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -7,9 +7,69 @@ use std::sync::Mutex; /// Saves all log records in a global deque. /// /// Uses a `DebugView` to access it. -pub struct CursiveLogger; +pub struct CursiveLogger { + /// Log filter level for log messages from within cursive + int_filter_level: log::LevelFilter, + /// Log filter level for log messages from sources outside of cursive + ext_filter_level: log::LevelFilter, +} + +fn get_env_log_level(env_var_name: &str) -> Option { + match std::env::var(env_var_name) { + Ok(mut log_level_str) => { + log_level_str.make_ascii_uppercase(); + match log_level_str { + level if level == "TRACE" => Some(log::LevelFilter::Trace), + level if level == "DEBUG" => Some(log::LevelFilter::Debug), + level if level == "INFO" => Some(log::LevelFilter::Info), + level if level == "WARN" => Some(log::LevelFilter::Warn), + level if level == "ERROR" => Some(log::LevelFilter::Error), + _ => None, + } + } + Err(_) => None, + } +} -static LOGGER: CursiveLogger = CursiveLogger; +impl CursiveLogger { + /// Creates a new CursiveLogger with default log filter levels of log::LevelFilter::Trace + /// If RUST_LOG is set, then both internal and external log levels are set to match + /// If CURSIVE_LOG is set, then the internal log level is set to match + /// Remember to call `init()` to install with `log` backend + pub fn new() -> Self { + let mut logger = CursiveLogger { + int_filter_level: log::LevelFilter::Trace, + ext_filter_level: log::LevelFilter::Trace, + }; + if let Some(filter_level) = get_env_log_level("RUST_LOG") { + logger.int_filter_level = filter_level; + logger.ext_filter_level = filter_level; + } + if let Some(filter_level) = get_env_log_level("CURSIVE_LOG") { + logger.int_filter_level = filter_level; + } + logger + } + + /// sets the internal log filter level + pub fn with_int_filter_level(mut self, level: log::LevelFilter) -> Self { + self.int_filter_level = level; + self + } + + /// sets the external log filter level + pub fn with_ext_filter_level(mut self, level: log::LevelFilter) -> Self { + self.ext_filter_level = level; + self + } + + /// installs the logger with log + /// calling twice will panic + pub fn init(self) { + log::set_boxed_logger(Box::new(self)).unwrap(); + log::set_max_level(log::LevelFilter::Trace); + } +} /// A log record. pub struct Record { @@ -44,12 +104,18 @@ pub fn log(record: &log::Record) { } impl log::Log for CursiveLogger { - fn enabled(&self, _metadata: &log::Metadata) -> bool { - true + fn enabled(&self, metadata: &log::Metadata) -> bool { + if metadata.target().contains("cursive_core") { + metadata.level() <= self.int_filter_level + } else { + metadata.level() <= self.ext_filter_level + } } fn log(&self, record: &log::Record) { - log(record); + if self.enabled(record.metadata()) { + log(record); + } } fn flush(&self) {} @@ -66,10 +132,7 @@ pub fn init() { reserve_logs(1_000); // This will panic if `set_logger` was already called. - log::set_logger(&LOGGER).unwrap(); - - // TODO: read the level from env variable? From argument? - log::set_max_level(log::LevelFilter::Trace); + CursiveLogger::new().init(); } /// Return a logger that stores records in cursive's log queue. @@ -79,7 +142,7 @@ pub fn init() { /// An easier alternative might be to use [`init()`]. pub fn get_logger() -> CursiveLogger { reserve_logs(1_000); - CursiveLogger + CursiveLogger::new() } /// Adds `n` more entries to cursive's log queue. From 166e12674bbb63fecc5c5ca4b524e6b464159529 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Mon, 6 Mar 2023 00:55:38 -0500 Subject: [PATCH 02/16] Add variable log queue size --- cursive-core/src/logger.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 3cabda82..9fc0137c 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -12,6 +12,8 @@ pub struct CursiveLogger { int_filter_level: log::LevelFilter, /// Log filter level for log messages from sources outside of cursive ext_filter_level: log::LevelFilter, + /// Size of log queue + log_size: usize } fn get_env_log_level(env_var_name: &str) -> Option { @@ -40,6 +42,7 @@ impl CursiveLogger { let mut logger = CursiveLogger { int_filter_level: log::LevelFilter::Trace, ext_filter_level: log::LevelFilter::Trace, + log_size: 1000, }; if let Some(filter_level) = get_env_log_level("RUST_LOG") { logger.int_filter_level = filter_level; @@ -63,9 +66,16 @@ impl CursiveLogger { self } + /// sets the size of the log queue + pub fn with_log_size(mut self, log_size: usize) -> Self { + self.log_size = log_size; + self + } + /// installs the logger with log /// calling twice will panic pub fn init(self) { + reserve_logs(self.log_size); log::set_boxed_logger(Box::new(self)).unwrap(); log::set_max_level(log::LevelFilter::Trace); } @@ -128,9 +138,6 @@ impl log::Log for CursiveLogger { /// Use a [`DebugView`](crate::views::DebugView) to see the logs, or use /// [`Cursive::toggle_debug_console()`](crate::Cursive::toggle_debug_console()). pub fn init() { - // TODO: Configure the deque size? - reserve_logs(1_000); - // This will panic if `set_logger` was already called. CursiveLogger::new().init(); } @@ -141,7 +148,6 @@ pub fn init() { /// /// An easier alternative might be to use [`init()`]. pub fn get_logger() -> CursiveLogger { - reserve_logs(1_000); CursiveLogger::new() } From 3af4e6d3af39b1642e1a5948c5dd1f8f8dd18fe6 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Mon, 6 Mar 2023 01:07:03 -0500 Subject: [PATCH 03/16] Remove changes to Cargo.toml --- cursive-core/Cargo.toml | 2 +- cursive-core/src/logger.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cursive-core/Cargo.toml b/cursive-core/Cargo.toml index 7075d409..80bb55bb 100644 --- a/cursive-core/Cargo.toml +++ b/cursive-core/Cargo.toml @@ -24,7 +24,7 @@ repository = "gyscos/cursive" [dependencies] enum-map = "2.0" enumset = "1.0.4" -log = { version = "0.4", features = ["std"] } +log = "0.4" owning_ref = "0.4" unicode-segmentation = "1" unicode-width = "0.1" diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 9fc0137c..8d32dbd1 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -76,7 +76,7 @@ impl CursiveLogger { /// calling twice will panic pub fn init(self) { reserve_logs(self.log_size); - log::set_boxed_logger(Box::new(self)).unwrap(); + log::set_logger(Box::leak(Box::new(self))).unwrap(); log::set_max_level(log::LevelFilter::Trace); } } From 22b6b8df7730d769baa36201e7b505edc5dbcb31 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Mon, 6 Mar 2023 01:55:59 -0500 Subject: [PATCH 04/16] Make env var based logging opt-in --- cursive-core/src/logger.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 8d32dbd1..3ed5bb99 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -39,19 +39,11 @@ impl CursiveLogger { /// If CURSIVE_LOG is set, then the internal log level is set to match /// Remember to call `init()` to install with `log` backend pub fn new() -> Self { - let mut logger = CursiveLogger { + CursiveLogger { int_filter_level: log::LevelFilter::Trace, ext_filter_level: log::LevelFilter::Trace, log_size: 1000, - }; - if let Some(filter_level) = get_env_log_level("RUST_LOG") { - logger.int_filter_level = filter_level; - logger.ext_filter_level = filter_level; - } - if let Some(filter_level) = get_env_log_level("CURSIVE_LOG") { - logger.int_filter_level = filter_level; } - logger } /// sets the internal log filter level @@ -66,6 +58,18 @@ impl CursiveLogger { self } + /// sets log filter levels based on environment variables `RUST_LOG` and `CURSIVE_LOG` + pub fn with_env(mut self) -> Self { + if let Some(filter_level) = get_env_log_level("RUST_LOG") { + self.int_filter_level = filter_level; + self.ext_filter_level = filter_level; + } + if let Some(filter_level) = get_env_log_level("CURSIVE_LOG") { + self.int_filter_level = filter_level; + } + self + } + /// sets the size of the log queue pub fn with_log_size(mut self, log_size: usize) -> Self { self.log_size = log_size; From ff0993dcebf6cae98be2b5fdaddb014a1477d518 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 14:11:02 -0500 Subject: [PATCH 05/16] Add examples --- cursive-core/src/logger.rs | 57 +++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 3ed5bb99..9a3e8291 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -7,12 +7,43 @@ use std::sync::Mutex; /// Saves all log records in a global deque. /// /// Uses a `DebugView` to access it. +/// +/// # Examples +/// +/// Set log levels from env vars +/// +/// ``` +/// # use cursive_core::logger::CursiveLogger; +/// CursiveLogger::new() +/// .with_env() +/// .init(); +/// ``` +/// +/// Set log levels explicitly. +/// +/// ``` +/// # use cursive_core::logger::CursiveLogger; +/// # use log::LevelFilter; +/// CursiveLogger::new() +/// .with_int_filter_level(LevelFilter::Warn) +/// .with_ext_filter_level(LevelFilter::Debug) +/// .init(); +/// ``` +/// +/// Set log queue size. +/// +/// ``` +/// # use cursive_core::logger::CursiveLogger; +/// CursiveLogger::new() +/// .with_log_size(10_000) +/// .init(); +/// ``` pub struct CursiveLogger { - /// Log filter level for log messages from within cursive + // Log filter level for log messages from within cursive int_filter_level: log::LevelFilter, - /// Log filter level for log messages from sources outside of cursive + // Log filter level for log messages from sources outside of cursive ext_filter_level: log::LevelFilter, - /// Size of log queue + // Size of log queue log_size: usize } @@ -34,10 +65,8 @@ fn get_env_log_level(env_var_name: &str) -> Option { } impl CursiveLogger { - /// Creates a new CursiveLogger with default log filter levels of log::LevelFilter::Trace - /// If RUST_LOG is set, then both internal and external log levels are set to match - /// If CURSIVE_LOG is set, then the internal log level is set to match - /// Remember to call `init()` to install with `log` backend + /// Creates a new CursiveLogger with default log filter levels of `log::LevelFilter::Trace`. + /// Remember to call `init()` to install with `log` backend. pub fn new() -> Self { CursiveLogger { int_filter_level: log::LevelFilter::Trace, @@ -46,19 +75,22 @@ impl CursiveLogger { } } - /// sets the internal log filter level + /// Sets the internal log filter level. pub fn with_int_filter_level(mut self, level: log::LevelFilter) -> Self { self.int_filter_level = level; self } - /// sets the external log filter level + /// Sets the external log filter level. pub fn with_ext_filter_level(mut self, level: log::LevelFilter) -> Self { self.ext_filter_level = level; self } - /// sets log filter levels based on environment variables `RUST_LOG` and `CURSIVE_LOG` + /// Sets log filter levels based on environment variables `RUST_LOG` and `CURSIVE_LOG`. + /// If `RUST_LOG` is set, then both internal and external log levels are set to match. + /// If `CURSIVE_LOG` is set, then the internal log level is set to match with precedence over + /// `RUST_LOG`. pub fn with_env(mut self) -> Self { if let Some(filter_level) = get_env_log_level("RUST_LOG") { self.int_filter_level = filter_level; @@ -70,14 +102,13 @@ impl CursiveLogger { self } - /// sets the size of the log queue + /// Sets the size of the log queue pub fn with_log_size(mut self, log_size: usize) -> Self { self.log_size = log_size; self } - /// installs the logger with log - /// calling twice will panic + /// Installs the logger with log. Calling twice will panic. pub fn init(self) { reserve_logs(self.log_size); log::set_logger(Box::leak(Box::new(self))).unwrap(); From f60e59114754ba785a79b242a2a36c8084a9eb09 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 14:31:07 -0500 Subject: [PATCH 06/16] Use LevelFilter from_str for parsing env vars --- cursive-core/src/logger.rs | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 9a3e8291..0a903e55 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -3,6 +3,7 @@ use lazy_static::lazy_static; use std::collections::VecDeque; use std::sync::Mutex; +use std::str::FromStr; /// Saves all log records in a global deque. /// @@ -47,23 +48,6 @@ pub struct CursiveLogger { log_size: usize } -fn get_env_log_level(env_var_name: &str) -> Option { - match std::env::var(env_var_name) { - Ok(mut log_level_str) => { - log_level_str.make_ascii_uppercase(); - match log_level_str { - level if level == "TRACE" => Some(log::LevelFilter::Trace), - level if level == "DEBUG" => Some(log::LevelFilter::Debug), - level if level == "INFO" => Some(log::LevelFilter::Info), - level if level == "WARN" => Some(log::LevelFilter::Warn), - level if level == "ERROR" => Some(log::LevelFilter::Error), - _ => None, - } - } - Err(_) => None, - } -} - impl CursiveLogger { /// Creates a new CursiveLogger with default log filter levels of `log::LevelFilter::Trace`. /// Remember to call `init()` to install with `log` backend. @@ -92,12 +76,16 @@ impl CursiveLogger { /// If `CURSIVE_LOG` is set, then the internal log level is set to match with precedence over /// `RUST_LOG`. pub fn with_env(mut self) -> Self { - if let Some(filter_level) = get_env_log_level("RUST_LOG") { - self.int_filter_level = filter_level; - self.ext_filter_level = filter_level; + if let Ok(rust_log) = std::env::var("RUST_LOG") { + if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { + self.int_filter_level = filter_level; + self.ext_filter_level = filter_level; + } } - if let Some(filter_level) = get_env_log_level("CURSIVE_LOG") { - self.int_filter_level = filter_level; + if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") { + if let Ok(filter_level) = log::LevelFilter::from_str(&cursive_log) { + self.int_filter_level = filter_level; + } } self } From 3bfc0862582f28ad2558395f53e4789b886d3112 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 15:06:08 -0500 Subject: [PATCH 07/16] rustfmt --- cursive-core/src/logger.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 0a903e55..ad01ce5b 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -2,8 +2,8 @@ use lazy_static::lazy_static; use std::collections::VecDeque; -use std::sync::Mutex; use std::str::FromStr; +use std::sync::Mutex; /// Saves all log records in a global deque. /// @@ -45,7 +45,7 @@ pub struct CursiveLogger { // Log filter level for log messages from sources outside of cursive ext_filter_level: log::LevelFilter, // Size of log queue - log_size: usize + log_size: usize, } impl CursiveLogger { From ca1950c73bd216069c718de98042821c3d3e6372 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 17:11:41 -0500 Subject: [PATCH 08/16] set_max_level based on max int/ext log level --- cursive-core/src/logger.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index ad01ce5b..e7b1ee5a 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -1,6 +1,7 @@ //! Logging utilities. use lazy_static::lazy_static; +use std::cmp::Ord; use std::collections::VecDeque; use std::str::FromStr; use std::sync::Mutex; @@ -99,8 +100,8 @@ impl CursiveLogger { /// Installs the logger with log. Calling twice will panic. pub fn init(self) { reserve_logs(self.log_size); + log::set_max_level(self.int_filter_level.max(self.ext_filter_level)); log::set_logger(Box::leak(Box::new(self))).unwrap(); - log::set_max_level(log::LevelFilter::Trace); } } From 27701bd2884d9903b2b0115ad24db21f54537310 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 17:31:44 -0500 Subject: [PATCH 09/16] changed int/ext to prefix based --- cursive-core/src/logger.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index e7b1ee5a..a1479abb 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -139,7 +139,7 @@ pub fn log(record: &log::Record) { impl log::Log for CursiveLogger { fn enabled(&self, metadata: &log::Metadata) -> bool { - if metadata.target().contains("cursive_core") { + if metadata.target().starts_with("cursive_core::") { metadata.level() <= self.int_filter_level } else { metadata.level() <= self.ext_filter_level From beb860df5af25fe987838c55ea9b30fbaa541238 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 7 Mar 2023 19:30:07 -0500 Subject: [PATCH 10/16] Use set_boxed_logger (requires log `std` feature) --- cursive-core/Cargo.toml | 2 +- cursive-core/src/logger.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cursive-core/Cargo.toml b/cursive-core/Cargo.toml index 80bb55bb..7075d409 100644 --- a/cursive-core/Cargo.toml +++ b/cursive-core/Cargo.toml @@ -24,7 +24,7 @@ repository = "gyscos/cursive" [dependencies] enum-map = "2.0" enumset = "1.0.4" -log = "0.4" +log = { version = "0.4", features = ["std"] } owning_ref = "0.4" unicode-segmentation = "1" unicode-width = "0.1" diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index a1479abb..af73d9d5 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -101,7 +101,7 @@ impl CursiveLogger { pub fn init(self) { reserve_logs(self.log_size); log::set_max_level(self.int_filter_level.max(self.ext_filter_level)); - log::set_logger(Box::leak(Box::new(self))).unwrap(); + log::set_boxed_logger(Box::new(self)).unwrap(); } } From c8f9744b1e4bb532522e4bd3827e4b97965ba336 Mon Sep 17 00:00:00 2001 From: blaisdellma <69583321+blaisdellma@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:47:34 -0500 Subject: [PATCH 11/16] Make CursiveLogger use global state (#1) * Make CursiveLogger use globals * Avoid duplicate log queue reservations * Check log queue size on init, get rid of `LOG_SIZE` --- cursive-core/Cargo.toml | 2 +- cursive-core/src/logger.rs | 125 ++++++++++++++----------------------- 2 files changed, 49 insertions(+), 78 deletions(-) diff --git a/cursive-core/Cargo.toml b/cursive-core/Cargo.toml index 7075d409..80bb55bb 100644 --- a/cursive-core/Cargo.toml +++ b/cursive-core/Cargo.toml @@ -24,7 +24,7 @@ repository = "gyscos/cursive" [dependencies] enum-map = "2.0" enumset = "1.0.4" -log = { version = "0.4", features = ["std"] } +log = "0.4" owning_ref = "0.4" unicode-segmentation = "1" unicode-width = "0.1" diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index af73d9d5..f82a7b1b 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -4,7 +4,7 @@ use lazy_static::lazy_static; use std::cmp::Ord; use std::collections::VecDeque; use std::str::FromStr; -use std::sync::Mutex; +use std::sync::{Mutex, RwLock}; /// Saves all log records in a global deque. /// @@ -15,93 +15,55 @@ use std::sync::Mutex; /// Set log levels from env vars /// /// ``` -/// # use cursive_core::logger::CursiveLogger; -/// CursiveLogger::new() -/// .with_env() -/// .init(); +/// # use cursive_core::*; +/// logger::set_filter_levels_with_env(); +/// logger::init(); /// ``` /// /// Set log levels explicitly. /// /// ``` -/// # use cursive_core::logger::CursiveLogger; +/// # use cursive_core::*; /// # use log::LevelFilter; -/// CursiveLogger::new() -/// .with_int_filter_level(LevelFilter::Warn) -/// .with_ext_filter_level(LevelFilter::Debug) -/// .init(); +/// logger::set_int_filter_level(LevelFilter::Warn); +/// logger::set_ext_filter_level(LevelFilter::Debug); +/// logger::init(); /// ``` -/// -/// Set log queue size. -/// -/// ``` -/// # use cursive_core::logger::CursiveLogger; -/// CursiveLogger::new() -/// .with_log_size(10_000) -/// .init(); -/// ``` -pub struct CursiveLogger { + +pub struct CursiveLogger; + +lazy_static! { // Log filter level for log messages from within cursive - int_filter_level: log::LevelFilter, + static ref INT_FILTER_LEVEL: RwLock = RwLock::new(log::LevelFilter::Trace); // Log filter level for log messages from sources outside of cursive - ext_filter_level: log::LevelFilter, - // Size of log queue - log_size: usize, + static ref EXT_FILTER_LEVEL: RwLock = RwLock::new(log::LevelFilter::Trace); } -impl CursiveLogger { - /// Creates a new CursiveLogger with default log filter levels of `log::LevelFilter::Trace`. - /// Remember to call `init()` to install with `log` backend. - pub fn new() -> Self { - CursiveLogger { - int_filter_level: log::LevelFilter::Trace, - ext_filter_level: log::LevelFilter::Trace, - log_size: 1000, - } - } - - /// Sets the internal log filter level. - pub fn with_int_filter_level(mut self, level: log::LevelFilter) -> Self { - self.int_filter_level = level; - self - } +/// Sets the internal log filter level. +pub fn set_int_filter_level(level: log::LevelFilter) { + *INT_FILTER_LEVEL.write().unwrap() = level; +} - /// Sets the external log filter level. - pub fn with_ext_filter_level(mut self, level: log::LevelFilter) -> Self { - self.ext_filter_level = level; - self - } +/// Sets the external log filter level. +pub fn set_ext_filter_level(level: log::LevelFilter) { + *EXT_FILTER_LEVEL.write().unwrap() = level; +} - /// Sets log filter levels based on environment variables `RUST_LOG` and `CURSIVE_LOG`. - /// If `RUST_LOG` is set, then both internal and external log levels are set to match. - /// If `CURSIVE_LOG` is set, then the internal log level is set to match with precedence over - /// `RUST_LOG`. - pub fn with_env(mut self) -> Self { - if let Ok(rust_log) = std::env::var("RUST_LOG") { - if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { - self.int_filter_level = filter_level; - self.ext_filter_level = filter_level; - } +/// Sets log filter levels based on environment variables `RUST_LOG` and `CURSIVE_LOG`. +/// If `RUST_LOG` is set, then both internal and external log levels are set to match. +/// If `CURSIVE_LOG` is set, then the internal log level is set to match with precedence over +/// `RUST_LOG`. +pub fn set_filter_levels_with_env() { + if let Ok(rust_log) = std::env::var("RUST_LOG") { + if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { + set_int_filter_level(filter_level); + set_ext_filter_level(filter_level); } - if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") { - if let Ok(filter_level) = log::LevelFilter::from_str(&cursive_log) { - self.int_filter_level = filter_level; - } - } - self - } - - /// Sets the size of the log queue - pub fn with_log_size(mut self, log_size: usize) -> Self { - self.log_size = log_size; - self } - - /// Installs the logger with log. Calling twice will panic. - pub fn init(self) { - reserve_logs(self.log_size); - log::set_max_level(self.int_filter_level.max(self.ext_filter_level)); - log::set_boxed_logger(Box::new(self)).unwrap(); + if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") { + if let Ok(filter_level) = log::LevelFilter::from_str(&cursive_log) { + set_int_filter_level(filter_level); + } } } @@ -140,9 +102,9 @@ pub fn log(record: &log::Record) { impl log::Log for CursiveLogger { fn enabled(&self, metadata: &log::Metadata) -> bool { if metadata.target().starts_with("cursive_core::") { - metadata.level() <= self.int_filter_level + metadata.level() <= *INT_FILTER_LEVEL.read().unwrap() } else { - metadata.level() <= self.ext_filter_level + metadata.level() <= *EXT_FILTER_LEVEL.read().unwrap() } } @@ -162,8 +124,13 @@ impl log::Log for CursiveLogger { /// Use a [`DebugView`](crate::views::DebugView) to see the logs, or use /// [`Cursive::toggle_debug_console()`](crate::Cursive::toggle_debug_console()). pub fn init() { + // ensure that the log queue capacity has been set + if LOGS.lock().unwrap().capacity() == 0 { + reserve_logs(1_000); + } + log::set_max_level((*INT_FILTER_LEVEL.read().unwrap()).max(*EXT_FILTER_LEVEL.read().unwrap())); // This will panic if `set_logger` was already called. - CursiveLogger::new().init(); + log::set_logger(&CursiveLogger).unwrap(); } /// Return a logger that stores records in cursive's log queue. @@ -172,7 +139,11 @@ pub fn init() { /// /// An easier alternative might be to use [`init()`]. pub fn get_logger() -> CursiveLogger { - CursiveLogger::new() + // ensure that the log queue capacity has been set + if LOGS.lock().unwrap().capacity() == 0 { + reserve_logs(1_000); + } + CursiveLogger } /// Adds `n` more entries to cursive's log queue. From 2c54e4f4b2bc58ad71210c901717dc32168f26b3 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 28 Mar 2023 10:16:04 -0400 Subject: [PATCH 12/16] Changed to `set_filter_levels_from_env()` --- cursive-core/src/logger.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index f82a7b1b..77797997 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -16,7 +16,7 @@ use std::sync::{Mutex, RwLock}; /// /// ``` /// # use cursive_core::*; -/// logger::set_filter_levels_with_env(); +/// logger::set_filter_levels_from_env(); /// logger::init(); /// ``` /// @@ -53,7 +53,7 @@ pub fn set_ext_filter_level(level: log::LevelFilter) { /// If `RUST_LOG` is set, then both internal and external log levels are set to match. /// If `CURSIVE_LOG` is set, then the internal log level is set to match with precedence over /// `RUST_LOG`. -pub fn set_filter_levels_with_env() { +pub fn set_filter_levels_from_env() { if let Ok(rust_log) = std::env::var("RUST_LOG") { if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { set_int_filter_level(filter_level); From 6bf3d4a35339dfa3cae1870fafb0d8e784c974bb Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 28 Mar 2023 10:18:59 -0400 Subject: [PATCH 13/16] Expanded fn names from int/ext to internal/external --- cursive-core/src/logger.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 77797997..38785cdd 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -25,8 +25,8 @@ use std::sync::{Mutex, RwLock}; /// ``` /// # use cursive_core::*; /// # use log::LevelFilter; -/// logger::set_int_filter_level(LevelFilter::Warn); -/// logger::set_ext_filter_level(LevelFilter::Debug); +/// logger::set_internal_filter_level(LevelFilter::Warn); +/// logger::set_external_filter_level(LevelFilter::Debug); /// logger::init(); /// ``` @@ -40,12 +40,12 @@ lazy_static! { } /// Sets the internal log filter level. -pub fn set_int_filter_level(level: log::LevelFilter) { +pub fn set_internal_filter_level(level: log::LevelFilter) { *INT_FILTER_LEVEL.write().unwrap() = level; } /// Sets the external log filter level. -pub fn set_ext_filter_level(level: log::LevelFilter) { +pub fn set_external_filter_level(level: log::LevelFilter) { *EXT_FILTER_LEVEL.write().unwrap() = level; } @@ -56,13 +56,13 @@ pub fn set_ext_filter_level(level: log::LevelFilter) { pub fn set_filter_levels_from_env() { if let Ok(rust_log) = std::env::var("RUST_LOG") { if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { - set_int_filter_level(filter_level); - set_ext_filter_level(filter_level); + set_internal_filter_level(filter_level); + set_external_filter_level(filter_level); } } if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") { if let Ok(filter_level) = log::LevelFilter::from_str(&cursive_log) { - set_int_filter_level(filter_level); + set_internal_filter_level(filter_level); } } } From 934ac2f5dabc386c8faab0b026795f3509a3207e Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 28 Mar 2023 10:20:57 -0400 Subject: [PATCH 14/16] Combine lazy_static! --- cursive-core/src/logger.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 38785cdd..f6cc58f5 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -33,6 +33,12 @@ use std::sync::{Mutex, RwLock}; pub struct CursiveLogger; lazy_static! { + /// Circular buffer for logs. Use it to implement [`DebugView`]. + /// + /// [`DebugView`]: ../views/struct.DebugView.html + pub static ref LOGS: Mutex> = + Mutex::new(VecDeque::new()); + // Log filter level for log messages from within cursive static ref INT_FILTER_LEVEL: RwLock = RwLock::new(log::LevelFilter::Trace); // Log filter level for log messages from sources outside of cursive @@ -77,14 +83,6 @@ pub struct Record { pub message: String, } -lazy_static! { - /// Circular buffer for logs. Use it to implement [`DebugView`]. - /// - /// [`DebugView`]: ../views/struct.DebugView.html - pub static ref LOGS: Mutex> = - Mutex::new(VecDeque::new()); -} - /// Log a record in cursive's log queue. pub fn log(record: &log::Record) { let mut logs = LOGS.lock().unwrap(); From e5f365fa25acc4751a3c9f3069c432314d0bc8ee Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 28 Mar 2023 10:25:24 -0400 Subject: [PATCH 15/16] Use `VecDeque::with_capacity()` --- cursive-core/src/logger.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index f6cc58f5..47df6447 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -37,7 +37,7 @@ lazy_static! { /// /// [`DebugView`]: ../views/struct.DebugView.html pub static ref LOGS: Mutex> = - Mutex::new(VecDeque::new()); + Mutex::new(VecDeque::with_capacity(1_000)); // Log filter level for log messages from within cursive static ref INT_FILTER_LEVEL: RwLock = RwLock::new(log::LevelFilter::Trace); @@ -122,10 +122,6 @@ impl log::Log for CursiveLogger { /// Use a [`DebugView`](crate::views::DebugView) to see the logs, or use /// [`Cursive::toggle_debug_console()`](crate::Cursive::toggle_debug_console()). pub fn init() { - // ensure that the log queue capacity has been set - if LOGS.lock().unwrap().capacity() == 0 { - reserve_logs(1_000); - } log::set_max_level((*INT_FILTER_LEVEL.read().unwrap()).max(*EXT_FILTER_LEVEL.read().unwrap())); // This will panic if `set_logger` was already called. log::set_logger(&CursiveLogger).unwrap(); @@ -137,18 +133,12 @@ pub fn init() { /// /// An easier alternative might be to use [`init()`]. pub fn get_logger() -> CursiveLogger { - // ensure that the log queue capacity has been set - if LOGS.lock().unwrap().capacity() == 0 { - reserve_logs(1_000); - } CursiveLogger } /// Adds `n` more entries to cursive's log queue. /// /// Most of the time you don't need to use this directly. -/// -/// You should call this if you're not using `init()` nor `get_logger()`. pub fn reserve_logs(n: usize) { LOGS.lock().unwrap().reserve(n); } From b122ba869cb4a0afaec04d50d2d864e4593384f4 Mon Sep 17 00:00:00 2001 From: Matt Blaisdell Date: Tue, 28 Mar 2023 10:30:17 -0400 Subject: [PATCH 16/16] Warn on failure to parse env vars --- cursive-core/src/logger.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cursive-core/src/logger.rs b/cursive-core/src/logger.rs index 47df6447..642958c7 100644 --- a/cursive-core/src/logger.rs +++ b/cursive-core/src/logger.rs @@ -61,14 +61,20 @@ pub fn set_external_filter_level(level: log::LevelFilter) { /// `RUST_LOG`. pub fn set_filter_levels_from_env() { if let Ok(rust_log) = std::env::var("RUST_LOG") { - if let Ok(filter_level) = log::LevelFilter::from_str(&rust_log) { - set_internal_filter_level(filter_level); - set_external_filter_level(filter_level); + match log::LevelFilter::from_str(&rust_log) { + Ok(filter_level) => { + set_internal_filter_level(filter_level); + set_external_filter_level(filter_level); + } + Err(e) => log::warn!("Could not parse RUST_LOG: {}", e), } } if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") { - if let Ok(filter_level) = log::LevelFilter::from_str(&cursive_log) { - set_internal_filter_level(filter_level); + match log::LevelFilter::from_str(&cursive_log) { + Ok(filter_level) => { + set_internal_filter_level(filter_level); + } + Err(e) => log::warn!("Could not parse CURSIVE_LOG: {}", e), } } }