metrale_telemetry/
clock.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-26: The clock [`crate::hub::Telemetry`] reads, injected so a test
4//! can count its reads (`tests/zero_cost_off.rs`).
5//!
6//! Owner: telemetry.
7//! Invariants: none beyond the types.
8
9use std::sync::OnceLock;
10use std::time::Instant;
11
12pub trait Clock: Send + Sync {
13    /// 2026-09-26: Nanoseconds on a monotonic timeline private to this clock.
14    fn now_ns(&self) -> u64;
15    /// 2026-09-26: Nanoseconds since `since`.
16    fn elapsed_ns(&self, since: Instant) -> u64;
17}
18
19/// 2026-09-26: The process's monotonic clock. Its origin is the first
20/// `now_ns` of any `MonotonicClock` in the process.
21#[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}