From c321bbff4ac054fdc1dd542e667b174bcf95d235 Mon Sep 17 00:00:00 2001 From: emabee Date: Sat, 19 Sep 2020 23:56:53 +0200 Subject: [PATCH] [0.16.0] Fix wrong wording and wrong suffix for compressed log files (see issue 65) - deprecate the feature name `ziplog` and call the feature now `compress` - rename `Cleanup::KeepZipFiles` into `Cleanup::KeepCompressedFiles` and `Cleanup::KeepLogAndZipFiles` into `Cleanup::KeepLogAndCompressedFiles` - the old names still work but are deprecated - change the file suffix for the compressed log files from `.zip` to `.gz` --- CHANGELOG.md | 50 ++++++++++++----- Cargo.toml | 5 +- README.md | 21 ++++--- scripts/cleanup.rs | 1 + src/logger.rs | 4 +- src/parameters.rs | 28 +++++---- src/reconfiguration_handle.rs | 4 +- src/writers/file_log_writer/builder.rs | 4 +- src/writers/file_log_writer/state.rs | 78 ++++++++++++++++---------- tests/test_multi_threaded_cleanup.rs | 16 +++--- 10 files changed, 132 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 869b269..16134ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.15.13] - 2020-08-07 +## [0.16.0] - 2020-09-19 + +If file logging is used, do not create the output file if no log is written. +Solves [issue-62](https://github.com/emabee/flexi_logger/issues/62). + +Improve color handling + +- introduce AdaptiveFormat for a clearer API +- Support using feature `atty` without provided coloring +- Extend example `colors` to provide insight in how AdaptiveFormat works +- Remove the deprecated method `Logger::do_not_log()`; use `log_target()` with `LogTarget::DevNull` instead. +- Remove deprecated method `Logger::o_log_to_file()`; use `log_target()` instead. The clearer convenience method `Logger::log_to_file()` is still available. + +Improve the compression feature. Solves [issue-65](https://github.com/emabee/flexi_logger/issues/65). + +- breaking change: change the file suffix for the compressed log files from `.zip` to `.gz` +- Fix wrong wording in code and documentation +- deprecate the feature name `ziplog` and call the feature now `compress` +- rename `Cleanup::KeepZipFiles` into `Cleanup::KeepCompressedFiles` + and `Cleanup::KeepLogAndZipFiles` into `Cleanup::KeepLogAndCompressedFiles` + - the old names still work but are deprecated If file logging is used, do not create the output file if no log is written Solves issue [issue-62](https://github.com/emabee/flexi_logger/issues/62). -## [0.15.12] - 2020-08-07 +## [0.15.12] - 2020-28-08 Make `1.37.0` the minimal rust version for `flexi_logger`. @@ -264,8 +284,8 @@ When file rotation is used, the name of the file to which the logs are written i Details: -* the logs are always written to a file with infix _rCURRENT -* if this file exceeds the specified rotate-over-size, it is closed and renamed +- the logs are always written to a file with infix _rCURRENT +- if this file exceeds the specified rotate-over-size, it is closed and renamed to a file with a sequential number infix, and then the logging continues again to the (fresh) file with infix _rCURRENT @@ -356,10 +376,10 @@ in the auto-generated docu (because it does not use --allfeatures) Add specfile feature -* Add a feature that allows to specify the LogSpecification via a file +- Add a feature that allows to specify the LogSpecification via a file that can be edited while the program is running -* Remove/hide deprecated APIs -* As a consequence, cleanup code, get rid of duplicate stuff. +_ Remove/hide deprecated APIs +- As a consequence, cleanup code, get rid of duplicate stuff. ## [0.7.1] - 2018-03-07 @@ -370,11 +390,11 @@ Update docu and the description in cargo.toml Add support for multiple log output streams -* replace FlexiWriter with DefaultLogWriter, which wraps a FileLogWriter -* add test where a SecurityWriter and an AlertWriter are added -* add docu -* move deprecated structs to separate package -* move benches to folder benches +- replace FlexiWriter with DefaultLogWriter, which wraps a FileLogWriter +- add test where a SecurityWriter and an AlertWriter are added +- add docu +- move deprecated structs to separate package +- move benches to folder benches ## [0.6.13] 2018-02-09 @@ -398,6 +418,6 @@ Publish version based on log 0.4 Use builder pattern for LogSpecification and Logger -* deprecate outdated API -* "objectify" LogSpecification -* improve documentation, e.g. document the dash/underscore issue +- deprecate outdated API +- "objectify" LogSpecification +- improve documentation, e.g. document the dash/underscore issue diff --git a/Cargo.toml b/Cargo.toml index 5ad0d49..889a6d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flexi_logger" -version = "0.16.0-alpha" +version = "0.16.0" authors = ["emabee "] edition = "2018" license = "MIT OR Apache-2.0" @@ -25,7 +25,8 @@ colors = ["atty", "lazy_static","yansi"] specfile = ["specfile_without_notification","notify"] specfile_without_notification = ["serde","toml","serde_derive"] syslog_writer = ["libc", "hostname"] -ziplogs = ["flate2"] +ziplog = ["compress"] # for backwards compatibility +compress = ["flate2"] textfilter = ["regex"] [dependencies] diff --git a/README.md b/README.md index e0e7e19..6922a72 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Add flexi_logger to the dependencies section in your project's `Cargo.toml`, wit ```toml [dependencies] -flexi_logger = "0.15" +flexi_logger = "0.16" log = "0.4" ``` @@ -22,7 +22,7 @@ or, if you want to use some of the optional features, with something like ```toml [dependencies] -flexi_logger = { version = "0.15", features = ["specfile", "ziplogs"] } +flexi_logger = { version = "0.16", features = ["specfile", "compress"] } log = "0.4" ``` @@ -30,7 +30,7 @@ or, to get the smallest footprint (and no colors), with ```toml [dependencies] -flexi_logger = { version = "0.15", default_features = false } +flexi_logger = { version = "0.16", default_features = false } log = "0.4" ``` @@ -146,7 +146,7 @@ The default feature `colors` simplifies this by doing three things: * provides additional colored pendants to the existing uncolored format functions * it uses `colored_default_format()` for the output to stderr, and the non-colored `default_format()` for the output to files -* it activates the optional dependency to `atty` to being able to switch off +* it activates the optional dependency to `atty` to being able to switch off coloring if the output is not sent to a terminal but e.g. piped to another program. **Colors**, @@ -154,6 +154,14 @@ or styles in general, are a matter of taste, and no choice will fit every need. With `--no-default-features --features="atty"` you can remove the yansi-based coloring but keep the capability to switch off your own coloring. +### **`compress`** + +The `compress` feature adds two options to the `Logger::Cleanup` `enum`, which allow keeping some +or all rotated log files in compressed form (`.gz`) rather than as plain text files. + +The feature was previously called `ziplogs`. The old name still works, but is deprecated and +should be replaced. + ### **`specfile`** The `specfile` feature adds a method `Logger::start_with_specfile(specfile)`. @@ -176,11 +184,6 @@ For that reason the feature is not active by default. Pretty much like `specfile`, except that updates to the file are being ignored. See [issue-59](https://github.com/emabee/flexi_logger/issues/59) for more details. -### **`ziplogs`** - -The `ziplogs` feature adds two options to the `Logger::Cleanup` `enum`, which allow keeping some -or all rotated log files in zipped form rather than as text files. - ### **`textfilter`** Removes the ability to filter logs by text, but also removes the dependency on the regex crate. diff --git a/scripts/cleanup.rs b/scripts/cleanup.rs index c309ee9..e867b2d 100644 --- a/scripts/cleanup.rs +++ b/scripts/cleanup.rs @@ -14,6 +14,7 @@ fn main() { "./*logspec.toml", "./log_files/**/*.log", "./log_files/**/*.zip", + "./log_files/**/*.gz", "./test_spec/*.toml", ] { for globresult in glob::glob(pattern).unwrap() { diff --git a/src/logger.rs b/src/logger.rs index 14e5bab..f145bd3 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -393,8 +393,8 @@ impl Logger { } /// When rotation is used with some `Cleanup` variant, then this option defines - /// if the cleanup activities (finding files, deleting files, evtl zipping files) is done in - /// the current thread (in the current log-call), or whether cleanup is delegated to a + /// if the cleanup activities (finding files, deleting files, evtl compressing files) is done + /// in the current thread (in the current log-call), or whether cleanup is delegated to a /// background thread. /// /// As of `flexi_logger` version `0.14.7`, diff --git a/src/parameters.rs b/src/parameters.rs index c3591fb..affed2a 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -96,6 +96,7 @@ pub enum Naming { /// See /// [`Logger::cleanup_in_background_thread`](struct.Logger.html#method.cleanup_in_background_thread) /// if you want to control whether this extra thread is created and used. +#[allow(deprecated)] #[derive(Copy, Clone, Debug)] pub enum Cleanup { /// Older log files are not touched - they remain for ever. @@ -103,23 +104,30 @@ pub enum Cleanup { /// The specified number of rotated log files are kept. /// Older files are deleted, if necessary. KeepLogFiles(usize), - /// The specified number of rotated log files are zipped and kept. + /// The specified number of rotated log files are compressed and kept. /// Older files are deleted, if necessary. /// - /// This option is only available with feature `ziplogs`. - #[cfg(feature = "ziplogs")] + /// This option is only available with feature `compress`. + #[cfg(feature = "compress")] + KeepCompressedFiles(usize), + /// Outdated + #[cfg(feature = "compress")] + #[deprecated(since = "0.16.0", note = "use KeepCompressedFiles instead")] KeepZipFiles(usize), - /// Allows keeping some files as text files and some as zip files. - /// - /// Is used in + /// Allows keeping some files as text files and some as compressed files. /// /// ## Example /// - /// `KeepLogAndZipFiles(5,30)` ensures that the youngest five log files are kept as text files, - /// the next 30 are kept as zip files, and older files are removed. + /// `KeepLogAndCompressedFiles(5,30)` ensures that the youngest five log files are + /// kept as text files, the next 30 are kept as compressed files with additional suffix `.gz`, + /// and older files are removed. /// - /// This option is only available with feature `ziplogs`. - #[cfg(feature = "ziplogs")] + /// This option is only available with feature `compress`. + #[cfg(feature = "compress")] + KeepLogAndCompressedFiles(usize, usize), + /// Outdated + #[deprecated(since = "0.16.0", note = "use KeepLogAndCompressedFiles instead")] + #[cfg(feature = "compress")] KeepLogAndZipFiles(usize, usize), } diff --git a/src/reconfiguration_handle.rs b/src/reconfiguration_handle.rs index 4bc716f..d7454a5 100644 --- a/src/reconfiguration_handle.rs +++ b/src/reconfiguration_handle.rs @@ -134,10 +134,10 @@ impl ReconfigurationHandle { /// /// This method is supposed to be called at the very end of your program, in case you use /// your own writers, or if you want to securely shutdown the cleanup-thread of the - /// `FileLogWriter`. If you use a [`Cleanup`](enum.Cleanup.html) strategy with zipping, + /// `FileLogWriter`. If you use a [`Cleanup`](enum.Cleanup.html) strategy with compressing, /// and your process terminates /// without correctly shutting down the cleanup-thread, then you might stop the cleanup-thread - /// while it is zipping a log file, which can leave unexpected files in the filesystem. + /// while it is compressing a log file, which can leave unexpected files in the filesystem. /// /// See also [`LogWriter::shutdown`](writers/trait.LogWriter.html#method.shutdown). pub fn shutdown(&self) { diff --git a/src/writers/file_log_writer/builder.rs b/src/writers/file_log_writer/builder.rs index 831debe..78c7671 100644 --- a/src/writers/file_log_writer/builder.rs +++ b/src/writers/file_log_writer/builder.rs @@ -71,8 +71,8 @@ impl FileLogWriterBuilder { } /// When rotation is used with some `Cleanup` variant, then this option defines - /// if the cleanup activities (finding files, deleting files, evtl zipping files) is done in - /// the current thread (in the current log-call), or whether cleanup is delegated to a + /// if the cleanup activities (finding files, deleting files, evtl compressing files) is done + /// in the current thread (in the current log-call), or whether cleanup is delegated to a /// background thread. /// /// As of `flexi_logger` version `0.14.7`, diff --git a/src/writers/file_log_writer/state.rs b/src/writers/file_log_writer/state.rs index 40d500c..e0d8a35 100644 --- a/src/writers/file_log_writer/state.rs +++ b/src/writers/file_log_writer/state.rs @@ -200,7 +200,7 @@ impl State { )?; let mut o_cleanup_thread_handle = None; if rotate_config.cleanup.do_cleanup() { - remove_or_zip_too_old_logfiles( + remove_or_compress_too_old_logfiles( &None, &rotate_config.cleanup, &self.config.filename_config, @@ -215,7 +215,7 @@ impl State { .spawn(move || loop { match receiver.recv() { Ok(MessageToCleanupThread::Act) => { - remove_or_zip_too_old_logfiles_impl( + remove_or_compress_too_old_logfiles_impl( &cleanup, &filename_config, ) @@ -282,7 +282,7 @@ impl State { *current_size = 0; } - remove_or_zip_too_old_logfiles( + remove_or_compress_too_old_logfiles( &rotation_state.o_cleanup_thread_handle, &rotation_state.cleanup, &self.config.filename_config, @@ -418,7 +418,7 @@ fn open_log_file( } fn get_highest_rotate_idx(filename_config: &FilenameConfig) -> IdxState { - match list_of_log_and_zip_files(filename_config) { + match list_of_log_and_compressed_files(filename_config) { Err(e) => { eprintln!("[flexi_logger] listing rotated log files failed with {}", e); IdxState::Start // hope and pray ...?? @@ -444,10 +444,17 @@ fn get_highest_rotate_idx(filename_config: &FilenameConfig) -> IdxState { } } -fn list_of_log_and_zip_files( +#[allow(clippy::type_complexity)] +fn list_of_log_and_compressed_files( filename_config: &FilenameConfig, -) -> Result< - std::iter::Chain, std::vec::IntoIter>, +) -> std::result::Result< + std::iter::Chain< + std::iter::Chain< + std::vec::IntoIter, + std::vec::IntoIter, + >, + std::vec::IntoIter, + >, std::io::Error, > { let fn_pattern = String::with_capacity(180) @@ -460,10 +467,16 @@ fn list_of_log_and_zip_files( let log_pattern = log_pattern.as_os_str().to_string_lossy(); let mut zip_pattern = filename_config.directory.clone(); - zip_pattern.push(fn_pattern.add("zip")); + zip_pattern.push(fn_pattern.clone().add("zip")); let zip_pattern = zip_pattern.as_os_str().to_string_lossy(); - Ok(list_of_files(&log_pattern).chain(list_of_files(&zip_pattern))) + let mut gz_pattern = filename_config.directory.clone(); + gz_pattern.push(fn_pattern.add("gz")); + let gz_pattern = gz_pattern.as_os_str().to_string_lossy(); + + Ok(list_of_files(&log_pattern) + .chain(list_of_files(&gz_pattern)) + .chain(list_of_files(&zip_pattern))) } fn list_of_files(pattern: &str) -> std::vec::IntoIter { @@ -475,7 +488,7 @@ fn list_of_files(pattern: &str) -> std::vec::IntoIter { log_files.into_iter() } -fn remove_or_zip_too_old_logfiles( +fn remove_or_compress_too_old_logfiles( o_cleanup_thread_handle: &Option, cleanup_config: &Cleanup, filename_config: &FilenameConfig, @@ -487,44 +500,51 @@ fn remove_or_zip_too_old_logfiles( .ok(); Ok(()) } else { - remove_or_zip_too_old_logfiles_impl(cleanup_config, filename_config) + remove_or_compress_too_old_logfiles_impl(cleanup_config, filename_config) } } -fn remove_or_zip_too_old_logfiles_impl( +fn remove_or_compress_too_old_logfiles_impl( cleanup_config: &Cleanup, filename_config: &FilenameConfig, ) -> Result<(), std::io::Error> { - let (log_limit, zip_limit) = match *cleanup_config { + let (log_limit, compress_limit) = match *cleanup_config { Cleanup::Never => { return Ok(()); } Cleanup::KeepLogFiles(log_limit) => (log_limit, 0), - #[cfg(feature = "ziplogs")] - Cleanup::KeepZipFiles(zip_limit) => (0, zip_limit), - #[cfg(feature = "ziplogs")] - Cleanup::KeepLogAndZipFiles(log_limit, zip_limit) => (log_limit, zip_limit), + + #[cfg(feature = "compress")] + #[allow(deprecated)] + Cleanup::KeepCompressedFiles(compress_limit) | Cleanup::KeepZipFiles(compress_limit) => { + (0, compress_limit) + } + + #[cfg(feature = "compress")] + #[allow(deprecated)] + Cleanup::KeepLogAndCompressedFiles(log_limit, compress_limit) + | Cleanup::KeepLogAndZipFiles(log_limit, compress_limit) => (log_limit, compress_limit), }; - for (index, file) in list_of_log_and_zip_files(&filename_config)?.enumerate() { - if index >= log_limit + zip_limit { - // delete (zip or log) + for (index, file) in list_of_log_and_compressed_files(&filename_config)?.enumerate() { + if index >= log_limit + compress_limit { + // delete (log or log.gz) std::fs::remove_file(&file)?; } else if index >= log_limit { - #[cfg(feature = "ziplogs")] + #[cfg(feature = "compress")] { - // zip, if not yet zipped + // compress, if not yet compressed if let Some(extension) = file.extension() { - if extension != "zip" { + if extension != "gz" { let mut old_file = File::open(file.clone())?; - let mut zip_file = file.clone(); - zip_file.set_extension("log.zip"); - let mut zip = flate2::write::GzEncoder::new( - File::create(zip_file)?, + let mut compressed_file = file.clone(); + compressed_file.set_extension("log.gz"); + let mut gz_encoder = flate2::write::GzEncoder::new( + File::create(compressed_file)?, flate2::Compression::fast(), ); - std::io::copy(&mut old_file, &mut zip)?; - zip.finish()?; + std::io::copy(&mut old_file, &mut gz_encoder)?; + gz_encoder.finish()?; std::fs::remove_file(&file)?; } } diff --git a/tests/test_multi_threaded_cleanup.rs b/tests/test_multi_threaded_cleanup.rs index 24f8d49..e773083 100644 --- a/tests/test_multi_threaded_cleanup.rs +++ b/tests/test_multi_threaded_cleanup.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "ziplogs")] +#[cfg(feature = "compress")] mod d { use chrono::Local; use flexi_logger::{ @@ -13,7 +13,7 @@ mod d { const NO_OF_LOGLINES_PER_THREAD: usize = 100_000; const ROTATE_OVER_SIZE: u64 = 3_000_000; const NO_OF_LOG_FILES: usize = 2; - const NO_OF_ZIP_FILES: usize = 5; + const NO_OF_GZ_FILES: usize = 5; #[test] fn multi_threaded() { @@ -30,7 +30,7 @@ mod d { .rotate( Criterion::Size(ROTATE_OVER_SIZE), Naming::Timestamps, - Cleanup::KeepLogAndZipFiles(NO_OF_LOG_FILES, NO_OF_ZIP_FILES), + Cleanup::KeepLogAndCompressedFiles(NO_OF_LOG_FILES, NO_OF_GZ_FILES), ) .start() .unwrap_or_else(|e| panic!("Logger initialization failed with {}", e)); @@ -120,7 +120,7 @@ mod d { fn verify_logs(directory: &str) { // Since the cleanup deleted log files, we just can confirm that the correct number of - // log files and zip files exist + // log files and compressed files exist let basename = String::from(directory).add("/").add( &std::path::Path::new(&std::env::args().next().unwrap()) @@ -140,16 +140,16 @@ mod d { .inspect(|p| println!("found: {:?}", p)) .count(); - let zip_pattern = fn_pattern.add("zip"); - let no_of_zip_files = glob(&zip_pattern) + let gz_pattern = fn_pattern.add("gz"); + let no_of_gz_files = glob(&gz_pattern) .unwrap() .map(Result::unwrap) .inspect(|p| println!("found: {:?}", p)) .count(); assert_eq!(no_of_log_files, NO_OF_LOG_FILES); - assert_eq!(no_of_zip_files, NO_OF_ZIP_FILES); + assert_eq!(no_of_gz_files, NO_OF_GZ_FILES); - info!("Found correct number of log and zip files"); + info!("Found correct number of log and compressed files"); } }