Implement cpu usage monitor
This commit is contained in:
89
src/stack.rs
Normal file
89
src/stack.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use crate::docker;
|
||||
use crate::process::{self, ProcInfo};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::task;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, PartialEq)]
|
||||
pub struct StackInfo {
|
||||
pub containers: u32,
|
||||
pub running_containers: u32,
|
||||
pub stopped_containers: u32,
|
||||
pub process_count: u32,
|
||||
pub cpu_percent: f64,
|
||||
pub memory_usage: usize,
|
||||
pub memory_percent: f64,
|
||||
}
|
||||
|
||||
pub fn spawn_monitor(stack: docker::Stack) -> mpsc::Receiver<StackInfo> {
|
||||
let (tx, rx) = mpsc::channel(64);
|
||||
|
||||
task::spawn(monitor_proc(tx, stack));
|
||||
|
||||
rx
|
||||
}
|
||||
|
||||
async fn monitor_proc(tx: mpsc::Sender<StackInfo>, stack: docker::Stack) -> anyhow::Result<()> {
|
||||
let mut proc_monitors: HashMap<u32, mpsc::Receiver<ProcInfo>> = HashMap::new();
|
||||
let mut processes = HashMap::<u32, ProcInfo>::new();
|
||||
let mut last_stack_info = StackInfo::default();
|
||||
|
||||
loop {
|
||||
let mut stack_info = StackInfo::default();
|
||||
|
||||
let containers = docker::list_containers(&stack).await?;
|
||||
stack_info.containers = containers.len() as u32;
|
||||
stack_info.running_containers = containers.iter().filter(|c| c.is_running()).count() as u32;
|
||||
stack_info.stopped_containers = stack_info.containers - stack_info.running_containers;
|
||||
|
||||
processes.clear();
|
||||
for container in &containers {
|
||||
for process in docker::list_processes(&stack, container).await? {
|
||||
processes.insert(process.pid, Default::default());
|
||||
if !proc_monitors.contains_key(&process.pid) {
|
||||
proc_monitors.insert(process.pid, process::spawn_monitor(process.pid));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc_monitors.retain(|&pid, monitor| {
|
||||
if !processes.contains_key(&pid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
match monitor.try_recv() {
|
||||
Ok(info) => {
|
||||
processes.insert(pid, info);
|
||||
true
|
||||
}
|
||||
Err(mpsc::error::TryRecvError::Empty) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
});
|
||||
|
||||
let memory_usage = processes.values().map(|p| p.memory_usage).sum();
|
||||
let host_memory = (1usize << 20) * 16; // 10 GiB // TODO
|
||||
|
||||
stack_info = StackInfo {
|
||||
process_count: processes.len() as u32,
|
||||
memory_usage,
|
||||
memory_percent: memory_usage as f64 / host_memory as f64,
|
||||
cpu_percent: processes
|
||||
.values()
|
||||
.map(|p| p.cpu_percent)
|
||||
.sum::<f64>()
|
||||
.max(0.0),
|
||||
..stack_info
|
||||
};
|
||||
|
||||
if stack_info != last_stack_info {
|
||||
last_stack_info = stack_info;
|
||||
|
||||
tx.send(stack_info).await?;
|
||||
}
|
||||
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user