diff --git a/Cargo.toml b/Cargo.toml index 63b659b5..cc4618fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,12 +63,13 @@ strip = false battery = ["starship-battery"] gpu = ["nvidia"] nvidia = ["nvml-wrapper"] +zfs = [] # The features we use by default. -default = ["fern", "log", "battery", "gpu"] +default = ["fern", "log", "battery", "gpu", "zfs"] # The features we use on deploy. Logging is not included as that is primarily (for now) just for debugging locally. -deploy = ["battery", "gpu"] +deploy = ["battery", "gpu", "zfs"] [dependencies] anyhow = "1.0.69" diff --git a/src/app/data_harvester/memory/sysinfo.rs b/src/app/data_harvester/memory/sysinfo.rs index 22dd941a..521ba6d2 100644 --- a/src/app/data_harvester/memory/sysinfo.rs +++ b/src/app/data_harvester/memory/sysinfo.rs @@ -52,6 +52,45 @@ pub(crate) fn get_swap_data(sys: &System) -> Option { #[cfg(feature = "zfs")] pub(crate) fn get_arc_data() -> Option { let (mem_total_in_kib, mem_used_in_kib) = { + #[cfg(target_os = "linux")] + { + // TODO: [OPT] is this efficient? + use std::fs::read_to_string; + if let Ok(arcinfo) = read_to_string("/proc/spl/kstat/zfs/arcstats") { + let mut mem_arc = 0; + let mut mem_total = 0; + let mut zfs_keys_read: u8 = 0; + const ZFS_KEYS_NEEDED: u8 = 2; + + for line in arcinfo.lines() { + if let Some((label, value)) = line.split_once(' ') { + let to_write = match label { + "size" => &mut mem_arc, + "memory_all_bytes" => &mut mem_total, + _ => { + continue; + } + }; + + if let Some((_type, number)) = value.trim_start().rsplit_once(' ') { + // Parse the value, remember it's in bytes! + if let Ok(number) = number.parse::() { + *to_write = number; + // We only need a few keys, so we can bail early. + zfs_keys_read += 1; + if zfs_keys_read == ZFS_KEYS_NEEDED { + break; + } + } + } + } + } + (mem_total / 1024, mem_arc / 1024) + } else { + (0, 0) + } + } + #[cfg(target_os = "freebsd")] { use sysctl::Sysctl; @@ -70,10 +109,19 @@ pub(crate) fn get_arc_data() -> Option { (0, 0) } } + #[cfg(target_os = "macos")] + { + (0, 0) + } + #[cfg(target_os = "windows")] + { + (0, 0) + } }; + Some(MemHarvest { - mem_total_in_kib, - mem_used_in_kib, + total_kib: mem_total_in_kib, + used_kib: mem_used_in_kib, use_percent: if mem_total_in_kib == 0 { None } else { diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 6f1f05d5..d6ea25a4 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -572,22 +572,21 @@ pub fn convert_arc_labels( } } - if current_data.arc_harvest.mem_total_in_kib > 0 { + if current_data.arc_harvest.total_kib > 0 { Some(( format!( "{:3.0}%", current_data.arc_harvest.use_percent.unwrap_or(0.0) ), { - let (unit, denominator) = return_unit_and_denominator_for_mem_kib( - current_data.arc_harvest.mem_total_in_kib, - ); + let (unit, denominator) = + return_unit_and_denominator_for_mem_kib(current_data.arc_harvest.total_kib); format!( " {:.1}{}/{:.1}{}", - current_data.arc_harvest.mem_used_in_kib as f64 / denominator, + current_data.arc_harvest.used_kib as f64 / denominator, unit, - (current_data.arc_harvest.mem_total_in_kib as f64 / denominator), + (current_data.arc_harvest.total_kib as f64 / denominator), unit ) },