From 0b6228c759f6acf50da44849ff472c0ed8d681db Mon Sep 17 00:00:00 2001 From: "Brian L. Troutwine" Date: Thu, 12 Dec 2024 18:03:11 -0800 Subject: [PATCH] Split reading of `/proc/pid/updtime` into module This commit is a mechanical move of the function that reads uptime data under the procfs/ module. It's intended to keep the code tidy. Signed-off-by: Brian L. Troutwine --- lading/src/observer/linux/procfs.rs | 50 ++------------------ lading/src/observer/linux/procfs/uptime.rs | 53 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 45 deletions(-) create mode 100644 lading/src/observer/linux/procfs/uptime.rs diff --git a/lading/src/observer/linux/procfs.rs b/lading/src/observer/linux/procfs.rs index 203aace1e8..60df209884 100644 --- a/lading/src/observer/linux/procfs.rs +++ b/lading/src/observer/linux/procfs.rs @@ -1,6 +1,7 @@ /// Sampler implementation for procfs filesystems mod memory; mod stat; +mod uptime; use std::{collections::VecDeque, io}; @@ -28,12 +29,9 @@ pub enum Error { /// Wrapper for [`stat::Error`] #[error("Unable to read stat: {0}")] Stat(#[from] stat::Error), - /// Unable to parse /proc/uptime - #[error("/proc/uptime malformed: {0}")] - MalformedUptime(&'static str), - /// Unable to parse floating point - #[error("Float Parsing: {0}")] - ParseFloat(#[from] std::num::ParseFloatError), + /// Wrapper for [`uptime::Error`] + #[error("Unable to read uptime: {0}")] + Uptime(#[from] uptime::Error), } macro_rules! report_status_field { @@ -142,7 +140,7 @@ impl Sampler { report_status_field!(status, labels, vmexe); report_status_field!(status, labels, vmlib); - let uptime = proc_uptime().await?; + let uptime = uptime::poll().await?; // `/proc/{pid}/stat`, most especially per-process CPU data. if let Err(e) = stat::poll(pid, uptime, &labels).await { @@ -285,41 +283,3 @@ async fn proc_cmdline(pid: i32) -> Result { }; Ok(res) } - -/// Read `/proc/uptime` -async fn proc_uptime() -> Result { - let buf = tokio::fs::read_to_string("/proc/uptime").await?; - let uptime_secs = proc_uptime_inner(&buf)?; - Ok(uptime_secs) -} - -/// Parse `/proc/uptime` to extract total uptime in seconds. -/// -/// # Errors -/// -/// Function errors if the file is malformed. -#[inline] -fn proc_uptime_inner(contents: &str) -> Result { - // TODO this should probably be scooted up to procfs.rs. Implies the - // `proc_*` functions there need a test component, making this an inner - // function eventually. - - let fields: Vec<&str> = contents.split_whitespace().collect(); - if fields.is_empty() { - return Err(Error::MalformedUptime("/proc/uptime empty")); - } - let uptime_secs = fields[0].parse::()?; - Ok(uptime_secs) -} - -#[cfg(test)] -mod test { - use super::proc_uptime_inner; - - #[test] - fn parse_uptime_basic() { - let line = "12345.67 4321.00\n"; - let uptime = proc_uptime_inner(line).unwrap(); - assert!((uptime - 12345.67).abs() < f64::EPSILON); - } -} diff --git a/lading/src/observer/linux/procfs/uptime.rs b/lading/src/observer/linux/procfs/uptime.rs new file mode 100644 index 0000000000..e548be1380 --- /dev/null +++ b/lading/src/observer/linux/procfs/uptime.rs @@ -0,0 +1,53 @@ +#[derive(thiserror::Error, Debug)] +/// Errors produced by functions in this module +pub enum Error { + /// Wrapper for [`std::io::Error`] + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + /// Unable to parse /proc/uptime + #[error("/proc/uptime malformed: {0}")] + Malformed(&'static str), + /// Unable to parse floating point + #[error("Float Parsing: {0}")] + ParseFloat(#[from] std::num::ParseFloatError), +} + +/// Read `/proc/uptime` +/// +/// Only the first field is used, which is the total uptime in seconds. +pub(crate) async fn poll() -> Result { + let buf = tokio::fs::read_to_string("/proc/uptime").await?; + let uptime_secs = proc_uptime_inner(&buf)?; + Ok(uptime_secs) +} + +/// Parse `/proc/uptime` to extract total uptime in seconds. +/// +/// # Errors +/// +/// Function errors if the file is malformed. +#[inline] +fn proc_uptime_inner(contents: &str) -> Result { + // TODO this should probably be scooted up to procfs.rs. Implies the + // `proc_*` functions there need a test component, making this an inner + // function eventually. + + let fields: Vec<&str> = contents.split_whitespace().collect(); + if fields.is_empty() { + return Err(Error::Malformed("/proc/uptime empty")); + } + let uptime_secs = fields[0].parse::()?; + Ok(uptime_secs) +} + +#[cfg(test)] +mod test { + use super::proc_uptime_inner; + + #[test] + fn parse_uptime_basic() { + let line = "12345.67 4321.00\n"; + let uptime = proc_uptime_inner(line).unwrap(); + assert!((uptime - 12345.67).abs() < f64::EPSILON); + } +}