Completed
Push — develop ( 28a887...d46380 )
by Stan
02:57
created

StorageManager   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 97.06%

Importance

Changes 0
Metric Value
dl 0
loc 149
ccs 66
cts 68
cp 0.9706
rs 10
c 0
b 0
f 0
wmc 19

7 Methods

Rating   Name   Duplication   Size   Complexity  
A increment() 0 14 3
B observe() 0 22 4
A set() 0 14 3
B collect() 0 23 4
A flush() 0 3 1
A __construct() 0 4 1
A decrement() 0 14 3
1
<?php
2
3
namespace Krenor\Prometheus\Storage;
4
5
use Exception;
6
use Krenor\Prometheus\Metrics\Summary;
7
use Krenor\Prometheus\Contracts\Metric;
8
use Krenor\Prometheus\Contracts\Storage;
9
use Krenor\Prometheus\Metrics\Histogram;
10
use Tightenco\Collect\Support\Collection;
11
use Krenor\Prometheus\Contracts\Repository;
12
use Krenor\Prometheus\Contracts\Types\Settable;
13
use Krenor\Prometheus\Exceptions\LabelException;
14
use Krenor\Prometheus\Contracts\Types\Observable;
15
use Krenor\Prometheus\Exceptions\StorageException;
16
use Krenor\Prometheus\Contracts\Types\Decrementable;
17
use Krenor\Prometheus\Contracts\Types\Incrementable;
18
use Krenor\Prometheus\Storage\Concerns\StoresMetrics;
19
20
class StorageManager implements Storage
21
{
22
    use StoresMetrics;
23
24
    /**
25
     * @var Repository
26
     */
27
    protected $repository;
28
29
    /**
30
     * @var string
31
     */
32
    protected $prefix;
33
34
    /**
35
     * StorageManager constructor.
36
     *
37
     * @param Repository $repository
38
     * @param string|null $prefix
39
     */
40 47
    public function __construct(Repository $repository, ?string $prefix = 'PROMETHEUS')
41
    {
42 47
        $this->repository = $repository;
43 47
        $this->prefix = $prefix;
44 47
    }
45
46
    /**
47
     * {@inheritdoc}
48
     */
49 34
    public function collect(Metric $metric): Collection
50
    {
51 34
        $key = "{$this->prefix}:{$metric->key()}";
52
53
        try {
54 34
            $items = $this->repository->get($key);
55
56
            switch (true) {
57 33
                case $metric instanceof Histogram:
58 6
                    return $metric->builder($items->merge($this->repository->get("{$key}:SUM")))
59 6
                                  ->samples();
60 27
                case $metric instanceof Summary:
61
                    return $metric->builder($items->map(function (string $key) {
62 6
                        return $this->repository->get($key);
63 6
                    }))->samples();
64
                default:
65 21
                    return $metric->builder($items)
66 21
                                  ->samples();
67
            }
68 1
        } catch (Exception $e) {
69 1
            $class = get_class($metric);
70
71 1
            throw new StorageException("Failed to collect the samples of [{$class}]: {$e->getMessage()}", 0, $e);
72
        }
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 18
    public function increment(Incrementable $metric, float $value, array $labels): void
79
    {
80
        try {
81 18
            $this->repository->increment(
82 18
                "{$this->prefix}:{$metric->key()}",
0 ignored issues
show
Bug introduced by
The method key() does not exist on Krenor\Prometheus\Contracts\Types\Incrementable. Since it exists in all sub-types, consider adding an abstract or default implementation to Krenor\Prometheus\Contracts\Types\Incrementable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
83 18
                $this->labeled($metric, $labels)->toJson(),
84 17
                $value
85
            );
86 2
        } catch (LabelException $e) {
87 1
            throw $e;
88 1
        } catch (Exception $e) {
89 1
            $class = get_class($metric);
90
91 1
            throw new StorageException("Failed to increment [{$class}] by `{$value}`: {$e->getMessage()}", 0, $e);
92
        }
93 16
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 8
    public function decrement(Decrementable $metric, float $value, array $labels): void
99
    {
100
        try {
101 8
            $this->repository->decrement(
102 8
                "{$this->prefix}:{$metric->key()}",
0 ignored issues
show
Bug introduced by
The method key() does not exist on Krenor\Prometheus\Contracts\Types\Decrementable. Since it exists in all sub-types, consider adding an abstract or default implementation to Krenor\Prometheus\Contracts\Types\Decrementable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

102
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
103 8
                $this->labeled($metric, $labels)->toJson(),
104 7
                $value
105
            );
106 2
        } catch (LabelException $e) {
107 1
            throw $e;
108 1
        } catch (Exception $e) {
109 1
            $class = get_class($metric);
110
111 1
            throw new StorageException("Failed to decrement [{$class}] by `{$value}`: {$e->getMessage()}", 0, $e);
112
        }
113 6
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 14
    public function observe(Observable $metric, float $value, array $labels): void
119
    {
120 14
        $key = "{$this->prefix}:{$metric->key()}";
0 ignored issues
show
Bug introduced by
The method key() does not exist on Krenor\Prometheus\Contracts\Types\Observable. Since it exists in all sub-types, consider adding an abstract or default implementation to Krenor\Prometheus\Contracts\Types\Observable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

120
        $key = "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}";
Loading history...
121 14
        $labeled = $this->labeled($metric, $labels);
122 13
        $field = $labeled->toJson();
123
124
        try {
125 13
            if ($metric instanceof Histogram) {
126 7
                $this->repository->increment($key, $labeled->merge($this->bucket($metric, $value))->toJson(), 1);
127 6
                $this->repository->increment("{$key}:SUM", $field, $value);
128
            }
129
130 12
            if ($metric instanceof Summary) {
131 6
                $identifier = "{$key}:" . crc32($field) . ':VALUES';
132
133 6
                $this->repository->set($key, $field, $identifier, false);
134 12
                $this->repository->push($identifier, $value);
135
            }
136 1
        } catch (Exception $e) {
137 1
            $class = get_class($metric);
138
139 1
            throw new StorageException("Failed to observe [{$class}] with `{$value}`: {$e->getMessage()}", 0, $e);
140
        }
141 12
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146 8
    public function set(Settable $metric, float $value, array $labels): void
147
    {
148
        try {
149 8
            $this->repository->set(
150 8
                "{$this->prefix}:{$metric->key()}",
0 ignored issues
show
Bug introduced by
The method key() does not exist on Krenor\Prometheus\Contracts\Types\Settable. Since it exists in all sub-types, consider adding an abstract or default implementation to Krenor\Prometheus\Contracts\Types\Settable. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

150
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
151 8
                $this->labeled($metric, $labels)->toJson(),
152 7
                $value
153
            );
154 2
        } catch (LabelException $e) {
155 1
            throw $e;
156 1
        } catch (Exception $e) {
157 1
            $class = get_class($metric);
158
159 1
            throw new StorageException("Failed to set [{$class}] to `{$value}`: {$e->getMessage()}", 0, $e);
160
        }
161 6
    }
162
163
    /**
164
     * @return bool
165
     */
166
    public function flush(): bool
167
    {
168
        return $this->repository->flush();
169
    }
170
}
171