Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

style: refactor using iterators and chaining #128

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 55 additions & 66 deletions src/sensors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,8 @@ impl Topology {
/// Generates CPUCore instances for the host and adds them
/// to appropriate CPUSocket instance from self.sockets
pub fn add_cpu_cores(&mut self) {
let mut cores = Topology::generate_cpu_cores().unwrap();
while !cores.is_empty() {
let c = cores.pop().unwrap();
let socket_id = &c
Topology::generate_cpu_cores().unwrap().into_iter().for_each(|core| {
let socket_id = &core
.attributes
.get("physical id")
.unwrap()
Expand All @@ -262,9 +260,9 @@ impl Topology {
.find(|x| &x.id == socket_id)
.expect("Trick: if you are running on a vm, do not forget to use --vm parameter invoking scaphandre at the command line");
if socket_id == &socket.id {
socket.add_cpu_core(c);
socket.add_cpu_core(core);
}
}
});
}

/// Triggers ProcessTracker refresh on process stats
Expand Down Expand Up @@ -298,10 +296,8 @@ impl Topology {

for p in current_procs {
let pid = p.pid;
let res = self.proc_tracker.add_process_record(p);
match res {
Ok(_) => {}
Err(msg) => panic!("Failed to track process with pid {} !\nGot: {}", pid, msg),
if let Err(msg) = self.proc_tracker.add_process_record(p) {
panic!("Failed to track process with pid {} !\nGot: {}", pid, msg);
}
}
}
Expand Down Expand Up @@ -435,47 +431,27 @@ impl Topology {

/// Reads content from /proc/stat and extracts the stats of the whole CPU topology.
pub fn read_stats(&self) -> Option<CPUStat> {
let kernelstats_or_not = KernelStats::new();
if let Ok(res_cputime) = kernelstats_or_not {
return Some(CPUStat {
cputime: res_cputime.total,
});
}
None
KernelStats::new()
.ok()
.map(|res| CPUStat { cputime: res.total })
}

/// Returns the number of processes currently available
pub fn read_nb_process_total_count(&self) -> Option<u64> {
if let Ok(result) = KernelStats::new() {
return Some(result.processes);
}
None
KernelStats::new().ok().map(|res| res.processes)
}

/// Returns the number of processes currently in a running state
pub fn read_nb_process_running_current(&self) -> Option<u32> {
if let Ok(result) = KernelStats::new() {
if let Some(procs_running) = result.procs_running {
return Some(procs_running);
}
}
None
KernelStats::new().ok().and_then(|res| res.procs_running)
}
/// Returns the number of processes currently blocked waiting
pub fn read_nb_process_blocked_current(&self) -> Option<u32> {
if let Ok(result) = KernelStats::new() {
if let Some(procs_blocked) = result.procs_blocked {
return Some(procs_blocked);
}
}
None
KernelStats::new().ok().and_then(|res| res.procs_blocked)
}
/// Returns the current number of context switches
pub fn read_nb_context_switches_total_count(&self) -> Option<u64> {
if let Ok(result) = KernelStats::new() {
return Some(result.ctxt);
}
None
KernelStats::new().ok().map(|res| res.ctxt)
}

/// Returns the power consumed between last and previous measurement for a given process ID, in microwatts
Expand Down Expand Up @@ -749,35 +725,29 @@ impl CPUSocket {
/// Combines stats from all CPU cores owned byu the socket and returns
/// a CpuTime struct containing stats for the whole socket.
pub fn read_stats(&self) -> Option<CPUStat> {
let mut stats = CPUStat {
cputime: CpuTime {
user: 0.0,
nice: 0.0,
system: 0.0,
idle: 0.0,
iowait: Some(0.0),
irq: Some(0.0),
softirq: Some(0.0),
guest: Some(0.0),
guest_nice: Some(0.0),
steal: Some(0.0),
},
};
for c in &self.cpu_cores {
let c_stats = c.read_stats().unwrap();
stats.cputime.user += c_stats.user;
stats.cputime.nice += c_stats.nice;
stats.cputime.system += c_stats.system;
stats.cputime.idle += c_stats.idle;
stats.cputime.iowait =
Some(stats.cputime.iowait.unwrap_or_default() + c_stats.iowait.unwrap_or_default());
stats.cputime.irq =
Some(stats.cputime.irq.unwrap_or_default() + c_stats.irq.unwrap_or_default());
stats.cputime.softirq = Some(
stats.cputime.softirq.unwrap_or_default() + c_stats.softirq.unwrap_or_default(),
);
}
Some(stats)
Some(
self.cpu_cores
.iter()
.fold(CPUStat::default(), |mut stats, c| {
let c_stats = c.read_stats().unwrap();
stats.cputime.user += c_stats.user;
stats.cputime.nice += c_stats.nice;
stats.cputime.system += c_stats.system;
stats.cputime.idle += c_stats.idle;
stats.cputime.iowait = Some(
stats.cputime.iowait.unwrap_or_default()
+ c_stats.iowait.unwrap_or_default(),
);
stats.cputime.irq = Some(
stats.cputime.irq.unwrap_or_default() + c_stats.irq.unwrap_or_default(),
);
stats.cputime.softirq = Some(
stats.cputime.softirq.unwrap_or_default()
+ c_stats.softirq.unwrap_or_default(),
);
stats
}),
)
}

/// Computes the difference between previous usage statistics record for the socket
Expand Down Expand Up @@ -1055,6 +1025,25 @@ pub struct CPUStat {
pub cputime: CpuTime,
}

impl Default for CPUStat {
fn default() -> Self {
Self {
cputime: CpuTime {
user: 0.0,
nice: 0.0,
system: 0.0,
idle: 0.0,
iowait: Some(0.0),
irq: Some(0.0),
softirq: Some(0.0),
guest: Some(0.0),
guest_nice: Some(0.0),
steal: Some(0.0),
},
}
}
}

impl CPUStat {
/// Returns the total of active CPU time spent, for this stat measurement
/// (not iowait, idle, irq or softirq)
Expand Down
43 changes: 18 additions & 25 deletions src/sensors/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,20 @@ impl ProcessTracker {
/// Returns all vectors of process records linked to a running, sleeping, waiting or zombie process.
/// (Not terminated)
pub fn get_alive_processes(&self) -> Vec<&Vec<ProcessRecord>> {
let mut res = vec![];
for p in self.procs.iter() {
if !p.is_empty() {
let status = p[0].process.status();
if let Ok(status_val) = status {
if !&status_val.state.contains('T') {
// !&status_val.state.contains("Z") &&
res.push(p);
}
}
}
}
res
self.procs
.iter()
.filter_map(|p| {
p.first()
.and_then(|p| p.process.status().ok())
.and_then(|status| {
if !status.state.contains('T') {
Some(p)
} else {
None
}
})
})
.collect::<Vec<_>>()
}

/// Extracts the container_id from a cgroup path containing it.
Expand Down Expand Up @@ -343,18 +344,10 @@ impl ProcessTracker {
.iter()
.filter(|x| !x.is_empty() && x.get(0).unwrap().process.pid == pid);
let process = result.next().unwrap();
if let Some(vec) = process.get(0) {
if let Ok(mut cmdline_vec) = vec.process.cmdline() {
let mut cmdline = String::from("");
while !cmdline_vec.is_empty() {
if !cmdline_vec.is_empty() {
cmdline.push_str(&cmdline_vec.remove(0));
}
}
return Some(cmdline);
}
}
None
process
.get(0)
.and_then(|vec| vec.process.cmdline().ok())
.map(|vec| vec.join(""))
}

/// Returns the CPU time consumed between two measure iteration
Expand Down