perfdata/perf/
dataset.rs

1use crate::monitoring_status::MonitoringStatus;
2use crate::Perfdata;
3use std::fmt::{Display, Formatter};
4
5/// A PerfdataSet is a collection of Perfdata.
6/// It can be built via `PerfdataSet::new()`, from Iterators with `Item=<Perfdata>`, or from a
7/// `Vec<Perfdata>`.
8#[derive(Debug, Default, PartialEq)]
9pub struct PerfdataSet<'a> {
10    data: Vec<Perfdata<'a>>,
11}
12
13impl<'a> PerfdataSet<'a> {
14    /// Create a new `PerfdataSet`
15    pub fn new() -> Self {
16        PerfdataSet::default()
17    }
18
19    /// Add Perfdata to a `PerfdataSet`
20    pub fn add(&mut self, pd: Perfdata<'a>) {
21        self.data.push(pd);
22    }
23
24    /// Returns true if the `PerfdataSet` does not contain any `Perfdata`
25    pub fn is_empty(&self) -> bool {
26        self.data.is_empty()
27    }
28
29    /// Returns an iterator over all contained `Perfdata`
30    pub fn data(&self) -> impl Iterator<Item = &Perfdata<'a>> {
31        self.data.iter()
32    }
33
34    /// Returns an iterator over all `Perfdata` which exceeds their critical threshold
35    pub fn critical(&self) -> impl Iterator<Item = &Perfdata<'a>> {
36        self.data().filter(|pd| pd.is_crit())
37    }
38
39    /// Returns true if any of the contained `Perfdata`has a critical `Threshold` assigned
40    /// and the value exceeds the `Threshold`
41    pub fn has_critical(&self) -> bool {
42        self.critical().next().is_some()
43    }
44
45    /// Returns an iterator over all `Perfdata` which exceeds their warning threshold
46    pub fn warning(&self) -> impl Iterator<Item = &Perfdata<'a>> {
47        self.data().filter(|pd| pd.is_warn())
48    }
49
50    /// Returns true if any of the contained `Perfdata`has a warning `Threshold` assigned
51    /// and the value exceeds the `Threshold`
52    pub fn has_warning(&self) -> bool {
53        self.warning().next().is_some()
54    }
55
56    /// Returns the MonitoringStatus reflecting the worst status based on Thresholds
57    /// Critical is worse than Warning is worse than OK
58    pub fn status(&self) -> MonitoringStatus {
59        if self.has_critical() {
60            MonitoringStatus::Critical
61        } else if self.has_warning() {
62            MonitoringStatus::Warning
63        } else {
64            MonitoringStatus::OK
65        }
66    }
67}
68
69impl<'a> From<Vec<Perfdata<'a>>> for PerfdataSet<'a> {
70    fn from(data: Vec<Perfdata<'a>>) -> Self {
71        Self { data }
72    }
73}
74
75impl<'a> FromIterator<Perfdata<'a>> for PerfdataSet<'a> {
76    fn from_iter<T: IntoIterator<Item = Perfdata<'a>>>(iter: T) -> Self {
77        Self {
78            data: iter.into_iter().collect(),
79        }
80    }
81}
82
83impl<'a> Display for PerfdataSet<'a> {
84    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
85        for (i, pd) in self.data.iter().enumerate() {
86            write!(f, "{}", pd)?;
87            if i != self.data.len() - 1 {
88                write!(f, " ")?;
89            }
90        }
91        Ok(())
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98    use crate::ThresholdRange;
99
100    #[test]
101    fn display_pdset() {
102        //Arrange
103        let thc = ThresholdRange::above_pos(23);
104        let thw = ThresholdRange::inside(0, 100);
105        let pd = Perfdata::bytes("bytes", 42)
106            .with_warn(thw)
107            .with_crit(thc)
108            .with_min(-100)
109            .with_max(100);
110
111        let pdo = Perfdata::unit("unit", 50);
112        let pdu = Perfdata::undetermined("undetermined");
113
114        let mut pds = PerfdataSet::new();
115        pds.add(pd);
116        pds.add(pdo);
117        pds.add(pdu);
118
119        let empty_pds = PerfdataSet::new();
120
121        // Act
122        let result = pds.to_string();
123        let expected = "'bytes'=42b;@100;23;-100;100; 'unit'=50; 'undetermined'=U;";
124
125        let empty_result = empty_pds.to_string();
126
127        // Assert
128        assert_eq!(&empty_result, "");
129        assert_eq!(&result, expected);
130    }
131
132    #[test]
133    fn test_degraded() {
134        let val = 10;
135        let pds = vec![
136            Perfdata::unit("critical", val).with_crit(ThresholdRange::above_pos(0)),
137            Perfdata::unit("warn", val).with_warn(ThresholdRange::above_pos(0)),
138            Perfdata::unit("ok", val),
139        ];
140
141        let pds_crit: PerfdataSet = pds[..].iter().cloned().collect();
142        let pds_warn: PerfdataSet = pds[1..].iter().cloned().collect();
143        let pds_ok: PerfdataSet = pds[2..].iter().cloned().collect();
144
145        assert_eq!(pds_crit.data().count(), 3);
146        assert_eq!(pds_warn.data().count(), 2);
147        assert_eq!(pds_ok.data().count(), 1);
148
149        assert_eq!(pds_crit.critical().count(), 1);
150        assert_eq!(pds_warn.warning().count(), 1);
151        assert_eq!(pds_ok.critical().count(), 0);
152        assert_eq!(pds_ok.warning().count(), 0);
153    }
154}