Skip to content

Commit

Permalink
If file logging is used, do not create the output file if no log is w…
Browse files Browse the repository at this point in the history
…ritten

Resolves emabee#62
  • Loading branch information
emabee committed Sep 18, 2020
1 parent 487add6 commit 2dd2fee
Show file tree
Hide file tree
Showing 9 changed files with 1,200 additions and 1,106 deletions.
13 changes: 9 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ 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

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

Make `1.37.0` the minimal rust version for `flexi_logger`.

## [0.15.11] - 2020-08-07

Introduce feature `specfile_without_notification` to allow coping with OS issues
(see [issue-59](https://github.com/emabee/flexi_logger/issues/59)).
(solves [issue-59](https://github.com/emabee/flexi_logger/issues/59)).

## [0.15.10] - 2020-07-22

Expand All @@ -21,16 +26,16 @@ Minor code maintenance.
## [0.15.9] - 2020-07-21

Allow using the log target with fantasy names, like with `env_logger`.
Closes [issue-56](https://github.com/emabee/flexi_logger/issues/56).
Solves [issue-56](https://github.com/emabee/flexi_logger/issues/56).

## [0.15.8] - 2020-07-20

Allow modifying the coloring palette through the environment variable `FLEXI_LOGGER_PALETTE`.
See function [style](https://docs.rs/flexi_logger/latest/flexi_logger/fn.style.html) for details.
Closes [issue-55](https://github.com/emabee/flexi_logger/issues/55).
Solves [issue-55](https://github.com/emabee/flexi_logger/issues/55).

By default, don't use colors if stdout or stderr are not a terminal
([issue-57](https://github.com/emabee/flexi_logger/issues/57)).
Solves [issue-57](https://github.com/emabee/flexi_logger/issues/57).

Add variant Criterion::AgeOrSize
(kudos to
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "flexi_logger"
version = "0.15.13-alpha"
version = "0.15.13"
authors = ["emabee <[email protected]>"]
edition = "2018"
license = "MIT OR Apache-2.0"
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ mod flexi_logger;
mod formats;
mod log_specification;
mod logger;
mod parameters;
mod primary_writer;
mod reconfiguration_handle;

Expand All @@ -56,7 +57,8 @@ pub use crate::deferred_now::DeferredNow;
pub use crate::flexi_error::FlexiLoggerError;
pub use crate::formats::*;
pub use crate::log_specification::{LogSpecBuilder, LogSpecification, ModuleFilter};
pub use crate::logger::{Age, Cleanup, Criterion, Duplicate, LogTarget, Logger, Naming};
pub use crate::logger::{Duplicate, LogTarget, Logger};
pub use crate::parameters::{Age, Cleanup, Criterion, Naming};
pub use crate::reconfiguration_handle::ReconfigurationHandle;

/// Function type for Format functions.
Expand Down
145 changes: 5 additions & 140 deletions src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::flexi_logger::FlexiLogger;
use crate::primary_writer::PrimaryWriter;
use crate::writers::{FileLogWriter, FileLogWriterBuilder, LogWriter};
use crate::FormatFunction;
use crate::ReconfigurationHandle;
use crate::{formats, FlexiLoggerError, LogSpecification};
use crate::{
formats, Cleanup, Criterion, FlexiLoggerError, FormatFunction, LogSpecification, Naming,
ReconfigurationHandle,
};

#[cfg(feature = "specfile")]
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
use std::collections::HashMap;
Expand Down Expand Up @@ -857,143 +859,6 @@ pub(crate) fn log_spec_string_from_file<P: AsRef<std::path::Path>>(
Ok(buf)
}

/// Criterion when to rotate the log file.
///
/// Used in [`Logger::rotate`](struct.Logger.html#method.rotate).
#[derive(Copy, Clone, Debug)]
pub enum Criterion {
/// Rotate the log file when it exceeds the specified size in bytes.
Size(u64),
/// Rotate the log file when it has become older than the specified age.
///
/// ## Minor limitation
///
/// ### TL,DR
/// the combination of `Logger::append()`
/// with `Criterion::Age` works OK, but not perfectly correct on Windows or Linux
/// when the program is restarted.
///
/// ### Details
/// Applying the age criterion works fine while your program is running.
/// Ideally, we should also apply it to the rCURRENT file when the program is restarted
/// and you chose the `Logger::append()` option.
///
/// Unfortunately, this does not work on Windows, and it does not work on linux,
/// for different reasons.
///
/// To minimize the impact on age-based file-rotation,
/// `flexi_logger` uses on Windows and linux its initialization time
/// rather than the real file property
/// as the created_at-info of an rCURRENT file that already exists, and the
/// current timestamp when file rotation happens during further execution.
/// Consequently, a left-over rCURRENT file from a previous program run will look newer
/// than it is, and will be used longer than it should be.
///
/// #### Issue on Windows
///
/// For compatibility with DOS (sic!), Windows magically transfers the created_at-info
/// of a file that is deleted (or renamed) to its successor,
/// when the recreation happens within some seconds [[1]](#ref-1).
///
/// <a name="ref-1">[1]</a> [https://superuser.com/questions/966490/windows-7-what-is-date-created-file-property-referring-to](https://superuser.com/questions/966490/windows-7-what-is-date-created-file-property-referring-to).
///
/// If the file property were used by `flexi_logger`,
/// the rCURRENT file would always appear to be as old as the
/// first one that ever was created - rotation by time would completely fail.
///
/// #### Issue on Linux
///
/// `std::fs::metadata.created()` returns `Err`, because linux does not maintain a
/// created-at-timestamp.
///
Age(Age),
/// Rotate the file when it has either become older than the specified age, or when it has
/// exceeded the specified size in bytes.
///
/// See documentation for Age and Size.
AgeOrSize(Age, u64),
}

/// The age after which a log file rotation will be triggered,
/// when [`Criterion::Age`](enum.Criterion.html#variant.Age) is chosen.
#[derive(Copy, Clone, Debug)]
pub enum Age {
/// Rotate the log file when the local clock has started a new day since the
/// current file had been created.
Day,
/// Rotate the log file when the local clock has started a new hour since the
/// current file had been created.
Hour,
/// Rotate the log file when the local clock has started a new minute since the
/// current file had been created.
Minute,
/// Rotate the log file when the local clock has started a new second since the
/// current file had been created.
Second,
}

/// The naming convention for rotated log files.
///
/// With file rotation, the logs are written to a file with infix `_rCURRENT`.
/// When rotation happens, the CURRENT log file will be renamed to a file with
/// another infix of the form `"_r..."`. `Naming` defines which other infix will be used.
///
/// Used in [`Logger::rotate`](struct.Logger.html#method.rotate).
#[derive(Copy, Clone, Debug)]
pub enum Naming {
/// File rotation rotates to files with a timestamp-infix, like `"r2020-01-27_14-41-08"`.
Timestamps,
/// File rotation rotates to files with a number-infix.
Numbers,
}

/// Defines the strategy for handling older log files.
///
/// Is used in [`Logger::rotate`](struct.Logger.html#method.rotate).
///
/// Note that if you use a strategy other than `Cleanup::Never`, then the cleanup work is
/// by default done in an extra thread, to minimize the impact on the program.
/// 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.
#[derive(Copy, Clone, Debug)]
pub enum Cleanup {
/// Older log files are not touched - they remain for ever.
Never,
/// 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.
/// Older files are deleted, if necessary.
///
/// This option is only available with feature `ziplogs`.
#[cfg(feature = "ziplogs")]
KeepZipFiles(usize),
/// Allows keeping some files as text files and some as zip files.
///
/// Is used in
///
/// ## 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.
///
/// This option is only available with feature `ziplogs`.
#[cfg(feature = "ziplogs")]
KeepLogAndZipFiles(usize, usize),
}

impl Cleanup {
// Returns true if some cleanup is to be done.
#[must_use]
pub(crate) fn do_cleanup(&self) -> bool {
match self {
Self::Never => false,
_ => true,
}
}
}

/// Used to control which messages are to be duplicated to stderr, when `log_to_file()` is used.
#[derive(Debug)]
pub enum Duplicate {
Expand Down
135 changes: 135 additions & 0 deletions src/parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/// Criterion when to rotate the log file.
///
/// Used in [`Logger::rotate`](struct.Logger.html#method.rotate).
#[derive(Copy, Clone, Debug)]
pub enum Criterion {
/// Rotate the log file when it exceeds the specified size in bytes.
Size(u64),
/// Rotate the log file when it has become older than the specified age.
///
/// ## Minor limitation
///
/// ### TL,DR
/// the combination of `Logger::append()`
/// with `Criterion::Age` works OK, but not perfectly correct on Windows or Linux
/// when the program is restarted.
///
/// ### Details
/// Applying the age criterion works fine while your program is running.
/// Ideally, we should also apply it to the rCURRENT file when the program is restarted
/// and you chose the `Logger::append()` option.
///
/// Unfortunately, this does not work on Windows, and it does not work on linux,
/// for different reasons.
///
/// To minimize the impact on age-based file-rotation,
/// `flexi_logger` uses on Windows and linux its initialization time
/// rather than the real file property
/// as the created_at-info of an rCURRENT file that already exists, and the
/// current timestamp when file rotation happens during further execution.
/// Consequently, a left-over rCURRENT file from a previous program run will look newer
/// than it is, and will be used longer than it should be.
///
/// #### Issue on Windows
///
/// For compatibility with DOS (sic!), Windows magically transfers the created_at-info
/// of a file that is deleted (or renamed) to its successor,
/// when the recreation happens within some seconds [[1]](#ref-1).
///
/// <a name="ref-1">[1]</a> [https://superuser.com/questions/966490/windows-7-what-is-date-created-file-property-referring-to](https://superuser.com/questions/966490/windows-7-what-is-date-created-file-property-referring-to).
///
/// If the file property were used by `flexi_logger`,
/// the rCURRENT file would always appear to be as old as the
/// first one that ever was created - rotation by time would completely fail.
///
/// #### Issue on Linux
///
/// `std::fs::metadata.created()` returns `Err`, because linux does not maintain a
/// created-at-timestamp.
///
Age(Age),
/// Rotate the file when it has either become older than the specified age, or when it has
/// exceeded the specified size in bytes.
///
/// See documentation for Age and Size.
AgeOrSize(Age, u64),
}

/// The age after which a log file rotation will be triggered,
/// when [`Criterion::Age`](enum.Criterion.html#variant.Age) is chosen.
#[derive(Copy, Clone, Debug)]
pub enum Age {
/// Rotate the log file when the local clock has started a new day since the
/// current file had been created.
Day,
/// Rotate the log file when the local clock has started a new hour since the
/// current file had been created.
Hour,
/// Rotate the log file when the local clock has started a new minute since the
/// current file had been created.
Minute,
/// Rotate the log file when the local clock has started a new second since the
/// current file had been created.
Second,
}

/// The naming convention for rotated log files.
///
/// With file rotation, the logs are written to a file with infix `_rCURRENT`.
/// When rotation happens, the CURRENT log file will be renamed to a file with
/// another infix of the form `"_r..."`. `Naming` defines which other infix will be used.
///
/// Used in [`Logger::rotate`](struct.Logger.html#method.rotate).
#[derive(Copy, Clone, Debug)]
pub enum Naming {
/// File rotation rotates to files with a timestamp-infix, like `"r2020-01-27_14-41-08"`.
Timestamps,
/// File rotation rotates to files with a number-infix.
Numbers,
}
/// Defines the strategy for handling older log files.
///
/// Is used in [`Logger::rotate`](struct.Logger.html#method.rotate).
///
/// Note that if you use a strategy other than `Cleanup::Never`, then the cleanup work is
/// by default done in an extra thread, to minimize the impact on the program.
/// 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.
#[derive(Copy, Clone, Debug)]
pub enum Cleanup {
/// Older log files are not touched - they remain for ever.
Never,
/// 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.
/// Older files are deleted, if necessary.
///
/// This option is only available with feature `ziplogs`.
#[cfg(feature = "ziplogs")]
KeepZipFiles(usize),
/// Allows keeping some files as text files and some as zip files.
///
/// Is used in
///
/// ## 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.
///
/// This option is only available with feature `ziplogs`.
#[cfg(feature = "ziplogs")]
KeepLogAndZipFiles(usize, usize),
}

impl Cleanup {
// Returns true if some cleanup is to be done.
#[must_use]
pub(crate) fn do_cleanup(&self) -> bool {
match self {
Self::Never => false,
_ => true,
}
}
}
Loading

0 comments on commit 2dd2fee

Please sign in to comment.