Completed
Push — develop ( e4bc3c...28a887 )
by Stan
02:51
created

StorageManager::flush()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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
use Krenor\Prometheus\Storage\Collectors\SamplesCollector;
20
use Krenor\Prometheus\Storage\Collectors\SummarySamplesCollector;
21
use Krenor\Prometheus\Storage\Collectors\HistogramSamplesCollector;
22
23
class StorageManager implements Storage
24
{
25
    use StoresMetrics;
26
27
    /**
28
     * @var Repository
29
     */
30
    protected $repository;
31
32
    /**
33
     * @var string
34
     */
35
    protected $prefix;
36
37
    /**
38
     * StorageManager constructor.
39
     *
40
     * @param Repository $repository
41
     * @param string|null $prefix
42
     */
43 47
    public function __construct(Repository $repository, ?string $prefix = 'PROMETHEUS')
44
    {
45 47
        $this->repository = $repository;
46 47
        $this->prefix = $prefix;
47 47
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52 34
    public function collect(Metric $metric): Collection
53
    {
54 34
        $key = "{$this->prefix}:{$metric->key()}";
55
56
        try {
57 34
            $items = $this->repository->get($key);
58
59
            switch (true) {
60 33
                case $metric instanceof Histogram:
61 6
                    return $this->samples($metric, $items->merge($this->repository->get("{$key}:SUM")));
62 27
                case $metric instanceof Summary:
63
                    return $this->samples($metric, $items->map(function (string $key) {
64 6
                        return $this->repository->get($key);
65 6
                    }));
66
                default:
67 21
                    return $this->samples($metric, $items);
68
            }
69 1
        } catch (Exception $e) {
70 1
            $class = get_class($metric);
71
72 1
            throw new StorageException("Failed to collect the samples of [{$class}]: {$e->getMessage()}", 0, $e);
73
        }
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 18
    public function increment(Incrementable $metric, float $value, array $labels): void
80
    {
81
        try {
82 18
            $this->repository->increment(
83 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

83
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
84 18
                $this->labeled($metric, $labels)->toJson(),
85 17
                $value
86
            );
87 2
        } catch (LabelException $e) {
88 1
            throw $e;
89 1
        } catch (Exception $e) {
90 1
            $class = get_class($metric);
91
92 1
            throw new StorageException("Failed to increment [{$class}] by `{$value}`: {$e->getMessage()}", 0, $e);
93
        }
94 16
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99 8
    public function decrement(Decrementable $metric, float $value, array $labels): void
100
    {
101
        try {
102 8
            $this->repository->decrement(
103 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

103
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
104 8
                $this->labeled($metric, $labels)->toJson(),
105 7
                $value
106
            );
107 2
        } catch (LabelException $e) {
108 1
            throw $e;
109 1
        } catch (Exception $e) {
110 1
            $class = get_class($metric);
111
112 1
            throw new StorageException("Failed to decrement [{$class}] by `{$value}`: {$e->getMessage()}", 0, $e);
113
        }
114 6
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 14
    public function observe(Observable $metric, float $value, array $labels): void
120
    {
121 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

121
        $key = "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}";
Loading history...
122 14
        $labeled = $this->labeled($metric, $labels);
123 13
        $field = $labeled->toJson();
124
125
        try {
126 13
            if ($metric instanceof Histogram) {
127 7
                $this->repository->increment($key, $labeled->merge($this->bucket($metric, $value))->toJson(), 1);
128 6
                $this->repository->increment("{$key}:SUM", $field, $value);
129
            }
130
131 12
            if ($metric instanceof Summary) {
132 6
                $identifier = "{$key}:" . crc32($field) . ':VALUES';
133
134 6
                $this->repository->set($key, $field, $identifier, false);
135 12
                $this->repository->push($identifier, $value);
136
            }
137 1
        } catch (Exception $e) {
138 1
            $class = get_class($metric);
139
140 1
            throw new StorageException("Failed to observe [{$class}] with `{$value}`: {$e->getMessage()}", 0, $e);
141
        }
142 12
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147 8
    public function set(Settable $metric, float $value, array $labels): void
148
    {
149
        try {
150 8
            $this->repository->set(
151 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

151
                "{$this->prefix}:{$metric->/** @scrutinizer ignore-call */ key()}",
Loading history...
152 8
                $this->labeled($metric, $labels)->toJson(),
153 7
                $value
154
            );
155 2
        } catch (LabelException $e) {
156 1
            throw $e;
157 1
        } catch (Exception $e) {
158 1
            $class = get_class($metric);
159
160 1
            throw new StorageException("Failed to set [{$class}] to `{$value}`: {$e->getMessage()}", 0, $e);
161
        }
162 6
    }
163
164
    /**
165
     * @return bool
166
     */
167
    public function flush(): bool
168
    {
169
        return $this->repository->flush();
170
    }
171
172
    /**
173
     * @param Metric $metric
174
     * @param Collection $items
175
     *
176
     * @return Collection
177
     */
178 33
    protected function samples(Metric $metric, Collection $items): Collection
179
    {
180
        switch (true) {
181 33
            case $metric instanceof Histogram:
182 6
                return (new HistogramSamplesCollector($metric, $items))->collect();
183 27
            case $metric instanceof Summary:
184 6
                return (new SummarySamplesCollector($metric, $items))->collect();
185
            default:
186 21
                return (new SamplesCollector($metric, $items))->collect();
187
        }
188
    }
189
190
}
191