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 | |