metrale_telemetry/
clock.rs1use std::sync::OnceLock;
10use std::time::Instant;
11
12pub trait Clock: Send + Sync {
13 fn now_ns(&self) -> u64;
15 fn elapsed_ns(&self, since: Instant) -> u64;
17}
18
19#[derive(Debug, Default)]
22pub struct MonotonicClock;
23
24fn origin() -> Instant {
25 static ORIGIN: OnceLock<Instant> = OnceLock::new();
26 *ORIGIN.get_or_init(Instant::now)
27}
28
29fn nanos(d: std::time::Duration) -> u64 {
30 u64::try_from(d.as_nanos()).unwrap_or(u64::MAX)
31}
32
33impl Clock for MonotonicClock {
34 fn now_ns(&self) -> u64 {
35 nanos(origin().elapsed())
36 }
37 fn elapsed_ns(&self, since: Instant) -> u64 {
38 nanos(since.elapsed())
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn the_monotonic_clock_never_goes_backwards() {
48 let c = MonotonicClock;
49 let a = c.now_ns();
50 let b = c.now_ns();
51 assert!(b >= a);
52 assert!(c.elapsed_ns(Instant::now()) < 1_000_000_000);
53 }
54}