1#![crate_type = "lib"]
2#![crate_name = "procstat"]
3
4use std::collections::HashMap;
5use std::{fs::File, io::{BufRead, BufReader}, path::Path};
6
7mod boot_time;
8mod cpu;
9mod contexts;
10mod interrupts;
11mod processes;
12mod soft_irq;
13
14pub use boot_time::*;
15pub use cpu::*;
16pub use contexts::*;
17pub use interrupts::*;
18pub use processes::*;
19pub use soft_irq::*;
20
21#[derive(Debug)]
22pub struct ProcStat {
23 pub cpu: CPU,
24 pub cpus: HashMap<usize,CPU>,
25 pub interrupts: Interrupts,
26 pub contexts: Contexts,
27 pub boot_time: BootTime,
28 pub processes: Processes,
29 pub soft_irq: SoftIrq,
30}
31
32const KEY_CPU: &str = "cpu";
33const KEY_INTERRUPTS: &str = "intr";
34const KEY_CONTEXTS: &str = "ctxt";
35const KEY_BOOT_TIME: &str = "btime";
36const KEY_SOFT_IRQ: &str = "softirq";
37const KEY_PROCESSES: &str = "processes";
38const KEY_PROCESSES_RUNNING: &str = "procs_running";
39const KEY_PROCESSES_BLOCKED: &str = "procs_blocked";
40
41impl ProcStat {
42 fn empty() -> Self {
43 Self {
44 cpu: CPU::empty(),
45 cpus: HashMap::new(),
46 interrupts: Interrupts::empty(),
47 contexts: Contexts::empty(),
48 boot_time: BootTime::empty(),
49 processes: Processes::empty(),
50 soft_irq: SoftIrq::empty(),
51 }
52 }
53
54 pub fn read() -> ProcStat {
55
56 let file = File::open(Path::new("/proc/stat")).unwrap();
57
58 ProcStat::read_file(file)
59 }
60
61 pub fn read_file(file: File) -> ProcStat {
62 let mut proc_stat = Self::empty();
63
64 let reader = BufReader::new(file);
65 for line in reader.lines() {
66 let line = line.unwrap();
67 let mut tokenised = line.split_whitespace();
68 let key = tokenised.next().unwrap_or("");
69 let values: Vec<u64> = tokenised.by_ref().map(|t| u64::from_str_radix(t, 10).unwrap_or_default()).collect();
70
71 if key.eq(KEY_CPU) {
72 proc_stat.cpu = CPU::from_vec(values);
73 } else if key.starts_with(KEY_CPU) {
74 let cpu = CPU::from_vec(values);
75 let cpu_index = usize::from_str_radix(key.split_at(3).1, 10).unwrap();
76 proc_stat.cpus.insert(cpu_index, cpu);
77 } else if key.eq(KEY_INTERRUPTS) {
78 proc_stat.interrupts = Interrupts::from_vec(values);
79 } else if key.eq(KEY_CONTEXTS) {
80 proc_stat.contexts = Contexts::from_vec(values);
81 } else if key.eq(KEY_BOOT_TIME) {
82 proc_stat.boot_time = BootTime::from_vec(values);
83 } else if key.eq(KEY_SOFT_IRQ) {
84 proc_stat.soft_irq = SoftIrq::from_vec(values);
85 } else if key.eq(KEY_PROCESSES) {
86 proc_stat.processes.forks_since_boot = *values.first().unwrap();
87 } else if key.eq(KEY_PROCESSES_RUNNING) {
88 proc_stat.processes.running_processes = *values.first().unwrap();
89 } else if key.eq(KEY_PROCESSES_BLOCKED) {
90 proc_stat.processes.blocked_processes = *values.first().unwrap();
91 }
92 }
93
94 proc_stat
95 }
96}