diff --git a/lading/src/observer/linux/procfs.rs b/lading/src/observer/linux/procfs.rs index 140231d3c..ad749c68b 100644 --- a/lading/src/observer/linux/procfs.rs +++ b/lading/src/observer/linux/procfs.rs @@ -80,8 +80,8 @@ impl Sampler { #[allow( clippy::similar_names, clippy::too_many_lines, - clippy::cast_possible_truncation, clippy::cast_sign_loss, + clippy::cast_possible_truncation, clippy::cast_possible_wrap )] pub(crate) async fn poll(&mut self) -> Result<(), Error> { @@ -89,16 +89,17 @@ impl Sampler { let mut samples: FxHashMap = FxHashMap::default(); let mut total_processes: u64 = 0; - // We maintain a tally of the total RSS and PSS consumed by the parent - // process and its children. - let mut aggr = memory::smaps_rollup::Aggregator::default(); - // Calculate the ticks since machine uptime. This will be important // later for calculating per-process uptime. Because we capture this one // we will be slightly out of date with each subsequent iteration of the // loop. We do not believe this to be an issue. let uptime_seconds: f64 = procfs::Uptime::current()?.uptime; // seconds since boot - let uptime_ticks: u64 = uptime_seconds.round() as u64 * self.ticks_per_second; // CPU-ticks since boot + let uptime_ticks: u64 = + (uptime_seconds.round() as u64).saturating_mul(self.ticks_per_second); // CPU-ticks since boot + + // A tally of the total RSS and PSS consumed by the parent process and + // its children. + let mut aggr = memory::smaps_rollup::Aggregator::default(); // Every sample run we collect all the child processes rooted at the // parent. As noted by the procfs documentation is this done by @@ -270,7 +271,7 @@ impl Sampler { // Number of threads this process has active. gauge!("num_threads", &labels).set(stats.num_threads as f64); - total_processes += 1; + total_processes = total_processes.saturating_add(1); // Also report memory data from `proc/status` as a reference point report_status_field!(status, labels, vmrss); @@ -282,10 +283,11 @@ impl Sampler { report_status_field!(status, labels, vmexe); report_status_field!(status, labels, vmlib); - // smaps and smaps_rollup are both governed by the same permission restrictions - // as /proc/[pid]/maps. Per man 5 proc: - // Permission to access this file is governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see ptrace(2). - // If a previous call to process.status() failed due to a lack of ptrace permissions, + // smaps and smaps_rollup are both governed by the same permission + // restrictions as /proc/[pid]/maps. Per man 5 proc: Permission to + // access this file is governed by a ptrace access mode + // PTRACE_MODE_READ_FSCREDS check; see ptrace(2). If a previous call + // to process.status() failed due to a lack of ptrace permissions, // then we assume smaps operations will fail as well. if has_ptrace_perm { // `/proc/{pid}/smaps` @@ -406,8 +408,8 @@ impl Sampler { } = key; Sample { - utime: acc.utime + sample.utime, - stime: acc.stime + sample.stime, + utime: acc.utime.saturating_add(sample.utime), + stime: acc.stime.saturating_add(sample.stime), // use parent process uptime uptime: if *pid == self.parent.pid() { sample.uptime diff --git a/lading/src/observer/linux/procfs/memory/smaps_rollup.rs b/lading/src/observer/linux/procfs/memory/smaps_rollup.rs index 02639e940..55765f94e 100644 --- a/lading/src/observer/linux/procfs/memory/smaps_rollup.rs +++ b/lading/src/observer/linux/procfs/memory/smaps_rollup.rs @@ -45,7 +45,7 @@ pub(crate) async fn poll( continue; }; - let value_kb = { + let value_bytes = { let value_token = next_token(line, &mut chars).ok_or(Error::Parsing(format!( "Could not parse numeric value from line: {line}" )))?; @@ -55,7 +55,7 @@ pub(crate) async fn poll( let numeric = value_token.parse::()?; match unit { - "kB" => Ok(numeric * BYTES_PER_KIBIBYTE), + "kB" => Ok(numeric.saturating_mul(BYTES_PER_KIBIBYTE)), unknown => Err(Error::Parsing(format!( "Unknown unit: {unknown} in line: {line}" ))), @@ -66,12 +66,12 @@ pub(crate) async fn poll( // Last character is a :, skip it. let field = name[..name_len - 1].to_snake_case(); match field.as_str() { - "rss" => aggr.rss += value_kb, - "pss" => aggr.pss += value_kb, + "rss" => aggr.rss = aggr.rss.saturating_add(value_bytes), + "pss" => aggr.pss = aggr.pss.saturating_add(value_bytes), _ => { /* ignore other fields */ } } let metric_name = format!("smaps_rollup.{field}"); - gauge!(metric_name, labels).set(value_kb as f64); + gauge!(metric_name, labels).set(value_bytes as f64); } Ok(())