From 7d617a97ac2562fd1cebdedec26cf0777e38adc5 Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Sat, 5 Feb 2022 21:11:40 +0100 Subject: [PATCH 1/3] replace chrono with time --- Cargo.toml | 5 ++- src/config.rs | 83 +++++++++++++++++++++++++++++++----------- src/lib.rs | 3 +- src/loggers/logging.rs | 21 ++++++++--- 4 files changed, 81 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 66487aa3..c76582dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,11 +20,12 @@ include = [ [features] test = [] -default = ["termcolor"] +default = ["termcolor", "local-offset"] +local-offset = ["time/local-offset"] [dependencies] log = { version = "0.4.*", features = ["std"] } termcolor = { version = "1.1.*", optional = true } paris = { version = "~1.5", optional = true } ansi_term = { version = "0.12", optional = true } -chrono = "0.4.1" +time = { version = "0.3.7", features = ["formatting", "macros"] } diff --git a/src/config.rs b/src/config.rs index be3a79c7..c3e0e1c3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,10 +2,10 @@ use log::Level; use log::LevelFilter; -pub use chrono::offset::{FixedOffset, Local, Offset, TimeZone, Utc}; use std::borrow::Cow; #[cfg(feature = "termcolor")] use termcolor::Color; +pub use time::{format_description::FormatItem, macros::format_description, UtcOffset}; #[derive(Debug, Clone, Copy)] /// Padding to be used for logging the level @@ -51,6 +51,13 @@ pub enum ThreadLogMode { Both, } +#[derive(Debug, Clone)] +pub(crate) enum TimeFormat { + Rfc2822, + Rfc3339, + Custom(&'static [time::format_description::FormatItem<'static>]), +} + /// Configuration for the Loggers /// /// All loggers print the message in the following form: @@ -72,9 +79,8 @@ pub struct Config { pub(crate) target: LevelFilter, pub(crate) target_padding: TargetPadding, pub(crate) location: LevelFilter, - pub(crate) time_format: Cow<'static, str>, - pub(crate) time_offset: FixedOffset, - pub(crate) time_local: bool, + pub(crate) time_format: TimeFormat, + pub(crate) time_offset: UtcOffset, pub(crate) filter_allow: Cow<'static, [Cow<'static, str>]>, pub(crate) filter_ignore: Cow<'static, [Cow<'static, str>]>, #[cfg(feature = "termcolor")] @@ -167,34 +173,68 @@ impl ConfigBuilder { self } - /// Set time chrono [strftime] format string. + /// Sets the time format to a custom representation. + /// + /// The easiest way to satisfy the static lifetime of the argument is to directly use the + /// re-exported [`time::macros::format_description`] macro. + /// + /// *Note*: The default time format is "[hour]:[minute]:[second]". + /// + /// The syntax for the format_description macro can be found in the + /// [`time` crate book](https://time-rs.github.io/book/api/format-description.html). /// - /// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers - pub fn set_time_format_str(&mut self, time_format: &'static str) -> &mut ConfigBuilder { - self.0.time_format = Cow::Borrowed(time_format); + /// # Usage + /// + /// ``` + /// # use simplelog::{ConfigBuilder, format_description}; + /// let config = ConfigBuilder::new() + /// .set_time_format_custom(format_description!("[hour]:[minute]:[second].[subsecond]")) + /// .build(); + /// ``` + pub fn set_time_format_custom( + &mut self, + time_format: &'static [FormatItem<'static>], + ) -> &mut ConfigBuilder { + self.0.time_format = TimeFormat::Custom(time_format); self } - /// Set time chrono [strftime] format string. - /// - /// [strftime]: https://docs.rs/chrono/0.4.0/chrono/format/strftime/index.html#specifiers - pub fn set_time_format(&mut self, time_format: String) -> &mut ConfigBuilder { - self.0.time_format = Cow::Owned(time_format); + /// Set time format string to use rfc2822. + pub fn set_time_format_rfc2822(&mut self) -> &mut ConfigBuilder { + self.0.time_format = TimeFormat::Rfc2822; self } - /// Set offset used for logging time (default is 0) - pub fn set_time_offset(&mut self, time_offset: FixedOffset) -> &mut ConfigBuilder { - self.0.time_offset = time_offset; + /// Set time format string to use rfc3339. + pub fn set_time_format_rfc3339(&mut self) -> &mut ConfigBuilder { + self.0.time_format = TimeFormat::Rfc3339; self } - /// set if you log in local timezone or UTC (default is UTC) - pub fn set_time_to_local(&mut self, local: bool) -> &mut ConfigBuilder { - self.0.time_local = local; + /// Set offset used for logging time (default is UTC) + pub fn set_time_offset(&mut self, offset: UtcOffset) -> &mut ConfigBuilder { + self.0.time_offset = offset; self } + /// Sets the offset used to the current local time offset + /// (overriding values previously set by [`ConfigBuilder::set_time_offset`]). + /// + /// This function may fail if the offset cannot be determined soundly. + /// This may be the case, when the program is multi-threaded by the time of calling this function. + /// One can opt-out of this behavior by setting `RUSTFLAGS="--cfg unsound_local_offset"`. + /// Doing so is not recommended, completely untested and may cause unexpected segfaults. + #[cfg(feature = "local-offset")] + pub fn set_time_offset_to_local(&mut self) -> Result<&mut ConfigBuilder, &mut ConfigBuilder> { + match UtcOffset::current_local_offset() { + Ok(offset) => { + self.0.time_offset = offset; + Ok(self) + } + Err(_) => Err(self), + } + } + /// set if you want to write colors in the logfile (default is Off) #[cfg(feature = "ansi_term")] pub fn set_write_log_enable_colors(&mut self, local: bool) -> &mut ConfigBuilder { @@ -284,9 +324,8 @@ impl Default for Config { target: LevelFilter::Debug, target_padding: TargetPadding::Off, location: LevelFilter::Trace, - time_format: Cow::Borrowed("%H:%M:%S"), - time_offset: FixedOffset::east(0), - time_local: false, + time_format: TimeFormat::Custom(format_description!("[hour]:[minute]:[second]")), + time_offset: UtcOffset::UTC, filter_allow: Cow::Borrowed(&[]), filter_ignore: Cow::Borrowed(&[]), write_log_enable_colors: false, diff --git a/src/lib.rs b/src/lib.rs index 2361b2e4..592be4d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,8 @@ mod config; mod loggers; pub use self::config::{ - Config, ConfigBuilder, LevelPadding, TargetPadding, ThreadLogMode, ThreadPadding, + format_description, Config, ConfigBuilder, FormatItem, LevelPadding, TargetPadding, + ThreadLogMode, ThreadPadding, }; #[cfg(feature = "test")] pub use self::loggers::TestLogger; diff --git a/src/loggers/logging.rs b/src/loggers/logging.rs index a1049369..a09bff3d 100644 --- a/src/loggers/logging.rs +++ b/src/loggers/logging.rs @@ -1,4 +1,4 @@ -use crate::config::TargetPadding; +use crate::config::{TargetPadding, TimeFormat}; use crate::{Config, LevelPadding, ThreadLogMode, ThreadPadding}; use log::{LevelFilter, Record}; use std::io::{Error, Write}; @@ -65,13 +65,22 @@ pub fn write_time(write: &mut W, config: &Config) -> Result<(), Error> where W: Write + Sized, { - let cur_time = if config.time_local { - (chrono::Local::now() + config.time_offset).format(&*config.time_format) - } else { - (chrono::Utc::now() + config.time_offset).format(&*config.time_format) + use time::error::Format; + use time::format_description::well_known::*; + + let time = time::OffsetDateTime::now_utc().to_offset(config.time_offset); + let res = match config.time_format { + TimeFormat::Rfc2822 => time.format_into(write, &Rfc2822), + TimeFormat::Rfc3339 => time.format_into(write, &Rfc3339), + TimeFormat::Custom(format) => time.format_into(write, &format), + }; + match res { + Err(Format::StdIo(err)) => return Err(err), + Err(err) => panic!("Invalid time format: {}", err), + _ => {} }; - write!(write, "{} ", cur_time)?; + write!(write, " ")?; Ok(()) } From 89a7ff86603ceca6a82d5ef6553ab4d1ef5ada5d Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Sat, 5 Feb 2022 21:11:58 +0100 Subject: [PATCH 2/3] v0.12.0-alpha1 --- CHANGELOG.md | 19 +++++++++++++++++++ Cargo.toml | 2 +- README.md | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba2d1f9c..89652790 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## v0.12.0 + - Replaces the semingly unmainted chrono library with the time crate. + - Addresses through this update + - RUSTSEC-2020-0159 (chrono) + - RUSTSEC-2020-0071 (time) + - `ConfigBuilder::set_time_to_local` is replaced by `ConfigBuilder::set_time_offset_to_local`. + - This function requires the new (and by default activated) `local-offset` feature. + - This function may fail, for more information read the docs. + - simplelog will not determine the local offset dynamically anymore, but only once, when this config option is set. + - Due to safety reasons there is no way to provide this property currently. + - `ConfigBuilder::set_time_offset` now takes a `time::UtcOffset` instead of a `chrono::FixedOffset`. + - `ConfigBuilder::set_time_format` has been replaced by three new variants + - `ConfigBuilder::set_time_format_rfc2822` sets the time format to use the format described by rfc2822. + - `ConfigBuilder::set_time_format_rfc3339` sets the time format to use the format described by rfc3339. + - `ConfigBuilder::set_time_format_custom` sets the time format to a custom time format best created using `time::macros::format_description`. + - Runtime provided time format configuration is possible, but difficult due to lifetime constraints. + - Fixing this will require a solution to https://github.com/time-rs/time/issues/429 + - *Note*: The default format is unchanged "[hour]:[minute]:[second]" + ## v0.11.0 - Add colored log levels using `ansi_term` (PR #88, credits to @manio) - Add target padding (PR #85, credits to @bytebeamio) diff --git a/Cargo.toml b/Cargo.toml index c76582dd..12cf3e26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "simplelog" -version = "0.11.2" +version = "0.12.0-alpha1" edition = "2018" authors = ["Drakulix "] description = "A simple and easy-to-use logging facility for Rust's log crate" diff --git a/README.md b/README.md index b095452a..a418cd58 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ fn main() { ### Results in ``` $ cargo run --example usage - Compiling simplelog v0.10.0 (file:///home/drakulix/Projects/simplelog) + Compiling simplelog v0.12.0 (file:///home/drakulix/Projects/simplelog) Running `target/debug/examples/usage` [ERROR] Bright red error ``` @@ -57,7 +57,7 @@ and my_rust_binary.log Just add ``` [dependencies] -simplelog = "^0.10.0" +simplelog = "^0.12.0" ``` to your `Cargo.toml` From cf8fc32c318c510afc40fec2d9bdcc8ec4590eed Mon Sep 17 00:00:00 2001 From: Victor Brekenfeld Date: Sat, 5 Feb 2022 21:26:01 +0100 Subject: [PATCH 3/3] fix TestLogger --- src/loggers/testlog.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/loggers/testlog.rs b/src/loggers/testlog.rs index 2c616442..f62130f7 100644 --- a/src/loggers/testlog.rs +++ b/src/loggers/testlog.rs @@ -8,7 +8,7 @@ //! Module providing the TestLogger Implementation use super::logging::should_skip; -use crate::{Config, LevelPadding, SharedLogger}; +use crate::{config::TimeFormat, Config, LevelPadding, SharedLogger}; use log::{set_boxed_logger, set_max_level, LevelFilter, Log, Metadata, Record, SetLoggerError}; use std::thread; @@ -128,12 +128,18 @@ pub fn log(config: &Config, record: &Record<'_>) { #[inline(always)] pub fn write_time(config: &Config) { - let cur_time = if config.time_local { - chrono::Local::now().naive_local() + config.time_offset - } else { - chrono::Utc::now().naive_utc() + config.time_offset + use time::format_description::well_known::*; + + let time = time::OffsetDateTime::now_utc().to_offset(config.time_offset); + let res = match config.time_format { + TimeFormat::Rfc2822 => time.format(&Rfc2822), + TimeFormat::Rfc3339 => time.format(&Rfc3339), + TimeFormat::Custom(format) => time.format(&format), + }; + match res { + Ok(time) => println!("{} ", time), + Err(err) => panic!("Invalid time format: {}", err), }; - print!("{} ", cur_time.format(&*config.time_format)); } #[inline(always)]