diff --git a/.gitignore b/.gitignore index 1d9fd55..6a3af20 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ Cargo.lock *.alerts *.log *.seclog +*.gz +*.zip link_to_log link_to_mt_log log_files diff --git a/Cargo.toml b/Cargo.toml index ad70fb9..e44f780 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,5 +46,5 @@ libc = {version = "^0.2.50", optional = true} [dev-dependencies] serde_derive = "1.0" -version-sync = "0.8" +version-sync = "0.9" #env_logger = '*' # optionally needed for the performance example \ No newline at end of file diff --git a/src/flexi_error.rs b/src/flexi_error.rs index ce170bb..63f2425 100644 --- a/src/flexi_error.rs +++ b/src/flexi_error.rs @@ -1,5 +1,4 @@ use crate::log_specification::LogSpecification; -use log; // use std::backtrace::Backtrace; use thiserror::Error; diff --git a/src/flexi_logger.rs b/src/flexi_logger.rs index 112f010..32cb154 100644 --- a/src/flexi_logger.rs +++ b/src/flexi_logger.rs @@ -2,7 +2,6 @@ use crate::primary_writer::PrimaryWriter; use crate::writers::LogWriter; use crate::LogSpecification; -use log; #[cfg(feature = "textfilter")] use regex::Regex; use std::collections::HashMap; diff --git a/src/logger.rs b/src/logger.rs index 06135f5..b7a4bf8 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -517,7 +517,22 @@ impl Logger { /// # Errors /// /// Several variants of `FlexiLoggerError` can occur. - pub fn start(mut self) -> Result { + pub fn start(self) -> Result { + let (boxed_logger, handle) = self.build()?; + log::set_boxed_logger(boxed_logger)?; + Ok(handle) + } + + /// Consumes the Logger object and builds a boxed logger and a `ReconfigurationHandle` for it. + /// + /// The returned reconfiguration handle allows updating the log specification programmatically + /// later on, e.g. to intensify logging for (buggy) parts of a (test) program, etc. + /// See [`ReconfigurationHandle`](struct.ReconfigurationHandle.html) for an example. + /// + /// # Errors + /// + /// Several variants of `FlexiLoggerError` can occur. + pub fn build(mut self) -> Result<(Box, ReconfigurationHandle), FlexiLoggerError> { let max_level = self.spec.max_level(); let spec = Arc::new(RwLock::new(self.spec)); let other_writers = Arc::new(self.other_writers); @@ -555,10 +570,9 @@ impl Logger { Arc::clone(&other_writers), ); - log::set_boxed_logger(Box::new(flexi_logger))?; let handle = ReconfigurationHandle::new(spec, primary_writer, other_writers); handle.reconfigure(max_level); - Ok(handle) + Ok((Box::new(flexi_logger), handle)) } /// Consumes the Logger object and initializes `flexi_logger` in a way that @@ -628,63 +642,88 @@ impl Logger { specfile: P, ) -> Result { // Make logging work, before caring for the specfile - let mut handle = self.start()?; - let handle2 = handle.clone(); - - let specfile = specfile.as_ref().to_owned(); - synchronize_handle_with_specfile(&mut handle, &specfile)?; + let (boxed_logger, handle) = self.build()?; + log::set_boxed_logger(boxed_logger)?; + setup_specfile(specfile, handle.clone())?; + Ok(handle) + } - // Now that the file exists, we can canonicalize the path - let specfile = specfile - .canonicalize() - .map_err(FlexiLoggerError::SpecfileIo)?; + /// + /// # Errors + /// + /// Several variants of `FlexiLoggerError` can occur. + /// + /// # Returns + /// + /// A `ReconfigurationHandle` is returned, predominantly to allow using its + /// [`shutdown`](struct.ReconfigurationHandle.html#method.shutdown) method. + #[cfg(feature = "specfile")] + pub fn build_with_specfile>( + self, + specfile: P, + ) -> Result<(Box, ReconfigurationHandle), FlexiLoggerError> { + let (boxed_log, handle) = self.build()?; + setup_specfile(specfile, handle.clone())?; + Ok((boxed_log, handle)) + } +} - // Watch the parent folder of the specfile, using debounced events - let (tx, rx) = std::sync::mpsc::channel(); - let debouncing_delay = std::time::Duration::from_millis(1000); - let mut watcher = watcher(tx, debouncing_delay)?; - watcher.watch(&specfile.parent().unwrap(), RecursiveMode::NonRecursive)?; - - // in a separate thread, reread the specfile when it was updated - std::thread::Builder::new() - .name("flexi_logger-specfile-watcher".to_string()) - .stack_size(128 * 1024) - .spawn(move || { - let _anchor_for_watcher = watcher; // keep it alive! - loop { - match rx.recv() { - Ok(debounced_event) => { - // println!("got debounced event {:?}", debounced_event); - match debounced_event { - DebouncedEvent::Create(ref path) - | DebouncedEvent::Write(ref path) => { - if path.canonicalize().unwrap() == specfile { - match log_spec_string_from_file(&specfile) - .map_err(FlexiLoggerError::SpecfileIo) - .and_then(|s| LogSpecification::from_toml(&s)) - { - Ok(spec) => handle.set_new_spec(spec), - Err(e) => eprintln!( +#[cfg(feature = "specfile")] +fn setup_specfile>( + specfile: P, + mut handle: ReconfigurationHandle, +) -> Result<(), FlexiLoggerError> { + let specfile = specfile.as_ref().to_owned(); + synchronize_handle_with_specfile(&mut handle, &specfile)?; + + // Now that the file exists, we can canonicalize the path + let specfile = specfile + .canonicalize() + .map_err(FlexiLoggerError::SpecfileIo)?; + + // Watch the parent folder of the specfile, using debounced events + let (tx, rx) = std::sync::mpsc::channel(); + let debouncing_delay = std::time::Duration::from_millis(1000); + let mut watcher = watcher(tx, debouncing_delay)?; + watcher.watch(&specfile.parent().unwrap(), RecursiveMode::NonRecursive)?; + + // in a separate thread, reread the specfile when it was updated + std::thread::Builder::new() + .name("flexi_logger-specfile-watcher".to_string()) + .stack_size(128 * 1024) + .spawn(move || { + let _anchor_for_watcher = watcher; // keep it alive! + loop { + match rx.recv() { + Ok(debounced_event) => { + // println!("got debounced event {:?}", debounced_event); + match debounced_event { + DebouncedEvent::Create(ref path) | DebouncedEvent::Write(ref path) => { + if path.canonicalize().unwrap() == specfile { + match log_spec_string_from_file(&specfile) + .map_err(FlexiLoggerError::SpecfileIo) + .and_then(|s| LogSpecification::from_toml(&s)) + { + Ok(spec) => handle.set_new_spec(spec), + Err(e) => eprintln!( "[flexi_logger] rereading the log specification file \ - failed with {:?}, \ - continuing with previous log specification", + failed with {:?}, \ + continuing with previous log specification", e ), - } } } - _event => {} } + _event => {} } - Err(e) => { - eprintln!("[flexi_logger] error while watching the specfile: {:?}", e) - } + } + Err(e) => { + eprintln!("[flexi_logger] error while watching the specfile: {:?}", e) } } - })?; - - Ok(handle2) - } + } + })?; + Ok(()) } // If the specfile exists, read the file and update the log_spec from it; diff --git a/src/reconfiguration_handle.rs b/src/reconfiguration_handle.rs index 077891e..8984bd5 100644 --- a/src/reconfiguration_handle.rs +++ b/src/reconfiguration_handle.rs @@ -1,7 +1,6 @@ use crate::log_specification::LogSpecification; use crate::primary_writer::PrimaryWriter; use crate::writers::LogWriter; -use std::borrow::Borrow; use std::collections::HashMap; use std::sync::{Arc, RwLock}; @@ -153,6 +152,6 @@ impl ReconfigurationHandle { // Allows checking the logs written so far to the writer #[doc(hidden)] pub fn validate_logs(&self, expected: &[(&'static str, &'static str, &'static str)]) { - Borrow::::borrow(&self.primary_writer).validate_logs(expected) + self.primary_writer.validate_logs(expected) } }