1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use crate::measurement::{marker::ResourcesUsage, status::Status, thresholds::Thresholds};
use std::{cmp::Ordering, fmt};

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct NamedProcess {
    name: String,
    id: usize,
}

impl NamedProcess {
    pub fn new(name: String, id: usize) -> Self {
        Self { name, id }
    }

    pub fn name(&self) -> String {
        self.name.to_string()
    }

    pub fn id(&self) -> usize {
        self.id
    }
}

impl fmt::Display for NamedProcess {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "id: {}, alias: {}", self.id, self.name)
    }
}

#[derive(Clone, Debug)]
pub struct Consumption {
    average_usage: ResourcesUsage,
}

impl fmt::Display for Consumption {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.average_usage)
    }
}

impl PartialEq for Consumption {
    fn eq(&self, other: &Self) -> bool {
        self.average_usage == other.average_usage
    }
}

impl PartialOrd for Consumption {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.average_usage.partial_cmp(&other.average_usage)
    }
}

impl Consumption {
    pub fn new(markers: Vec<ResourcesUsage>) -> Self {
        Self {
            average_usage: Self::average_resource_usage(markers),
        }
    }

    fn average_resource_usage(markers: Vec<ResourcesUsage>) -> ResourcesUsage {
        let average_cpu = Self::median(markers.iter().map(|x| x.cpu_usage()).collect());
        let average_memory = Self::median(markers.iter().map(|x| x.memory_usage()).collect());
        let average_virtual_memory =
            Self::median(markers.iter().map(|x| x.virtual_memory_usage()).collect());
        ResourcesUsage::new(average_cpu, average_memory, average_virtual_memory)
    }

    fn median(mut markers: Vec<u32>) -> u32 {
        markers.sort_unstable();
        let mid = markers.len() / 2;
        *markers.get(mid).unwrap()
    }

    pub fn against(&self, thresholds: &Thresholds<Self>) -> Status {
        let green = thresholds.green_threshold();
        let yellow = thresholds.yellow_threshold();

        if *self <= green {
            return Status::Green;
        }
        if *self <= yellow {
            return Status::Yellow;
        }
        Status::Red
    }
}