mprober_lib/cpu/
cpu_stat.rs1use std::{io::ErrorKind, thread::sleep, time::Duration};
2
3use crate::{
4 cpu::CPUTime,
5 scanner_rust::{
6 generic_array::typenum::{U1024, U72},
7 ScannerAscii, ScannerError,
8 },
9};
10
11#[derive(Default, Debug, Clone)]
12pub struct CPUStat {
13 pub user: u64,
14 pub nice: u64,
15 pub system: u64,
16 pub idle: u64,
17 pub iowait: u64,
18 pub irq: u64,
19 pub softirq: u64,
20 pub steal: u64,
21 pub guest: u64,
22 pub guest_nice: u64,
23}
24
25impl CPUStat {
26 #[inline]
37 pub fn compute_cpu_time(&self) -> CPUTime {
38 let idle = self.idle + self.iowait;
39
40 let non_idle = self.user + self.nice + self.system + self.irq + self.softirq + self.steal;
41
42 CPUTime {
43 non_idle,
44 idle,
45 }
46 }
47
48 #[inline]
67 pub fn compute_cpu_utilization_in_percentage(&self, cpu_stat_after_this: &CPUStat) -> f64 {
68 let pre_cpu_time = self.compute_cpu_time();
69 let cpu_time = cpu_stat_after_this.compute_cpu_time();
70
71 let d_total = cpu_time.get_total_time() - pre_cpu_time.get_total_time();
72 let d_non_idle = cpu_time.non_idle - pre_cpu_time.non_idle;
73
74 d_non_idle as f64 / d_total as f64
75 }
76}
77
78pub fn get_average_cpu_stat() -> Result<CPUStat, ScannerError> {
88 let mut sc: ScannerAscii<_, U72> = ScannerAscii::scan_path2("/proc/stat")?;
89
90 let label = sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?;
91
92 if label == b"cpu" {
93 let user = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
94 let nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
95 let system = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
96 let idle = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
97 let iowait = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
98 let irq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
99 let softirq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
100 let steal = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
101 let guest = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
102 let guest_nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
103
104 Ok(CPUStat {
105 user,
106 nice,
107 system,
108 idle,
109 iowait,
110 irq,
111 softirq,
112 steal,
113 guest,
114 guest_nice,
115 })
116 } else {
117 Err(ErrorKind::InvalidData.into())
118 }
119}
120
121pub fn get_all_cpus_stat(with_average: bool) -> Result<Vec<CPUStat>, ScannerError> {
131 let mut sc: ScannerAscii<_, U1024> = ScannerAscii::scan_path2("/proc/stat")?;
132
133 let mut cpus_stat = Vec::with_capacity(1);
134
135 if with_average {
136 let label = sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?;
137
138 if label == b"cpu" {
139 let user = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
140 let nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
141 let system = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
142 let idle = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
143 let iowait = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
144 let irq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
145 let softirq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
146 let steal = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
147 let guest = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
148 let guest_nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
149
150 let cpu_stat = CPUStat {
151 user,
152 nice,
153 system,
154 idle,
155 iowait,
156 irq,
157 softirq,
158 steal,
159 guest,
160 guest_nice,
161 };
162
163 cpus_stat.push(cpu_stat);
164 } else {
165 return Err(ErrorKind::InvalidData.into());
166 }
167 } else {
168 sc.drop_next_line()?.ok_or(ErrorKind::UnexpectedEof)?;
169 }
170
171 loop {
172 let label = sc.next_raw()?.ok_or(ErrorKind::UnexpectedEof)?;
173
174 if label.starts_with(b"cpu") {
175 let user = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
176 let nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
177 let system = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
178 let idle = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
179 let iowait = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
180 let irq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
181 let softirq = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
182 let steal = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
183 let guest = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
184 let guest_nice = sc.next_u64()?.ok_or(ErrorKind::UnexpectedEof)?;
185
186 let cpu_stat = CPUStat {
187 user,
188 nice,
189 system,
190 idle,
191 iowait,
192 irq,
193 softirq,
194 steal,
195 guest,
196 guest_nice,
197 };
198
199 cpus_stat.push(cpu_stat);
200 } else {
201 break;
202 }
203 }
204
205 Ok(cpus_stat)
206}
207
208#[inline]
223pub fn get_average_cpu_utilization_in_percentage(interval: Duration) -> Result<f64, ScannerError> {
224 let pre_cpu_stat = get_average_cpu_stat()?;
225
226 sleep(interval);
227
228 let cpu_stat = get_average_cpu_stat()?;
229
230 Ok(pre_cpu_stat.compute_cpu_utilization_in_percentage(&cpu_stat))
231}
232
233#[inline]
253pub fn get_all_cpu_utilization_in_percentage(
254 with_average: bool,
255 interval: Duration,
256) -> Result<Vec<f64>, ScannerError> {
257 let pre_cpus_stat = get_all_cpus_stat(with_average)?;
258
259 sleep(interval);
260
261 let cpus_stat = get_all_cpus_stat(with_average)?;
262
263 let result = pre_cpus_stat
264 .into_iter()
265 .zip(cpus_stat)
266 .map(|(pre_cpus_stat, cpus_stat)| {
267 pre_cpus_stat.compute_cpu_utilization_in_percentage(&cpus_stat)
268 })
269 .collect();
270
271 Ok(result)
272}