Skip to main content

agentsight_capture_core/
time.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 eunomia-bpf org.
3
4//! Timestamp conversion utilities
5//!
6//! All timestamps in the system are standardized to milliseconds since UNIX epoch
7//! for consistency and ease of use in the frontend.
8
9use std::sync::OnceLock;
10use std::time::{SystemTime, UNIX_EPOCH};
11
12/// Cached boot time in seconds since UNIX epoch
13static BOOT_TIME_SECS: OnceLock<i64> = OnceLock::new();
14
15/// Get the system boot time in seconds since UNIX epoch
16///
17/// This uses the platform process backend and caches the result.
18pub fn get_boot_time_secs() -> i64 {
19    *BOOT_TIME_SECS.get_or_init(|| {
20        if let Ok(boot_time) = i64::try_from(sysinfo::System::boot_time())
21            && boot_time > 0
22        {
23            return boot_time;
24        }
25
26        let now_secs = SystemTime::now()
27            .duration_since(UNIX_EPOCH)
28            .unwrap()
29            .as_secs() as i64;
30        let uptime_secs = i64::try_from(sysinfo::System::uptime())
31            .ok()
32            .filter(|uptime| *uptime > 0)
33            .unwrap_or(1);
34        now_secs.saturating_sub(uptime_secs)
35    })
36}
37
38/// Convert nanoseconds since boot to milliseconds since UNIX epoch
39///
40/// This is used to convert eBPF timestamps (from bpf_ktime_get_ns()) to standard UNIX timestamps.
41///
42/// # Arguments
43/// * `ns_since_boot` - Nanoseconds since system boot (from bpf_ktime_get_ns())
44///
45/// # Returns
46/// Milliseconds since UNIX epoch (1970-01-01 00:00:00 UTC)
47pub fn boot_ns_to_epoch_ms(ns_since_boot: u64) -> u64 {
48    let boot_time_secs = get_boot_time_secs();
49    let boot_time_ms = boot_time_secs * 1000;
50    let offset_ms = (ns_since_boot / 1_000_000) as i64;
51    (boot_time_ms + offset_ms) as u64
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_boot_time_is_reasonable() {
60        let boot_time = get_boot_time_secs();
61        // Boot time should be in the past (less than current time)
62        let now = SystemTime::now()
63            .duration_since(UNIX_EPOCH)
64            .unwrap()
65            .as_secs() as i64;
66        assert!(boot_time < now);
67        // Boot time should be reasonable (after year 2020)
68        assert!(boot_time > 1577836800); // 2020-01-01
69    }
70
71    #[test]
72    fn test_boot_ns_to_epoch_ms_conversion() {
73        // Test with a known timestamp: 1000 seconds after boot
74        let ns_since_boot = 1_000_000_000_000u64; // 1000 seconds in nanoseconds
75        let result_ms = boot_ns_to_epoch_ms(ns_since_boot);
76
77        let boot_time = get_boot_time_secs();
78        let expected_ms = (boot_time + 1000) * 1000;
79
80        assert_eq!(result_ms, expected_ms as u64);
81    }
82}