refactor(stats-daemon): split into cpu/mem/temp/gpu modules, add gpu support
This commit is contained in:
parent
1edd14cf30
commit
76ccc99e17
5 changed files with 532 additions and 414 deletions
112
stats-daemon/src/mem.rs
Normal file
112
stats-daemon/src/mem.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use std::fs;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct MemInfo {
|
||||
pub percent: u64,
|
||||
pub used_gb: f64,
|
||||
pub total_gb: f64,
|
||||
pub avail_gb: f64,
|
||||
pub cached_gb: f64,
|
||||
pub buffers_gb: f64,
|
||||
}
|
||||
|
||||
pub fn parse_meminfo(input: &str) -> Option<MemInfo> {
|
||||
let mut total = 0u64;
|
||||
let mut avail = 0u64;
|
||||
let mut buffers = 0u64;
|
||||
let mut cached = 0u64;
|
||||
let mut sreclaimable = 0u64;
|
||||
|
||||
for line in input.lines() {
|
||||
let mut parts = line.splitn(2, ':');
|
||||
let key = parts.next().unwrap_or("").trim();
|
||||
let val: u64 = parts
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.parse()
|
||||
.unwrap_or(0);
|
||||
match key {
|
||||
"MemTotal" => total = val,
|
||||
"MemAvailable" => avail = val,
|
||||
"Buffers" => buffers = val,
|
||||
"Cached" => cached = val,
|
||||
"SReclaimable" => sreclaimable = val,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if total == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let used = total.saturating_sub(avail);
|
||||
let cached_total = cached + sreclaimable;
|
||||
let gb = |kb: u64| kb as f64 / 1_048_576.0;
|
||||
|
||||
Some(MemInfo {
|
||||
percent: used * 100 / total,
|
||||
used_gb: gb(used),
|
||||
total_gb: gb(total),
|
||||
avail_gb: gb(avail),
|
||||
cached_gb: gb(cached_total),
|
||||
buffers_gb: gb(buffers),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn emit_mem(out: &mut impl Write) {
|
||||
let content = fs::read_to_string("/proc/meminfo").unwrap_or_default();
|
||||
if let Some(m) = parse_meminfo(&content) {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"{{\"type\":\"mem\",\"percent\":{},\"used_gb\":{:.3},\"total_gb\":{:.3},\"avail_gb\":{:.3},\"cached_gb\":{:.3},\"buffers_gb\":{:.3}}}",
|
||||
m.percent, m.used_gb, m.total_gb, m.avail_gb, m.cached_gb, m.buffers_gb,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const MEMINFO_SAMPLE: &str = "\
|
||||
MemTotal: 16384000 kB
|
||||
MemFree: 2048000 kB
|
||||
MemAvailable: 4096000 kB
|
||||
Buffers: 512000 kB
|
||||
Cached: 3072000 kB
|
||||
SReclaimable: 512000 kB
|
||||
SwapTotal: 8192000 kB
|
||||
SwapFree: 8192000 kB";
|
||||
|
||||
#[test]
|
||||
fn parse_meminfo_percent() {
|
||||
let m = parse_meminfo(MEMINFO_SAMPLE).unwrap();
|
||||
assert_eq!(m.percent, 75);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_meminfo_total_gb() {
|
||||
let m = parse_meminfo(MEMINFO_SAMPLE).unwrap();
|
||||
assert!((m.total_gb - 15.625).abs() < 0.001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_meminfo_cached_includes_sreclaimable() {
|
||||
let m = parse_meminfo(MEMINFO_SAMPLE).unwrap();
|
||||
let expected = 3_584_000.0 / 1_048_576.0;
|
||||
assert!((m.cached_gb - expected).abs() < 0.001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_meminfo_zero_total_returns_none() {
|
||||
assert!(parse_meminfo("MemFree: 1000 kB\n").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_meminfo_empty_returns_none() {
|
||||
assert!(parse_meminfo("").is_none());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue