Skip to main content

systemstat/
data.rs

1//! This module provides the data structures that represent system information.
2//!
3//! They're always the same across all platforms.
4
5pub use bytesize::ByteSize;
6pub use std::collections::BTreeMap;
7use std::io;
8pub use std::net::{Ipv4Addr, Ipv6Addr};
9use std::ops::Sub;
10pub use std::time::Duration;
11pub use time::OffsetDateTime;
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16#[inline(always)]
17pub fn saturating_sub_bytes(l: ByteSize, r: ByteSize) -> ByteSize {
18    ByteSize::b(l.as_u64().saturating_sub(r.as_u64()))
19}
20
21/// A wrapper for a measurement that takes time.
22///
23/// Time should pass between getting the object and calling .done() on it.
24pub struct DelayedMeasurement<T> {
25    res: Box<dyn Fn() -> io::Result<T> + Send>,
26}
27
28impl<T> DelayedMeasurement<T> {
29    #[inline(always)]
30    pub fn new(f: Box<dyn Fn() -> io::Result<T> + Send>) -> DelayedMeasurement<T> {
31        DelayedMeasurement { res: f }
32    }
33
34    #[inline(always)]
35    pub fn done(&self) -> io::Result<T> {
36        (self.res)()
37    }
38}
39
40#[cfg(not(target_os = "linux"))]
41#[cfg_attr(
42    feature = "serde",
43    derive(Serialize, Deserialize),
44    serde(crate = "the_serde")
45)]
46#[derive(Debug, Clone)]
47pub struct PlatformCpuLoad {}
48
49#[cfg(target_os = "linux")]
50#[cfg_attr(
51    feature = "serde",
52    derive(Serialize, Deserialize),
53    serde(crate = "the_serde")
54)]
55#[derive(Debug, Clone)]
56pub struct PlatformCpuLoad {
57    pub iowait: f32,
58}
59
60impl PlatformCpuLoad {
61    #[cfg(target_os = "linux")]
62    #[inline(always)]
63    pub fn avg_add(self, rhs: &Self) -> Self {
64        PlatformCpuLoad {
65            iowait: (self.iowait + rhs.iowait) / 2.0,
66        }
67    }
68
69    #[cfg(not(target_os = "linux"))]
70    #[inline(always)]
71    pub fn avg_add(self, _rhs: &Self) -> Self {
72        PlatformCpuLoad {}
73    }
74
75    #[cfg(target_os = "linux")]
76    #[inline(always)]
77    pub fn zero() -> Self {
78        PlatformCpuLoad { iowait: 0.0 }
79    }
80
81    #[cfg(not(target_os = "linux"))]
82    #[inline(always)]
83    pub fn zero() -> Self {
84        PlatformCpuLoad {}
85    }
86
87    #[cfg(target_os = "linux")]
88    #[inline(always)]
89    pub fn from(input: f32) -> Self {
90        PlatformCpuLoad { iowait: input }
91    }
92
93    #[cfg(not(target_os = "linux"))]
94    #[inline(always)]
95    pub fn from(_input: f32) -> Self {
96        PlatformCpuLoad {}
97    }
98
99    #[cfg(target_os = "linux")]
100    #[inline(always)]
101    pub fn sum(&self) -> f32 {
102        self.iowait
103    }
104
105    #[cfg(not(target_os = "linux"))]
106    #[inline(always)]
107    pub fn sum(&self) -> f32 {
108        0.0
109    }
110}
111
112#[cfg_attr(
113    feature = "serde",
114    derive(Serialize, Deserialize),
115    serde(crate = "the_serde")
116)]
117#[derive(Debug, Clone)]
118pub struct CPULoad {
119    pub user: f32,
120    pub nice: f32,
121    pub system: f32,
122    pub interrupt: f32,
123    pub idle: f32,
124    pub platform: PlatformCpuLoad,
125}
126
127impl CPULoad {
128    #[inline(always)]
129    pub fn avg_add(self, rhs: &Self) -> Self {
130        CPULoad {
131            user: (self.user + rhs.user) / 2.0,
132            nice: (self.nice + rhs.nice) / 2.0,
133            system: (self.system + rhs.system) / 2.0,
134            interrupt: (self.interrupt + rhs.interrupt) / 2.0,
135            idle: (self.idle + rhs.idle) / 2.0,
136            platform: self.platform.avg_add(&rhs.platform),
137        }
138    }
139}
140
141#[cfg_attr(
142    feature = "serde",
143    derive(Serialize, Deserialize),
144    serde(crate = "the_serde")
145)]
146#[derive(Debug, Clone, Copy)]
147pub struct CpuTime {
148    pub user: usize,
149    pub nice: usize,
150    pub system: usize,
151    pub interrupt: usize,
152    pub idle: usize,
153    pub other: usize,
154}
155
156impl<'a> Sub<&'a CpuTime> for CpuTime {
157    type Output = CpuTime;
158
159    #[inline(always)]
160    fn sub(self, rhs: &CpuTime) -> CpuTime {
161        CpuTime {
162            user: self.user.saturating_sub(rhs.user),
163            nice: self.nice.saturating_sub(rhs.nice),
164            system: self.system.saturating_sub(rhs.system),
165            interrupt: self.interrupt.saturating_sub(rhs.interrupt),
166            idle: self.idle.saturating_sub(rhs.idle),
167            other: self.other.saturating_sub(rhs.other),
168        }
169    }
170}
171
172impl CpuTime {
173    pub fn to_cpuload(&self) -> CPULoad {
174        let total = self.user + self.nice + self.system + self.interrupt + self.idle + self.other;
175        if total == 0 {
176            CPULoad {
177                user: 0.0,
178                nice: 0.0,
179                system: 0.0,
180                interrupt: 0.0,
181                idle: 0.0,
182                platform: PlatformCpuLoad::zero(),
183            }
184        } else {
185            CPULoad {
186                user: self.user as f32 / total as f32,
187                nice: self.nice as f32 / total as f32,
188                system: self.system as f32 / total as f32,
189                interrupt: self.interrupt as f32 / total as f32,
190                idle: self.idle as f32 / total as f32,
191                platform: PlatformCpuLoad::from(self.other as f32 / total as f32),
192            }
193        }
194    }
195}
196
197#[cfg_attr(
198    feature = "serde",
199    derive(Serialize, Deserialize),
200    serde(crate = "the_serde")
201)]
202#[derive(Debug, Clone)]
203pub struct LoadAverage {
204    pub one: f32,
205    pub five: f32,
206    pub fifteen: f32,
207}
208
209#[cfg(target_os = "windows")]
210#[cfg_attr(
211    feature = "serde",
212    derive(Serialize, Deserialize),
213    serde(crate = "the_serde")
214)]
215#[derive(Debug, Clone)]
216pub struct PlatformMemory {
217    pub load: u32,
218    pub total_phys: ByteSize,
219    pub avail_phys: ByteSize,
220    pub total_pagefile: ByteSize,
221    pub avail_pagefile: ByteSize,
222    pub total_virt: ByteSize,
223    pub avail_virt: ByteSize,
224    pub avail_ext: ByteSize,
225}
226
227#[cfg(target_os = "freebsd")]
228#[cfg_attr(
229    feature = "serde",
230    derive(Serialize, Deserialize),
231    serde(crate = "the_serde")
232)]
233#[derive(Debug, Clone)]
234pub struct PlatformMemory {
235    pub active: ByteSize,
236    pub inactive: ByteSize,
237    pub wired: ByteSize,
238    pub cache: ByteSize,
239    pub zfs_arc: ByteSize,
240    pub free: ByteSize,
241}
242
243#[cfg(any(target_os = "openbsd", target_os = "illumos", target_os = "solaris"))]
244#[cfg_attr(
245    feature = "serde",
246    derive(Serialize, Deserialize),
247    serde(crate = "the_serde")
248)]
249#[derive(Debug, Clone)]
250pub struct PlatformMemory {
251    pub total: ByteSize,
252    pub active: ByteSize,
253    pub inactive: ByteSize,
254    pub wired: ByteSize,
255    pub cache: ByteSize,
256    pub free: ByteSize,
257    pub paging: ByteSize,
258    pub sw: ByteSize,
259    pub swinuse: ByteSize,
260    pub swonly: ByteSize,
261}
262
263#[cfg(target_os = "netbsd")]
264#[cfg_attr(
265    feature = "serde",
266    derive(Serialize, Deserialize),
267    serde(crate = "the_serde")
268)]
269#[derive(Debug, Clone)]
270pub struct PlatformMemory {
271    pub pageshift: i64,
272    pub total: ByteSize,
273    pub active: ByteSize,
274    pub inactive: ByteSize,
275    pub wired: ByteSize,
276    pub free: ByteSize,
277    pub paging: ByteSize,
278    pub anon: ByteSize,
279    pub files: ByteSize,
280    pub exec: ByteSize,
281    pub sw: ByteSize,
282    pub swinuse: ByteSize,
283    pub swonly: ByteSize,
284}
285
286#[cfg(target_vendor = "apple")]
287#[cfg_attr(
288    feature = "serde",
289    derive(Serialize, Deserialize),
290    serde(crate = "the_serde")
291)]
292#[derive(Debug, Clone)]
293pub struct PlatformMemory {
294    pub total: ByteSize,
295    pub active: ByteSize,
296    pub inactive: ByteSize,
297    pub wired: ByteSize,
298    pub free: ByteSize,
299    pub purgeable: ByteSize,
300    pub speculative: ByteSize,
301    pub compressor: ByteSize,
302    pub throttled: ByteSize,
303    pub external: ByteSize,
304    pub internal: ByteSize,
305    pub uncompressed_in_compressor: ByteSize,
306}
307
308#[cfg(any(target_os = "linux", target_os = "android", target_os = "hurd"))]
309#[cfg_attr(
310    feature = "serde",
311    derive(Serialize, Deserialize),
312    serde(crate = "the_serde")
313)]
314#[derive(Debug, Clone)]
315pub struct PlatformMemory {
316    pub meminfo: BTreeMap<String, ByteSize>,
317}
318
319#[cfg_attr(
320    feature = "serde",
321    derive(Serialize, Deserialize),
322    serde(crate = "the_serde")
323)]
324#[derive(Debug, Clone)]
325pub struct Memory {
326    pub total: ByteSize,
327    pub free: ByteSize,
328    pub platform_memory: PlatformMemory,
329}
330
331#[cfg(any(
332    target_os = "windows",
333    target_os = "linux",
334    target_os = "android",
335    target_os = "openbsd",
336    target_os = "netbsd",
337    target_os = "illumos",
338    target_os = "solaris",
339    target_os = "hurd",
340))]
341pub type PlatformSwap = PlatformMemory;
342
343#[cfg(any(target_vendor = "apple", target_os = "freebsd"))]
344#[cfg_attr(
345    feature = "serde",
346    derive(Serialize, Deserialize),
347    serde(crate = "the_serde")
348)]
349#[derive(Debug, Clone)]
350pub struct PlatformSwap {
351    pub total: ByteSize,
352    pub avail: ByteSize,
353    pub used: ByteSize,
354    pub pagesize: ByteSize,
355    pub encrypted: bool,
356}
357
358#[cfg_attr(
359    feature = "serde",
360    derive(Serialize, Deserialize),
361    serde(crate = "the_serde")
362)]
363#[derive(Debug, Clone)]
364pub struct Swap {
365    pub total: ByteSize,
366    pub free: ByteSize,
367    pub platform_swap: PlatformSwap,
368}
369
370#[cfg_attr(
371    feature = "serde",
372    derive(Serialize, Deserialize),
373    serde(crate = "the_serde")
374)]
375#[derive(Debug, Clone)]
376pub struct BatteryLife {
377    pub remaining_capacity: f32,
378    pub remaining_time: Duration,
379}
380
381#[cfg_attr(
382    feature = "serde",
383    derive(Serialize, Deserialize),
384    serde(crate = "the_serde")
385)]
386#[derive(Debug, Clone)]
387pub struct Filesystem {
388    /// Used file nodes in filesystem
389    pub files: usize,
390    /// Total file nodes in filesystem
391    pub files_total: usize,
392    /// Free nodes available to non-superuser
393    pub files_avail: usize,
394    /// Free bytes in filesystem
395    pub free: ByteSize,
396    /// Free bytes available to non-superuser
397    pub avail: ByteSize,
398    /// Total bytes in filesystem
399    pub total: ByteSize,
400    /// Maximum filename length
401    pub name_max: usize,
402    pub fs_type: String,
403    pub fs_mounted_from: String,
404    pub fs_mounted_on: String,
405}
406
407#[cfg_attr(
408    feature = "serde",
409    derive(Serialize, Deserialize),
410    serde(crate = "the_serde")
411)]
412#[derive(Debug, Clone)]
413pub struct BlockDeviceStats {
414    pub name: String,
415    pub read_ios: usize,
416    pub read_merges: usize,
417    pub read_sectors: usize,
418    pub read_ticks: usize,
419    pub write_ios: usize,
420    pub write_merges: usize,
421    pub write_sectors: usize,
422    pub write_ticks: usize,
423    pub in_flight: usize,
424    pub io_ticks: usize,
425    pub time_in_queue: usize,
426}
427
428#[cfg_attr(
429    feature = "serde",
430    derive(Serialize, Deserialize),
431    serde(crate = "the_serde")
432)]
433#[derive(Debug, Clone, PartialEq)]
434pub enum IpAddr {
435    Empty,
436    Unsupported,
437    V4(Ipv4Addr),
438    V6(Ipv6Addr),
439}
440
441#[cfg_attr(
442    feature = "serde",
443    derive(Serialize, Deserialize),
444    serde(crate = "the_serde")
445)]
446#[derive(Debug, Clone)]
447pub struct NetworkAddrs {
448    pub addr: IpAddr,
449    pub netmask: IpAddr,
450}
451
452#[cfg_attr(
453    feature = "serde",
454    derive(Serialize, Deserialize),
455    serde(crate = "the_serde")
456)]
457#[derive(Debug, Clone)]
458pub struct Network {
459    pub name: String,
460    pub addrs: Vec<NetworkAddrs>,
461}
462
463#[cfg_attr(
464    feature = "serde",
465    derive(Serialize, Deserialize),
466    serde(crate = "the_serde")
467)]
468#[derive(Debug, Clone)]
469pub struct NetworkStats {
470    pub rx_bytes: ByteSize,
471    pub tx_bytes: ByteSize,
472    pub rx_packets: u64,
473    pub tx_packets: u64,
474    pub rx_errors: u64,
475    pub tx_errors: u64,
476}
477
478#[cfg_attr(
479    feature = "serde",
480    derive(Serialize, Deserialize),
481    serde(crate = "the_serde")
482)]
483#[derive(Debug, Clone)]
484pub struct SocketStats {
485    pub tcp_sockets_in_use: usize,
486    pub tcp_sockets_orphaned: usize,
487    pub udp_sockets_in_use: usize,
488    pub tcp6_sockets_in_use: usize,
489    pub udp6_sockets_in_use: usize,
490}