performance improvements and formatting cleanup
This commit is contained in:
@@ -4,19 +4,23 @@ use crate::gpu::collect_all_gpus;
|
||||
use crate::state::AppState;
|
||||
use crate::types::{DiskInfo, Metrics, NetworkInfo, ProcessInfo};
|
||||
|
||||
use sysinfo::{Components, Disks, Networks, System};
|
||||
use std::cmp::Ordering;
|
||||
use sysinfo::{ProcessesToUpdate, System};
|
||||
use tracing::warn;
|
||||
|
||||
pub async fn collect_metrics(state: &AppState) -> Metrics {
|
||||
let mut sys = state.sys.lock().await;
|
||||
|
||||
// Targeted refresh: CPU/mem/processes only
|
||||
if let Err(e) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
sys.refresh_all();
|
||||
sys.refresh_cpu_usage();
|
||||
sys.refresh_memory();
|
||||
sys.refresh_processes(ProcessesToUpdate::All, true);
|
||||
})) {
|
||||
warn!("sysinfo refresh panicked: {e:?}");
|
||||
warn!("sysinfo selective refresh panicked: {e:?}");
|
||||
}
|
||||
|
||||
// Hostname (associated fn on System in 0.37)
|
||||
// Hostname
|
||||
let hostname = System::host_name().unwrap_or_else(|| "unknown".to_string());
|
||||
|
||||
// CPU usage
|
||||
@@ -29,52 +33,82 @@ pub async fn collect_metrics(state: &AppState) -> Metrics {
|
||||
let swap_total = sys.total_swap();
|
||||
let swap_used = sys.used_swap();
|
||||
|
||||
// Temperature (via Components container)
|
||||
let components = Components::new_with_refreshed_list();
|
||||
let cpu_temp_c = components.iter().find_map(|c| {
|
||||
let l = c.label().to_ascii_lowercase();
|
||||
if l.contains("cpu") || l.contains("package") || l.contains("tctl") || l.contains("tdie") {
|
||||
c.temperature()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
drop(sys); // release quickly before touching other locks
|
||||
|
||||
// Components (cached): just refresh temps
|
||||
let cpu_temp_c = {
|
||||
let mut components = state.components.lock().await;
|
||||
components.refresh(true);
|
||||
components.iter().find_map(|c| {
|
||||
let l = c.label().to_ascii_lowercase();
|
||||
if l.contains("cpu") || l.contains("package") || l.contains("tctl") || l.contains("tdie") {
|
||||
c.temperature()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// Disks (cached): refresh sizes/usage, reuse enumeration
|
||||
let disks: Vec<DiskInfo> = {
|
||||
let mut disks_list = state.disks.lock().await;
|
||||
disks_list.refresh(true);
|
||||
disks_list
|
||||
.iter()
|
||||
.map(|d| DiskInfo {
|
||||
name: d.name().to_string_lossy().into_owned(),
|
||||
total: d.total_space(),
|
||||
available: d.available_space(),
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
// Networks (cached): refresh counters
|
||||
let networks: Vec<NetworkInfo> = {
|
||||
let mut nets = state.networks.lock().await;
|
||||
nets.refresh(true);
|
||||
nets.iter()
|
||||
.map(|(name, data)| NetworkInfo {
|
||||
name: name.to_string(),
|
||||
received: data.total_received(),
|
||||
transmitted: data.total_transmitted()
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
// Processes: only collect fields we use (pid, name, cpu, mem), keep top K efficiently
|
||||
const TOP_K: usize = 30;
|
||||
let mut procs: Vec<ProcessInfo> = {
|
||||
let sys = state.sys.lock().await; // re-lock briefly to read processes
|
||||
sys.processes()
|
||||
.values()
|
||||
.map(|p| ProcessInfo {
|
||||
pid: p.pid().as_u32(),
|
||||
name: p.name().to_string_lossy().into_owned(),
|
||||
cpu_usage: p.cpu_usage(),
|
||||
mem_bytes: p.memory()
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
||||
if procs.len() > TOP_K {
|
||||
procs.select_nth_unstable_by(TOP_K, |a, b| {
|
||||
b.cpu_usage
|
||||
.partial_cmp(&a.cpu_usage)
|
||||
.unwrap_or(Ordering::Equal)
|
||||
});
|
||||
procs.truncate(TOP_K);
|
||||
}
|
||||
procs.sort_by(|a, b| {
|
||||
b.cpu_usage
|
||||
.partial_cmp(&a.cpu_usage)
|
||||
.unwrap_or(Ordering::Equal)
|
||||
});
|
||||
|
||||
// Disks (via Disks container)
|
||||
let disks_list = Disks::new_with_refreshed_list();
|
||||
let disks: Vec<DiskInfo> = disks_list
|
||||
.iter()
|
||||
.map(|d| DiskInfo {
|
||||
name: d.name().to_string_lossy().into_owned(),
|
||||
total: d.total_space(),
|
||||
available: d.available_space(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Networks (via Networks container) – include interface name
|
||||
let nets = Networks::new_with_refreshed_list();
|
||||
let networks: Vec<NetworkInfo> = nets
|
||||
.iter()
|
||||
.map(|(name, data)| NetworkInfo {
|
||||
name: name.to_string(),
|
||||
received: data.total_received(),
|
||||
transmitted: data.total_transmitted(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Processes (top N by CPU)
|
||||
let mut procs: Vec<ProcessInfo> = sys
|
||||
.processes()
|
||||
.values()
|
||||
.map(|p| ProcessInfo {
|
||||
pid: p.pid().as_u32(),
|
||||
name: p.name().to_string_lossy().into_owned(),
|
||||
cpu_usage: p.cpu_usage(),
|
||||
mem_bytes: p.memory(),
|
||||
})
|
||||
.collect();
|
||||
procs.sort_by(|a, b| b.cpu_usage.partial_cmp(&a.cpu_usage).unwrap_or(std::cmp::Ordering::Equal));
|
||||
procs.truncate(30);
|
||||
let process_count = {
|
||||
let sys = state.sys.lock().await;
|
||||
sys.processes().len()
|
||||
};
|
||||
|
||||
// GPU(s)
|
||||
let gpus = match collect_all_gpus() {
|
||||
@@ -93,12 +127,12 @@ pub async fn collect_metrics(state: &AppState) -> Metrics {
|
||||
mem_used,
|
||||
swap_total,
|
||||
swap_used,
|
||||
process_count: sys.processes().len(),
|
||||
process_count,
|
||||
hostname,
|
||||
cpu_temp_c,
|
||||
disks,
|
||||
networks,
|
||||
top_processes: procs,
|
||||
gpus,
|
||||
gpus
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user