Skip to content

Commit

Permalink
Merge pull request #95 from Drakulix/fix/chrono_dep
Browse files Browse the repository at this point in the history
Replace chrono with time
  • Loading branch information
Drakulix committed Apr 19, 2022
2 parents 81c6293 + cf8fc32 commit 44a294f
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 40 deletions.
19 changes: 19 additions & 0 deletions 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)
Expand Down
7 changes: 4 additions & 3 deletions Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "simplelog"
version = "0.11.2"
version = "0.12.0-alpha1"
edition = "2018"
authors = ["Drakulix <github@drakulix.de>"]
description = "A simple and easy-to-use logging facility for Rust's log crate"
Expand All @@ -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"] }
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -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
```
Expand All @@ -57,7 +57,7 @@ and my_rust_binary.log
Just add
```
[dependencies]
simplelog = "^0.10.0"
simplelog = "^0.12.0"
```
to your `Cargo.toml`

Expand Down
83 changes: 61 additions & 22 deletions src/config.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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")]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Expand Up @@ -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;
Expand Down
21 changes: 15 additions & 6 deletions 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};
Expand Down Expand Up @@ -65,13 +65,22 @@ pub fn write_time<W>(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(())
}

Expand Down
18 changes: 12 additions & 6 deletions src/loggers/testlog.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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)]
Expand Down

0 comments on commit 44a294f

Please sign in to comment.