diff --git a/CHANGELOG.md b/CHANGELOG.md index d0e743c49..6900b876f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Added +- Retrieve memory, CPU information from cgroup controller for every pid observed on Linux. ## [0.22.0-rc1] ### Fixed diff --git a/lading/Cargo.toml b/lading/Cargo.toml index 5ecdda839..c85f6a942 100644 --- a/lading/Cargo.toml +++ b/lading/Cargo.toml @@ -54,7 +54,7 @@ uuid = { workspace = true } zstd = "0.13.1" [target.'cfg(target_os = "linux")'.dependencies] -cgroups-rs = "0.3" +cgroups-rs = { version = "0.3", default-features = false, features = [] } procfs = { version = "0.15", default-features = false, features = [] } async-pidfd = "0.1" diff --git a/lading/src/observer/linux.rs b/lading/src/observer/linux.rs index 726ae6d06..3d0d8fefd 100644 --- a/lading/src/observer/linux.rs +++ b/lading/src/observer/linux.rs @@ -357,6 +357,9 @@ impl Sampler { if let Some(memory_controller) = cgroup.controller_of::() { + let mut labels = Vec::from(&labels); + labels.push(("cgroup", String::from(cgroup.path()))); + let mem_stat = memory_controller.memory_stat(); let inactive_file = if cgroup.v2() { @@ -372,6 +375,40 @@ impl Sampler { }; gauge!("working_set_bytes", &labels).set(working_set as f64); + gauge!("memory.working_set_bytes", &labels).set(working_set as f64); + + gauge!("memory.fail_cnt", &labels).set(mem_stat.fail_cnt as f64); + gauge!("memory.limit_bytes", &labels).set(mem_stat.limit_in_bytes as f64); + gauge!("memory.usage_in_bytes", &labels).set(mem_stat.usage_in_bytes as f64); + gauge!("memory.max_usage_in_bytes", &labels) + .set(mem_stat.max_usage_in_bytes as f64); + gauge!("memory.soft_limit_in_bytes", &labels) + .set(mem_stat.soft_limit_in_bytes as f64); + } + // Load the CPU controller and get the cpu.stat String out of the + // cgroup, parse whatever fields are present and report them back + // out as metrics. + if let Some(cpu_controller) = cgroup.controller_of::() { + let mut labels = Vec::from(&labels); + labels.push(("cgroup", String::from(cgroup.path()))); + + let cpu = cpu_controller.cpu(); + for line in cpu.stat.lines() { + let mut fields = line.split_whitespace(); + let metric_name = fields.next().unwrap_or_default(); + let value = fields.next().unwrap_or_default(); + gauge!(format!("cpu.{metric_name}"), &labels) + .set(value.parse::().unwrap_or_default()); + } + if let Ok(shares) = cpu_controller.shares() { + gauge!("cpu.shares", &labels).set(shares as f64); + } + if let Ok(cfs_period) = cpu_controller.cfs_period() { + gauge!("cpu.cfs_period", &labels).set(cfs_period as f64); + } + if let Ok(cfs_quota) = cpu_controller.cfs_quota() { + gauge!("cpu.cfs_quota", &labels).set(cfs_quota as f64); + } } }