subscriber: add ChronoUtc and ChronoLocal timers, RFC 3339 support (#387)

* subscriber: add ChronoUtc and ChronoLocal timers
* subscriber: ChronoLocal::rfc3339,ChronoUtc::rfc3339
* subscriber: make with_format constructor for ChronoUtc, ChronoLocal
This commit is contained in:
Evan Schwartz 2019-10-17 17:34:19 -04:00 committed by Eliza Weisman
parent 6e9d9c486a
commit f19f63f83d
3 changed files with 131 additions and 2 deletions

View File

@ -141,7 +141,17 @@ impl<F, T> Format<F, T> {
}
}
/// Use the given `timer` for log message timestamps.
/// Use the given [`timer`] for log message timestamps.
///
/// See [`time`] for the provided timer implementations.
///
/// Note that using the `chrono` feature flag enables the
/// additional time formatters [`ChronoUtc`] and [`ChronoLocal`].
///
/// [`time`]: ./time/index.html
/// [`timer`]: ./time/trait.FormatTime.html
/// [`ChronoUtc`]: ./time/struct.ChronoUtc.html
/// [`ChronoLocal`]: ./time/struct.ChronoLocal.html
pub fn with_timer<T2>(self, timer: T2) -> Format<F, T2> {
Format {
format: self.format,

View File

@ -457,7 +457,17 @@ impl<N, L, T, F, W> Builder<N, format::Format<L, T>, F, W>
where
N: for<'writer> FormatFields<'writer> + 'static,
{
/// Use the given `timer` for log message timestamps.
/// Use the given [`timer`] for log message timestamps.
///
/// See [`time`] for the provided timer implementations.
///
/// Note that using the `chrono` feature flag enables the
/// additional time formatters [`ChronoUtc`] and [`ChronoLocal`].
///
/// [`time`]: ./time/index.html
/// [`timer`]: ./time/trait.FormatTime.html
/// [`ChronoUtc`]: ./time/struct.ChronoUtc.html
/// [`ChronoLocal`]: ./time/struct.ChronoLocal.html
pub fn with_timer<T2>(self, timer: T2) -> Builder<N, format::Format<L, T2>, F, W> {
Builder {
fmt_fields: self.fmt_fields,

View File

@ -17,6 +17,10 @@ use std::time::Instant;
/// current time as reported by `std::time::SystemTime`, and the latter does not print the current
/// time at all. `FormatTime` is also automatically implemented for any function pointer with the
/// appropriate signature.
///
/// The full list of provided implementations can be found in [`time`].
///
/// [`time`]: ./index.html
pub trait FormatTime {
/// Measure and write out the current time.
///
@ -96,6 +100,111 @@ impl FormatTime for Uptime {
}
}
/// The RFC 3339 format is used by default and using
/// this struct allows chrono to bypass the parsing
/// used when a custom format string is provided
#[cfg(feature = "chrono")]
#[derive(Debug, Clone, Eq, PartialEq)]
enum ChronoFmtType {
Rfc3339,
Custom(String),
}
#[cfg(feature = "chrono")]
impl Default for ChronoFmtType {
fn default() -> Self {
ChronoFmtType::Rfc3339
}
}
/// Retrieve and print the current UTC time.
#[cfg(feature = "chrono")]
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ChronoUtc {
format: ChronoFmtType,
}
#[cfg(feature = "chrono")]
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 rfc3339() -> Self {
ChronoUtc {
format: ChronoFmtType::Rfc3339,
}
}
/// Format the time using the given format string.
///
/// 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
pub fn with_format(format_string: String) -> Self {
ChronoUtc {
format: ChronoFmtType::Custom(format_string),
}
}
}
#[cfg(feature = "chrono")]
impl FormatTime for ChronoUtc {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
let time = chrono::Utc::now();
match self.format {
ChronoFmtType::Rfc3339 => write!(w, "{} ", time.to_rfc3339()),
ChronoFmtType::Custom(ref format_str) => write!(w, "{} ", time.format(format_str)),
}
}
}
/// Retrieve and print the current local time.
#[cfg(feature = "chrono")]
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct ChronoLocal {
format: ChronoFmtType,
}
#[cfg(feature = "chrono")]
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 rfc3339() -> Self {
ChronoLocal {
format: ChronoFmtType::Rfc3339,
}
}
/// Format the time using the given format string.
///
/// 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
pub fn with_format(format_string: String) -> Self {
ChronoLocal {
format: ChronoFmtType::Custom(format_string),
}
}
}
#[cfg(feature = "chrono")]
impl FormatTime for ChronoLocal {
fn format_time(&self, w: &mut dyn fmt::Write) -> fmt::Result {
let time = chrono::Local::now();
match self.format {
ChronoFmtType::Rfc3339 => write!(w, "{} ", time.to_rfc3339()),
ChronoFmtType::Custom(ref format_str) => write!(w, "{} ", time.format(format_str)),
}
}
}
#[inline(always)]
#[cfg(feature = "ansi")]
pub(crate) fn write<T>(timer: T, writer: &mut dyn fmt::Write, with_ansi: bool) -> fmt::Result