| 1 | /// A type that can measure and format the current time. | 
| 2 | /// | 
|---|
| 3 | /// This trait is used by [HierarchicalLayer] to include a timestamp with each | 
|---|
| 4 | /// [Event] when it is logged. | 
|---|
| 5 | /// | 
|---|
| 6 | /// Notable default implementations of this trait are [LocalDateTime] and `()`. | 
|---|
| 7 | /// The former prints the current time as reported by [time's OffsetDateTime] | 
|---|
| 8 | /// (note that it requires a `time` feature to be enabled and may panic! | 
|---|
| 9 | /// make sure to check out the docs for the [LocalDateTime]), | 
|---|
| 10 | /// and the latter does not print the current time at all. | 
|---|
| 11 | /// | 
|---|
| 12 | /// Inspired by the [FormatTime] trait from [tracing-subscriber]. | 
|---|
| 13 | /// | 
|---|
| 14 | /// [HierarchicalLayer]: crate::HierarchicalLayer | 
|---|
| 15 | /// [Event]: tracing_core::Event | 
|---|
| 16 | /// [time's OffsetDateTime]: time::OffsetDateTime | 
|---|
| 17 | /// [FormatTime]: tracing_subscriber::fmt::time::FormatTime | 
|---|
| 18 | /// [tracing-subscriber]: tracing_subscriber | 
|---|
| 19 | // NB: | 
|---|
| 20 | //   We can't use `tracing_subscriber::fmt::format::Writer` | 
|---|
| 21 | //   since it doesn't have a public constructor. | 
|---|
| 22 | pub trait FormatTime { | 
|---|
| 23 | fn format_time(&self, w: &mut impl std::fmt::Write) -> std::fmt::Result; | 
|---|
| 24 | } | 
|---|
| 25 |  | 
|---|
| 26 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 27 |  | 
|---|
| 28 | /// Default do-nothing time formatter. | 
|---|
| 29 | impl FormatTime for () { | 
|---|
| 30 | fn format_time(&self, _w: &mut impl std::fmt::Write) -> std::fmt::Result { | 
|---|
| 31 | Ok(()) | 
|---|
| 32 | } | 
|---|
| 33 | } | 
|---|
| 34 |  | 
|---|
| 35 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 36 |  | 
|---|
| 37 | /// Retrieve and print the current wall-clock time in UTC timezone. | 
|---|
| 38 | #[ cfg(feature = "time")] | 
|---|
| 39 | #[ derive(Debug, Clone, Copy, Eq, PartialEq, Default)] | 
|---|
| 40 | pub struct UtcDateTime; | 
|---|
| 41 |  | 
|---|
| 42 | #[ cfg(feature = "time")] | 
|---|
| 43 | impl FormatTime for UtcDateTime { | 
|---|
| 44 | fn format_time(&self, w: &mut impl std::fmt::Write) -> std::fmt::Result { | 
|---|
| 45 | let time = time::OffsetDateTime::now_utc(); | 
|---|
| 46 | write!(w, "{} {}", time.date(), time.time()) | 
|---|
| 47 | } | 
|---|
| 48 | } | 
|---|
| 49 |  | 
|---|
| 50 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 51 |  | 
|---|
| 52 | /// Retrieve and print the current wall-clock time. | 
|---|
| 53 | /// | 
|---|
| 54 | /// # Panics | 
|---|
| 55 | /// | 
|---|
| 56 | /// Panics if [time crate] cannot determine the local UTC offset. | 
|---|
| 57 | /// | 
|---|
| 58 | /// [time crate]: time | 
|---|
| 59 | // NB: | 
|---|
| 60 | //   Can't use `tracing_subscriber::fmt::time::SystemTime` since it uses | 
|---|
| 61 | //   private `datetime` module to format the actual time. | 
|---|
| 62 | #[ cfg(feature = "time")] | 
|---|
| 63 | #[ derive(Debug, Clone, Copy, Eq, PartialEq, Default)] | 
|---|
| 64 | pub struct LocalDateTime; | 
|---|
| 65 |  | 
|---|
| 66 | #[ cfg(feature = "time")] | 
|---|
| 67 | impl FormatTime for LocalDateTime { | 
|---|
| 68 | fn format_time(&self, w: &mut impl std::fmt::Write) -> std::fmt::Result { | 
|---|
| 69 | let time = time::OffsetDateTime::now_local().expect( "time offset cannot be determined"); | 
|---|
| 70 | write!(w, "{}", time) | 
|---|
| 71 | } | 
|---|
| 72 | } | 
|---|
| 73 |  | 
|---|
| 74 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 75 |  | 
|---|
| 76 | /// Retrieve and print the relative elapsed wall-clock time since an epoch. | 
|---|
| 77 | /// | 
|---|
| 78 | /// The `Default` implementation for `Uptime` makes the epoch the current time. | 
|---|
| 79 | // NB: Copy-pasted from `tracing-subscriber::fmt::time::Uptime`. | 
|---|
| 80 | #[ derive(Debug, Clone, Copy, Eq, PartialEq)] | 
|---|
| 81 | pub struct Uptime { | 
|---|
| 82 | epoch: std::time::Instant, | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | impl Default for Uptime { | 
|---|
| 86 | fn default() -> Self { | 
|---|
| 87 | Uptime { | 
|---|
| 88 | epoch: std::time::Instant::now(), | 
|---|
| 89 | } | 
|---|
| 90 | } | 
|---|
| 91 | } | 
|---|
| 92 |  | 
|---|
| 93 | impl From<std::time::Instant> for Uptime { | 
|---|
| 94 | fn from(epoch: std::time::Instant) -> Self { | 
|---|
| 95 | Uptime { epoch } | 
|---|
| 96 | } | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | impl FormatTime for Uptime { | 
|---|
| 100 | fn format_time(&self, w: &mut impl std::fmt::Write) -> std::fmt::Result { | 
|---|
| 101 | let e: Duration = self.epoch.elapsed(); | 
|---|
| 102 | write!(w, "{:4} .{:06} s", e.as_secs(), e.subsec_micros()) | 
|---|
| 103 | } | 
|---|
| 104 | } | 
|---|
| 105 |  | 
|---|
| 106 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| 107 |  | 
|---|
| 108 | impl<'a, F> FormatTime for &'a F | 
|---|
| 109 | where | 
|---|
| 110 | F: FormatTime, | 
|---|
| 111 | { | 
|---|
| 112 | fn format_time(&self, w: &mut impl std::fmt::Write) -> std::fmt::Result { | 
|---|
| 113 | (*self).format_time(w) | 
|---|
| 114 | } | 
|---|
| 115 | } | 
|---|
| 116 |  | 
|---|
| 117 | // NB: | 
|---|
| 118 | //   Can't impl for `fn(&mut impl std::fmt::Write)` since impl trait is not allowed | 
|---|
| 119 | //   outside of function and inherent method return types for now. | 
|---|
| 120 |  | 
|---|