pub fn parse_threshold_mb(raw: Option<&str>) -> u64 {
match raw {
None => 450,
Some(s) => s.parse().unwrap_or(450),
}
}
pub fn recycle_threshold_mb() -> u64 {
parse_threshold_mb(std::env::var("OCSERVE_SIDECAR_RECYCLE_MB").ok().as_deref())
}
pub fn should_recycle(
threshold_mb: u64,
rss_mb: u64,
consecutive_high: u32,
in_flight: usize,
uptime_s: u64,
) -> bool {
threshold_mb > 0
&& rss_mb >= threshold_mb
&& consecutive_high >= 2
&& in_flight == 0
&& uptime_s >= 300
}
pub fn parse_pressure_avg10(text: &str) -> Option<i64> {
let some = text.lines().find(|l| l.starts_with("some "))?;
let tok = some.split_whitespace().find(|t| t.starts_with("avg10="))?;
let v: f64 = tok.trim_start_matches("avg10=").parse().ok()?;
Some((v * 100.0).round() as i64)
}
pub fn psi_avg10_centi() -> Option<i64> {
let cg = std::fs::read_to_string("/proc/self/cgroup").ok()?;
let path = cg.lines().find_map(|l| l.strip_prefix("0::"))?.trim();
let text = std::fs::read_to_string(format!("/sys/fs/cgroup{path}/memory.pressure")).ok()?;
parse_pressure_avg10(&text)
}
pub fn rss_of_pid(pid: u32) -> Option<i64> {
if pid == 0 {
return None;
}
let status = std::fs::read_to_string(format!("/proc/{pid}/status")).ok()?;
status
.lines()
.find(|l| l.starts_with("VmRSS:"))?
.split_whitespace()
.nth(1)?
.parse::<i64>()
.ok()
.map(|kb| kb * 1024)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn threshold_defaults_and_kill_switch() {
assert_eq!(parse_threshold_mb(None), 450);
assert_eq!(parse_threshold_mb(Some("0")), 0);
assert_eq!(parse_threshold_mb(Some("600")), 600);
assert_eq!(parse_threshold_mb(Some("junk")), 450); }
#[test]
fn recycle_needs_every_condition() {
assert!(should_recycle(450, 500, 2, 0, 400));
assert!(!should_recycle(0, 9999, 9, 0, 9999));
assert!(!should_recycle(450, 449, 2, 0, 400));
assert!(!should_recycle(450, 500, 1, 0, 400));
assert!(!should_recycle(450, 500, 2, 1, 400));
assert!(!should_recycle(450, 500, 2, 0, 299));
assert!(should_recycle(450, 500, 2, 0, 300));
}
#[test]
fn pressure_line_parses() {
let text = "some avg10=12.34 avg60=3.00 avg300=1.00 total=251798\nfull avg10=0.00 avg60=0.00 avg300=0.00 total=250908\n";
assert_eq!(parse_pressure_avg10(text), Some(1234));
assert_eq!(parse_pressure_avg10("some avg10=0.00 total=0\n"), Some(0));
assert_eq!(parse_pressure_avg10("full avg10=0.00 total=0\n"), None); assert_eq!(parse_pressure_avg10("garbage"), None);
}
#[test]
fn rss_reads_own_process() {
let me = std::process::id();
assert!(rss_of_pid(me).unwrap_or(0) > 0);
assert_eq!(rss_of_pid(0), None);
assert_eq!(rss_of_pid(4194305), None); }
#[test]
fn live_psi_is_readable_or_absent() {
let _ = psi_avg10_centi();
}
}