From 09f209b35aea467c133685c2a0e7d00c4a92ce24 Mon Sep 17 00:00:00 2001 From: Shayne Fletcher Date: Fri, 18 Aug 2023 15:25:39 -0400 Subject: [PATCH 1/8] [tracing-subscriber]: add chrono crate implementations of FormatTime (local time & UTC) --- tracing-subscriber/Cargo.toml | 1 + .../src/fmt/time/chrono_crate.rs | 57 +++++++++++++++++++ tracing-subscriber/src/fmt/time/mod.rs | 3 + 3 files changed, 61 insertions(+) create mode 100644 tracing-subscriber/src/fmt/time/chrono_crate.rs diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index 100da643ca..ea205be5f9 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -50,6 +50,7 @@ once_cell = { optional = true, version = "1.13.0" } tracing-log = { path = "../tracing-log", version = "0.2", optional = true, default-features = false, features = ["log-tracer", "std"] } nu-ansi-term = { version = "0.46.0", optional = true } time = { version = "0.3.2", features = ["formatting"], optional = true } +chrono = { version = "0.4.26" } # only required by the json feature serde_json = { version = "1.0.82", optional = true } diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs new file mode 100644 index 0000000000..0a3d5cfb64 --- /dev/null +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -0,0 +1,57 @@ +use crate::fmt::format::Writer; +use crate::fmt::time::FormatTime; + +/// Formats [local time]s and [UTC time]s with [formatter] implementations +/// that use the [`chrono` crate]. +/// +/// [local time]: https://docs.rs/chrono/0.4.26/chrono/offset/struct.Local.html +/// [UTC time]: https://docs.rs/chrono/0.4.26/chrono/offset/struct.Utc.html +/// [`chrono` crate]: https://docs.rs/chrono/0.4.26/chrono/ +/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html + +/// Tag-type (indicating UTC timezone) enabling static dispatch +/// to `chrono::Local` functions. +#[derive(Debug)] +pub struct LocalTime; + +impl FormatTime for LocalTime { + fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { + w.write_str(&chrono::Local::now().to_rfc3339()) + } +} + +/// Tag-type (indicating the "local" timezone) enabling static +/// dispatch to `chrono::Utc` functions. +#[derive(Debug)] +pub struct Utc; + +impl FormatTime for Utc { + fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { + w.write_str(&chrono::Utc::now().to_rfc3339()) + } +} + +#[cfg(test)] +mod tests { + use crate::fmt::format::Writer; + use crate::fmt::time::FormatTime; + + use super::LocalTime; + use super::Utc; + + #[test] + fn test_chrono_format_time_utc() { + let mut buf = String::new(); + let mut dst: Writer<'_> = Writer::new(&mut buf); + assert!(FormatTime::format_time(&Utc, &mut dst).is_ok()); + // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00" + } + + #[test] + fn test_chrono_format_time_local() { + let mut buf = String::new(); + let mut dst: Writer<'_> = Writer::new(&mut buf); + assert!(FormatTime::format_time(&LocalTime, &mut dst).is_ok()); + // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00". + } +} diff --git a/tracing-subscriber/src/fmt/time/mod.rs b/tracing-subscriber/src/fmt/time/mod.rs index 21d692bbb0..be450a9a98 100644 --- a/tracing-subscriber/src/fmt/time/mod.rs +++ b/tracing-subscriber/src/fmt/time/mod.rs @@ -15,6 +15,9 @@ pub use time_crate::UtcTime; #[cfg_attr(docsrs, doc(cfg(all(unsound_local_offset, feature = "local-time"))))] pub use time_crate::LocalTime; +/// [`Chrono`]-based implementation for time. +pub mod chrono_crate; + /// A type that can measure and format the current time. /// /// This trait is used by `Format` to include a timestamp with each `Event` when it is logged. From f4817a52f42c4a74dcac28ddf1b6705fbc99b21b Mon Sep 17 00:00:00 2001 From: Shayne Fletcher Date: Mon, 21 Aug 2023 14:53:45 -0400 Subject: [PATCH 2/8] [tracing-subscriber]: add chrono feature --- tracing-subscriber/Cargo.toml | 3 +- .../src/fmt/time/chrono_crate.rs | 45 +++++++++++-------- tracing-subscriber/src/fmt/time/mod.rs | 3 +- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index ea205be5f9..ca5b674263 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -32,6 +32,7 @@ fmt = ["registry", "std"] ansi = ["fmt", "nu-ansi-term"] registry = ["sharded-slab", "thread_local", "std"] json = ["tracing-serde", "serde", "serde_json"] + # Enables support for local time when using the `time` crate timestamp # formatters. local-time = ["time/local-offset"] @@ -50,7 +51,6 @@ once_cell = { optional = true, version = "1.13.0" } tracing-log = { path = "../tracing-log", version = "0.2", optional = true, default-features = false, features = ["log-tracer", "std"] } nu-ansi-term = { version = "0.46.0", optional = true } time = { version = "0.3.2", features = ["formatting"], optional = true } -chrono = { version = "0.4.26" } # only required by the json feature serde_json = { version = "1.0.82", optional = true } @@ -59,6 +59,7 @@ tracing-serde = { path = "../tracing-serde", version = "0.2", optional = true } # opt-in deps parking_lot = { version = "0.12.1", optional = true } +chrono = { version = "0.4.26", optional = true } # registry sharded-slab = { version = "0.1.4", optional = true } diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index 0a3d5cfb64..69146ae89d 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -1,31 +1,34 @@ use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; -/// Formats [local time]s and [UTC time]s with [formatter] implementations +/// Formats [local time]s and [UTC time]s with `FormatTime` implementations /// that use the [`chrono` crate]. /// -/// [local time]: https://docs.rs/chrono/0.4.26/chrono/offset/struct.Local.html -/// [UTC time]: https://docs.rs/chrono/0.4.26/chrono/offset/struct.Utc.html -/// [`chrono` crate]: https://docs.rs/chrono/0.4.26/chrono/ -/// [formatter]: https://docs.rs/time/0.3/time/formatting/trait.Formattable.html +/// [local time]: [`chrono::offset::Local`] +/// [UTC time]: [`chrono::offset::Utc`] +/// [`chrono` crate]: [`chrono`] -/// Tag-type (indicating UTC timezone) enabling static dispatch -/// to `chrono::Local` functions. -#[derive(Debug)] -pub struct LocalTime; +/// Retrieve and print the current local time. +#[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] +pub struct ChronoLocal; -impl FormatTime for LocalTime { +#[cfg(feature = "chrono")] +impl FormatTime for ChronoLocal { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { w.write_str(&chrono::Local::now().to_rfc3339()) } } -/// Tag-type (indicating the "local" timezone) enabling static -/// dispatch to `chrono::Utc` functions. -#[derive(Debug)] -pub struct Utc; +/// Retrieve and print the current UTC time. +#[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] +pub struct ChronoUtc; -impl FormatTime for Utc { +#[cfg(feature = "chrono")] +impl FormatTime for ChronoUtc { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { w.write_str(&chrono::Utc::now().to_rfc3339()) } @@ -36,22 +39,26 @@ mod tests { use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; - use super::LocalTime; - use super::Utc; + #[cfg(feature = "chrono")] + use super::ChronoLocal; + #[cfg(feature = "chrono")] + use super::ChronoUtc; + #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_utc() { let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); - assert!(FormatTime::format_time(&Utc, &mut dst).is_ok()); + assert!(FormatTime::format_time(&ChronoUtc, &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00" } + #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_local() { let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); - assert!(FormatTime::format_time(&LocalTime, &mut dst).is_ok()); + assert!(FormatTime::format_time(&ChronoLocal, &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00". } } diff --git a/tracing-subscriber/src/fmt/time/mod.rs b/tracing-subscriber/src/fmt/time/mod.rs index be450a9a98..d3e7aadca8 100644 --- a/tracing-subscriber/src/fmt/time/mod.rs +++ b/tracing-subscriber/src/fmt/time/mod.rs @@ -15,7 +15,8 @@ pub use time_crate::UtcTime; #[cfg_attr(docsrs, doc(cfg(all(unsound_local_offset, feature = "local-time"))))] pub use time_crate::LocalTime; -/// [`Chrono`]-based implementation for time. +/// [`chrono`]-based implementation for time. +#[cfg(feature = "chrono")] pub mod chrono_crate; /// A type that can measure and format the current time. From f8023345e8c68ce93af9fdc0cdfacc7bc85b51ed Mon Sep 17 00:00:00 2001 From: Shayne Fletcher Date: Wed, 23 Aug 2023 12:01:28 -0400 Subject: [PATCH 3/8] allow for custom datetime formattters w/chrono_crate --- .../src/fmt/time/chrono_crate.rs | 81 ++++++++++++++++--- 1 file changed, 71 insertions(+), 10 deletions(-) diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index 69146ae89d..6699a56985 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -8,29 +8,63 @@ use crate::fmt::time::FormatTime; /// [UTC time]: [`chrono::offset::Utc`] /// [`chrono` crate]: [`chrono`] +/// The RFC 3339 format is used by default but a custom format string +/// can be used. See [`chrono::format::strftime`]for details on +/// the supported syntax. +/// +/// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html +#[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum ChronoFmtType { + /// Format according to the RFC 3339 convention. + Rfc3339, + /// Format according to a custom format string. + Custom(String), +} + +#[cfg(feature = "chrono")] +impl Default for ChronoFmtType { + fn default() -> Self { + ChronoFmtType::Rfc3339 + } +} + /// Retrieve and print the current local time. #[cfg(feature = "chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] -#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] -pub struct ChronoLocal; +#[derive(Debug, Clone, Eq, PartialEq, Default)] +pub struct ChronoLocal { + format: ChronoFmtType, +} #[cfg(feature = "chrono")] impl FormatTime for ChronoLocal { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { - w.write_str(&chrono::Local::now().to_rfc3339()) + let t = chrono::Local::now(); + match &self.format { + ChronoFmtType::Rfc3339 => w.write_str(&t.to_rfc3339()), + ChronoFmtType::Custom(fmt) => w.write_str(&format!("{}", t.format(fmt))), + } } } /// Retrieve and print the current UTC time. #[cfg(feature = "chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] -#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] -pub struct ChronoUtc; +#[derive(Debug, Clone, Eq, PartialEq, Default)] +pub struct ChronoUtc { + format: ChronoFmtType, +} #[cfg(feature = "chrono")] impl FormatTime for ChronoUtc { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { - w.write_str(&chrono::Utc::now().to_rfc3339()) + let t = chrono::Utc::now(); + match &self.format { + ChronoFmtType::Rfc3339 => w.write_str(&t.to_rfc3339()), + ChronoFmtType::Custom(fmt) => w.write_str(&format!("{}", t.format(fmt))), + } } } @@ -39,6 +73,8 @@ mod tests { use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; + #[cfg(feature = "chrono")] + use super::ChronoFmtType; #[cfg(feature = "chrono")] use super::ChronoLocal; #[cfg(feature = "chrono")] @@ -46,19 +82,44 @@ mod tests { #[cfg(feature = "chrono")] #[test] - fn test_chrono_format_time_utc() { + fn test_chrono_format_time_utc_default() { let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); - assert!(FormatTime::format_time(&ChronoUtc, &mut dst).is_ok()); + assert!(FormatTime::format_time(&ChronoUtc::default(), &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00" } #[cfg(feature = "chrono")] #[test] - fn test_chrono_format_time_local() { + fn test_chrono_format_time_utc_custom() { + let fmt = ChronoUtc { + format: ChronoFmtType::Custom("%a %b %e %T %Y".to_owned()), + }; let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); - assert!(FormatTime::format_time(&ChronoLocal, &mut dst).is_ok()); + assert!(FormatTime::format_time(&fmt, &mut dst).is_ok()); + println!("{}", buf); + // e.g. `buf` contains "Wed Aug 23 15:53:23 2023" + } + + #[cfg(feature = "chrono")] + #[test] + fn test_chrono_format_time_local_default() { + let mut buf = String::new(); + let mut dst: Writer<'_> = Writer::new(&mut buf); + assert!(FormatTime::format_time(&ChronoLocal::default(), &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00". } + + #[cfg(feature = "chrono")] + #[test] + fn test_chrono_format_time_local_custom() { + let fmt = ChronoLocal { + format: ChronoFmtType::Custom("%a %b %e %T %Y".to_owned()), + }; + let mut buf = String::new(); + let mut dst: Writer<'_> = Writer::new(&mut buf); + assert!(FormatTime::format_time(&fmt, &mut dst).is_ok()); + // e.g. `buf` contains "Wed Aug 23 15:55:46 2023". + } } From 897cfeb5f7ad33bea744f9fd3a631bca5e869d94 Mon Sep 17 00:00:00 2001 From: Shayne Fletcher Date: Wed, 6 Sep 2023 18:18:06 -0400 Subject: [PATCH 4/8] [tracing-subscriber]: remove redundant cfg --- tracing-subscriber/src/fmt/time/chrono_crate.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index 6699a56985..8dc275fd49 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -13,17 +13,15 @@ use crate::fmt::time::FormatTime; /// the supported syntax. /// /// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html -#[cfg(feature = "chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq)] -pub enum ChronoFmtType { +enum ChronoFmtType { /// Format according to the RFC 3339 convention. Rfc3339, /// Format according to a custom format string. Custom(String), } -#[cfg(feature = "chrono")] impl Default for ChronoFmtType { fn default() -> Self { ChronoFmtType::Rfc3339 @@ -31,14 +29,12 @@ impl Default for ChronoFmtType { } /// Retrieve and print the current local time. -#[cfg(feature = "chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoLocal { format: ChronoFmtType, } -#[cfg(feature = "chrono")] impl FormatTime for ChronoLocal { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Local::now(); @@ -50,14 +46,12 @@ impl FormatTime for ChronoLocal { } /// Retrieve and print the current UTC time. -#[cfg(feature = "chrono")] #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoUtc { format: ChronoFmtType, } -#[cfg(feature = "chrono")] impl FormatTime for ChronoUtc { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Utc::now(); @@ -73,14 +67,10 @@ mod tests { use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; - #[cfg(feature = "chrono")] use super::ChronoFmtType; - #[cfg(feature = "chrono")] use super::ChronoLocal; - #[cfg(feature = "chrono")] use super::ChronoUtc; - #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_utc_default() { let mut buf = String::new(); @@ -89,7 +79,6 @@ mod tests { // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00" } - #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_utc_custom() { let fmt = ChronoUtc { @@ -98,11 +87,9 @@ mod tests { let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); assert!(FormatTime::format_time(&fmt, &mut dst).is_ok()); - println!("{}", buf); // e.g. `buf` contains "Wed Aug 23 15:53:23 2023" } - #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_local_default() { let mut buf = String::new(); @@ -111,7 +98,6 @@ mod tests { // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00". } - #[cfg(feature = "chrono")] #[test] fn test_chrono_format_time_local_custom() { let fmt = ChronoLocal { From ae007f9eb6878b37db22969f5c19c2942fdef5ec Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 21 Sep 2023 10:20:35 -0500 Subject: [PATCH 5/8] edit docs, add constructors for `ChronoLocal` and `ChronoUtc` --- .../src/fmt/time/chrono_crate.rs | 54 ++++++++++++++++++- tracing-subscriber/src/fmt/time/mod.rs | 14 ++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index 8dc275fd49..ca1162bb07 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -28,13 +28,38 @@ impl Default for ChronoFmtType { } } -/// Retrieve and print the current local time. +/// Formats the current [local time] using a [formatter] from the [`chrono`] crate. +/// +/// [local time]: chrono::Local::now() +/// [formatter]: chrono::format #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoLocal { format: ChronoFmtType, } +impl ChronoLocal { + /// Format the time using the [`RFC 3339`] format + /// (a subset of [`ISO 8601`]). + /// + /// [`RFC 3339`]: https://tools.ietf.org/html/rfc3339 + /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601 + pub fn rfc_3339() -> Self { + Self { + format: ChronoFmtType::Rfc3339, + } + } + + /// Format the time using the given format string. + /// + /// See [`chrono::format::strftime`] for details on the supported syntax. + pub fn new(format_string: String) -> Self { + Self { + format: ChronoFmtType::Custom(format_string), + } + } +} + impl FormatTime for ChronoLocal { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Local::now(); @@ -45,13 +70,38 @@ impl FormatTime for ChronoLocal { } } -/// Retrieve and print the current UTC time. +/// Formats the current [UTC time] using a [formatter] from the [`chrono`] crate. +/// +/// [UTC time]: chrono::Utc::now() +/// [formatter]: chrono::format #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoUtc { format: ChronoFmtType, } +impl ChronoUtc { + /// Format the time using the [`RFC 3339`] format + /// (a subset of [`ISO 8601`]). + /// + /// [`RFC 3339`]: https://tools.ietf.org/html/rfc3339 + /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601 + pub fn rfc_3339() -> Self { + Self { + format: ChronoFmtType::Rfc3339, + } + } + + /// Format the time using the given format string. + /// + /// See [`chrono::format::strftime`] for details on the supported syntax. + pub fn new(format_string: String) -> Self { + Self { + format: ChronoFmtType::Custom(format_string), + } + } +} + impl FormatTime for ChronoUtc { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Utc::now(); diff --git a/tracing-subscriber/src/fmt/time/mod.rs b/tracing-subscriber/src/fmt/time/mod.rs index d3e7aadca8..dacf7531e3 100644 --- a/tracing-subscriber/src/fmt/time/mod.rs +++ b/tracing-subscriber/src/fmt/time/mod.rs @@ -7,6 +7,7 @@ mod datetime; #[cfg(feature = "time")] mod time_crate; + #[cfg(feature = "time")] #[cfg_attr(docsrs, doc(cfg(feature = "time")))] pub use time_crate::UtcTime; @@ -15,9 +16,18 @@ pub use time_crate::UtcTime; #[cfg_attr(docsrs, doc(cfg(all(unsound_local_offset, feature = "local-time"))))] pub use time_crate::LocalTime; -/// [`chrono`]-based implementation for time. +/// [`chrono`]-based implementation for [`FormatTime`]. +#[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(feature = "local-time"))] +mod chrono_crate; + +#[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(feature = "chrono"))] +pub use chrono_crate::ChronoLocal; + #[cfg(feature = "chrono")] -pub mod chrono_crate; +#[cfg_attr(docsrs, doc(feature = "chrono"))] +pub use chrono_crate::ChronoUtc; /// A type that can measure and format the current time. /// From e2c7bec188345b3d73698753c07dd394f1b2eb74 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Thu, 21 Sep 2023 11:22:03 -0500 Subject: [PATCH 6/8] fix invalid doc(cfg(...)) --- tracing-subscriber/src/fmt/time/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tracing-subscriber/src/fmt/time/mod.rs b/tracing-subscriber/src/fmt/time/mod.rs index dacf7531e3..a00c9522c2 100644 --- a/tracing-subscriber/src/fmt/time/mod.rs +++ b/tracing-subscriber/src/fmt/time/mod.rs @@ -18,15 +18,15 @@ pub use time_crate::LocalTime; /// [`chrono`]-based implementation for [`FormatTime`]. #[cfg(feature = "chrono")] -#[cfg_attr(docsrs, doc(feature = "local-time"))] +#[cfg_attr(docsrs, doc(cfg(feature = "local-time")))] mod chrono_crate; #[cfg(feature = "chrono")] -#[cfg_attr(docsrs, doc(feature = "chrono"))] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] pub use chrono_crate::ChronoLocal; #[cfg(feature = "chrono")] -#[cfg_attr(docsrs, doc(feature = "chrono"))] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] pub use chrono_crate::ChronoUtc; /// A type that can measure and format the current time. From 269695ad71781de81499805be5117d534464200f Mon Sep 17 00:00:00 2001 From: Shayne Fletcher Date: Fri, 22 Sep 2023 11:14:05 -0400 Subject: [PATCH 7/8] implement hawkw's review suggestions --- tracing-subscriber/Cargo.toml | 2 +- .../src/fmt/time/chrono_crate.rs | 81 +++++++++++-------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/tracing-subscriber/Cargo.toml b/tracing-subscriber/Cargo.toml index ca5b674263..b73272ba1e 100644 --- a/tracing-subscriber/Cargo.toml +++ b/tracing-subscriber/Cargo.toml @@ -59,7 +59,7 @@ tracing-serde = { path = "../tracing-serde", version = "0.2", optional = true } # opt-in deps parking_lot = { version = "0.12.1", optional = true } -chrono = { version = "0.4.26", optional = true } +chrono = { version = "0.4.26", default-features = false, features = ["clock", "std"], optional = true } # registry sharded-slab = { version = "0.1.4", optional = true } diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index ca1162bb07..e742f336c3 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -1,6 +1,8 @@ use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; +use std::sync::Arc; + /// Formats [local time]s and [UTC time]s with `FormatTime` implementations /// that use the [`chrono` crate]. /// @@ -8,26 +10,6 @@ use crate::fmt::time::FormatTime; /// [UTC time]: [`chrono::offset::Utc`] /// [`chrono` crate]: [`chrono`] -/// The RFC 3339 format is used by default but a custom format string -/// can be used. See [`chrono::format::strftime`]for details on -/// the supported syntax. -/// -/// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html -#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] -#[derive(Debug, Clone, Eq, PartialEq)] -enum ChronoFmtType { - /// Format according to the RFC 3339 convention. - Rfc3339, - /// Format according to a custom format string. - Custom(String), -} - -impl Default for ChronoFmtType { - fn default() -> Self { - ChronoFmtType::Rfc3339 - } -} - /// Formats the current [local time] using a [formatter] from the [`chrono`] crate. /// /// [local time]: chrono::Local::now() @@ -35,7 +17,7 @@ impl Default for ChronoFmtType { #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoLocal { - format: ChronoFmtType, + format: Arc, } impl ChronoLocal { @@ -46,7 +28,7 @@ impl ChronoLocal { /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601 pub fn rfc_3339() -> Self { Self { - format: ChronoFmtType::Rfc3339, + format: Arc::new(ChronoFmtType::Rfc3339), } } @@ -55,7 +37,7 @@ impl ChronoLocal { /// See [`chrono::format::strftime`] for details on the supported syntax. pub fn new(format_string: String) -> Self { Self { - format: ChronoFmtType::Custom(format_string), + format: Arc::new(ChronoFmtType::Custom(format_string)), } } } @@ -63,9 +45,18 @@ impl ChronoLocal { impl FormatTime for ChronoLocal { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Local::now(); - match &self.format { - ChronoFmtType::Rfc3339 => w.write_str(&t.to_rfc3339()), - ChronoFmtType::Custom(fmt) => w.write_str(&format!("{}", t.format(fmt))), + match self.format.as_ref() { + ChronoFmtType::Rfc3339 => { + use chrono::format::{Fixed, Item}; + write!( + w, + "{}", + t.format_with_items(core::iter::once(Item::Fixed(Fixed::RFC3339))) + ) + } + ChronoFmtType::Custom(fmt) => { + write!(w, "{}", t.format(fmt)) + } } } } @@ -77,7 +68,7 @@ impl FormatTime for ChronoLocal { #[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq, Default)] pub struct ChronoUtc { - format: ChronoFmtType, + format: Arc, } impl ChronoUtc { @@ -88,7 +79,7 @@ impl ChronoUtc { /// [`ISO 8601`]: https://en.wikipedia.org/wiki/ISO_8601 pub fn rfc_3339() -> Self { Self { - format: ChronoFmtType::Rfc3339, + format: Arc::new(ChronoFmtType::Rfc3339), } } @@ -97,7 +88,7 @@ impl ChronoUtc { /// See [`chrono::format::strftime`] for details on the supported syntax. pub fn new(format_string: String) -> Self { Self { - format: ChronoFmtType::Custom(format_string), + format: Arc::new(ChronoFmtType::Custom(format_string)), } } } @@ -105,18 +96,40 @@ impl ChronoUtc { impl FormatTime for ChronoUtc { fn format_time(&self, w: &mut Writer<'_>) -> alloc::fmt::Result { let t = chrono::Utc::now(); - match &self.format { + match self.format.as_ref() { ChronoFmtType::Rfc3339 => w.write_str(&t.to_rfc3339()), ChronoFmtType::Custom(fmt) => w.write_str(&format!("{}", t.format(fmt))), } } } +/// The RFC 3339 format is used by default but a custom format string +/// can be used. See [`chrono::format::strftime`]for details on +/// the supported syntax. +/// +/// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] +#[derive(Debug, Clone, Eq, PartialEq)] +enum ChronoFmtType { + /// Format according to the RFC 3339 convention. + Rfc3339, + /// Format according to a custom format string. + Custom(String), +} + +impl Default for ChronoFmtType { + fn default() -> Self { + ChronoFmtType::Rfc3339 + } +} + #[cfg(test)] mod tests { use crate::fmt::format::Writer; use crate::fmt::time::FormatTime; + use std::sync::Arc; + use super::ChronoFmtType; use super::ChronoLocal; use super::ChronoUtc; @@ -127,17 +140,19 @@ mod tests { let mut dst: Writer<'_> = Writer::new(&mut buf); assert!(FormatTime::format_time(&ChronoUtc::default(), &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T19:05:08.662499+00:00" + assert!(chrono::DateTime::parse_from_str(&buf, "%FT%H:%M:%S%.6f%z").is_ok()); } #[test] fn test_chrono_format_time_utc_custom() { let fmt = ChronoUtc { - format: ChronoFmtType::Custom("%a %b %e %T %Y".to_owned()), + format: Arc::new(ChronoFmtType::Custom("%a %b %e %T %Y".to_owned())), }; let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); assert!(FormatTime::format_time(&fmt, &mut dst).is_ok()); // e.g. `buf` contains "Wed Aug 23 15:53:23 2023" + assert!(chrono::NaiveDateTime::parse_from_str(&buf, "%a %b %e %T %Y").is_ok()); } #[test] @@ -146,16 +161,18 @@ mod tests { let mut dst: Writer<'_> = Writer::new(&mut buf); assert!(FormatTime::format_time(&ChronoLocal::default(), &mut dst).is_ok()); // e.g. `buf` contains "2023-08-18T14:59:08.662499-04:00". + assert!(chrono::DateTime::parse_from_str(&buf, "%FT%H:%M:%S%.6f%z").is_ok()); } #[test] fn test_chrono_format_time_local_custom() { let fmt = ChronoLocal { - format: ChronoFmtType::Custom("%a %b %e %T %Y".to_owned()), + format: Arc::new(ChronoFmtType::Custom("%a %b %e %T %Y".to_owned())), }; let mut buf = String::new(); let mut dst: Writer<'_> = Writer::new(&mut buf); assert!(FormatTime::format_time(&fmt, &mut dst).is_ok()); // e.g. `buf` contains "Wed Aug 23 15:55:46 2023". + assert!(chrono::NaiveDateTime::parse_from_str(&buf, "%a %b %e %T %Y").is_ok()); } } From 56f35773b066bf91776ec2f098a591af94c24528 Mon Sep 17 00:00:00 2001 From: David Barsky Date: Fri, 22 Sep 2023 13:00:21 -0500 Subject: [PATCH 8/8] fix remaining nits --- tracing-subscriber/src/fmt/time/chrono_crate.rs | 1 - tracing-subscriber/src/fmt/time/mod.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/tracing-subscriber/src/fmt/time/chrono_crate.rs b/tracing-subscriber/src/fmt/time/chrono_crate.rs index e742f336c3..1a831efa1b 100644 --- a/tracing-subscriber/src/fmt/time/chrono_crate.rs +++ b/tracing-subscriber/src/fmt/time/chrono_crate.rs @@ -108,7 +108,6 @@ impl FormatTime for ChronoUtc { /// the supported syntax. /// /// [`chrono::format::strftime`]: https://docs.rs/chrono/0.4.9/chrono/format/strftime/index.html -#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] #[derive(Debug, Clone, Eq, PartialEq)] enum ChronoFmtType { /// Format according to the RFC 3339 convention. diff --git a/tracing-subscriber/src/fmt/time/mod.rs b/tracing-subscriber/src/fmt/time/mod.rs index a00c9522c2..87886ec797 100644 --- a/tracing-subscriber/src/fmt/time/mod.rs +++ b/tracing-subscriber/src/fmt/time/mod.rs @@ -18,7 +18,6 @@ pub use time_crate::LocalTime; /// [`chrono`]-based implementation for [`FormatTime`]. #[cfg(feature = "chrono")] -#[cfg_attr(docsrs, doc(cfg(feature = "local-time")))] mod chrono_crate; #[cfg(feature = "chrono")]