yggdrasil/tasks/
sysinfo_sampler.rs1use std::sync::LazyLock;
11use std::time::Duration;
12
13use crate::models::system::SystemSnapshot;
14
15static SNAPSHOT: LazyLock<tokio::sync::RwLock<SystemSnapshot>> =
16 LazyLock::new(|| tokio::sync::RwLock::new(SystemSnapshot::default()));
17
18fn sample_interval() -> Duration {
20 let secs = std::env::var("SYSINFO_SAMPLE_SECS")
21 .ok()
22 .and_then(|s| s.parse::<f64>().ok())
23 .unwrap_or(0.5);
24 Duration::from_secs_f64(secs.max(0.05))
25}
26
27pub fn spawn_sampler() {
31 crate::tasks::spawn_supervised("sysinfo_sampler", async move {
32 use sysinfo::{Disks, System};
33
34 let mut sys = match System::new() {
35 Ok(sys) => sys,
36 Err(error) => {
37 tracing::warn!("sysinfo 不支持当前系统,主机指标保持默认值: {error}");
38 return;
39 }
40 };
41 let interval = sample_interval();
42 sys.refresh_cpu_usage();
44 let disks = Disks::new_with_refreshed_list().ok();
45
46 loop {
47 tokio::time::sleep(interval).await;
48 sys.refresh_cpu_usage();
49 sys.refresh_memory();
50 let load = System::load_average().unwrap_or_default();
51
52 let (disk_total, disk_available) = disks
54 .iter()
55 .flat_map(|disks| disks.iter())
56 .max_by_key(|d| d.total_space())
57 .map(|d| (d.total_space(), d.available_space()))
58 .unwrap_or((0, 0));
59
60 let snap = SystemSnapshot {
61 cpu_usage: sys.global_cpu_usage(),
62 load_avg_1: load.one,
63 total_memory: sys.total_memory(),
64 used_memory: sys.used_memory(),
65 disk_total,
66 disk_available,
67 os_name: System::long_os_version().unwrap_or_default(),
68 kernel_version: System::kernel_version().unwrap_or_default(),
69 uptime_secs: System::uptime().unwrap_or_default(),
70 };
71 *SNAPSHOT.write().await = snap;
72 }
73 });
74}
75
76pub async fn read_snapshot() -> SystemSnapshot {
78 SNAPSHOT.read().await.clone()
79}