MetricThresholdCollector   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 58
c 2
b 0
f 0
dl 0
loc 98
rs 10
wmc 13

2 Methods

Rating   Name   Duplication   Size   Complexity  
B countStandardDeviationOutliers() 0 35 7
A collect() 0 23 6
1
<?php
2
3
namespace Startwind\Inventorio\Collector\Metrics;
4
5
use Startwind\Inventorio\Collector\BasicCollector;
6
use Startwind\Inventorio\Metrics\Collector\Metric\Webserver\ApacheAccessLogMetric;
7
use Startwind\Inventorio\Metrics\Collector\Metric\Webserver\ApacheErrorLogMetric;
8
use Startwind\Inventorio\Metrics\Collector\Metric\Webserver\NginxAccessLogMetric;
9
use Startwind\Inventorio\Metrics\Collector\Metric\Webserver\NginxErrorLogMetric;
10
use Startwind\Inventorio\Metrics\Memory\Memory;
11
12
class MetricThresholdCollector extends BasicCollector
13
{
14
    const THRESHOLD_ABSOLUTE = 'absolute';
15
    const THRESHOLD_STANDARD_DEVIATION = 'standardDeviation';
16
17
    protected string $identifier = 'MetricsThreshold';
18
19
    private array $thresholds = [
20
        'cpu-usage' => [
21
            'type' => self::THRESHOLD_ABSOLUTE,
22
            'threshold' => 80
23
        ],
24
        'memory-usage' => [
25
            'type' => self::THRESHOLD_ABSOLUTE,
26
            'threshold' => 80
27
        ],
28
        ApacheErrorLogMetric::IDENTIFIER => [
29
            'type' => self::THRESHOLD_STANDARD_DEVIATION,
30
            'factor' => 3,
31
            'outlinerMinLimit' => 10
32
        ],
33
        ApacheAccessLogMetric::IDENTIFIER => [
34
            'type' => self::THRESHOLD_STANDARD_DEVIATION,
35
            'factor' => 3,
36
            'outlinerMinLimit' => 10
37
        ],
38
        NginxErrorLogMetric::IDENTIFIER => [
39
            'type' => self::THRESHOLD_STANDARD_DEVIATION,
40
            'factor' => 3,
41
            'outlinerMinLimit' => 10
42
        ],
43
        NginxAccessLogMetric::IDENTIFIER => [
44
            'type' => self::THRESHOLD_STANDARD_DEVIATION,
45
            'factor' => 3,
46
            'outlinerMinLimit' => 10
47
        ],
48
    ];
49
50
    public function collect(): array
51
    {
52
        $memory = Memory::getInstance();
53
54
        $result = [];
55
56
        foreach ($this->thresholds as $metric => $threshold) {
57
            switch ($threshold['type']) {
58
                case self::THRESHOLD_ABSOLUTE:
59
                    if ($memory->hasData($metric)) {
60
                        $result[$metric] = $memory->getNumberOfGreaterThan($metric, $threshold['threshold']);
61
                    }
62
                    break;
63
                case self::THRESHOLD_STANDARD_DEVIATION:
64
                    if ($memory->hasData($metric)) {
65
                        $data = $memory->getData($metric);
66
                        $result[$metric] = $this->countStandardDeviationOutliers($data, $threshold['factor'], $threshold['outlinerMinLimit']);
67
                    }
68
                    break;
69
            }
70
        }
71
72
        return $result;
73
    }
74
75
    private function countStandardDeviationOutliers(array $values, float $factor = 3.0, $outlinerMinLimit = 10): int
76
    {
77
        $n = count($values);
78
79
        // we wait until we have enough data
80
        if ($n < 5) {
81
            return 0;
82
        }
83
84
        $sum = array_sum($values);
85
        $mean = $sum / $n;
86
87
        // Calculate standard deviation
88
        $sumOfSquares = 0.0;
89
        foreach ($values as $value) {
90
            $sumOfSquares += pow($value - $mean, 2);
91
        }
92
93
        $stdDev = sqrt($sumOfSquares / $n);
94
95
        if ($stdDev == 0.0) {
96
            return 0;
97
        }
98
99
        // Count outliers
100
        $threshold = $factor * $stdDev;
101
        $outliers = 0;
102
103
        foreach ($values as $value) {
104
            if (abs($value - $mean) > $threshold && $value > $outlinerMinLimit) {
105
                $outliers++;
106
            }
107
        }
108
109
        return $outliers;
110
    }
111
}
112