ILIAS  release_7 Revision v7.30-3-g800a261c036
Metric.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2020 Richard Klees <richard.klees@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4
5namespace ILIAS\Setup\Metrics;
6
9
17final class Metric
18{
22 // Config metrics only change when some administrator explicitely changes
23 // a configuration.
24 const STABILITY_CONFIG = "config";
25 // Stable metric only change occassionally when some change in the installation
26 // happened, e.g. a config change or an update.
27 const STABILITY_STABLE = "stable";
28 // Volatile metrics may change at every time even unexpectedly.
29 const STABILITY_VOLATILE = "volatile";
30 // This should only be used for collections with mixed content.
31 const STABILITY_MIXED = "mixed";
32
36 // Simply a yes or a no.
37 const TYPE_BOOL = "bool";
38 // A number that always increases.
39 const TYPE_COUNTER = "counter";
40 // A numeric value to measure some quantity of the installation.
41 const TYPE_GAUGE = "gauge";
42 // A timestamp to inform about a certain event in the installation.
43 const TYPE_TIMESTAMP = "timestamp";
44 // Some textual information about the installation. Prefer using one of the
45 // other types.
46 const TYPE_TEXT = "text";
47 // A collection of metrics that contains multiple named metrics.
48 const TYPE_COLLECTION = "collection";
49
53 protected $stability;
54
58 protected $type;
59
63 protected $value;
64
68 protected $description;
69
70 public function __construct(
71 string $stability,
72 string $type,
73 $value,
74 string $description = null
75 ) {
76 $this->checkStability($stability, $type);
77 $this->checkType($type);
78 $this->checkValue($type, $value);
79
80 $this->stability = $stability;
81 $this->type = $type;
82 $this->value = $value;
83 $this->description = $description;
84 }
85
86 protected function checkStability($stability, $type)
87 {
88 if (
89 $stability !== self::STABILITY_CONFIG
90 && $stability !== self::STABILITY_STABLE
91 && $stability !== self::STABILITY_VOLATILE
92 && !($stability === self::STABILITY_MIXED && $type === self::TYPE_COLLECTION)
93 ) {
94 throw new \InvalidArgumentException(
95 "Invalid stability for metric: $stability"
96 );
97 }
98 }
99
100 protected function checkType($type)
101 {
102 if (
103 $type !== self::TYPE_BOOL
104 && $type !== self::TYPE_COUNTER
105 && $type !== self::TYPE_GAUGE
106 && $type !== self::TYPE_TIMESTAMP
107 && $type !== self::TYPE_TEXT
108 && $type !== self::TYPE_COLLECTION
109 ) {
110 throw new \InvalidArgumentException(
111 "Invalid type for metric: $type"
112 );
113 }
114 }
115
116 protected function checkValue($type, $value)
117 {
118 if (
119 ($type === self::TYPE_BOOL && !is_bool($value))
120 || ($type === self::TYPE_COUNTER && !is_int($value))
121 || ($type === self::TYPE_GAUGE && !(is_int($value) || is_float($value)))
122 || ($type === self::TYPE_TIMESTAMP && !($value instanceof \DateTimeImmutable))
123 || ($type === self::TYPE_TEXT && !is_string($value))
124 || ($type === self::TYPE_COLLECTION && !is_array($value))
125 ) {
126 throw new \InvalidArgumentException(
127 "Invalid type " . gettype($value) . " for metric of type $type"
128 );
129 }
130
131 if ($type === self::TYPE_COLLECTION) {
132 foreach ($value as $v) {
133 if (!($v instanceof Metric)) {
134 throw new \InvalidArgumentException(
135 "Every element of a collection needs to be a metric, found " . gettype($v)
136 );
137 }
138 }
139 }
140 }
141
142 public function getStability() : string
143 {
144 return $this->stability;
145 }
146
147 public function getType() : string
148 {
149 return $this->type;
150 }
151
155 public function getValue()
156 {
157 return $this->value;
158 }
159
160 public function getDescription() : ?string
161 {
162 return $this->description;
163 }
164
165 public function toYAML(int $indentation = 0) : string
166 {
167 $value = $this->getValue();
168 switch ($this->getType()) {
169 case self::TYPE_BOOL:
170 if ($value) {
171 return "true";
172 } else {
173 return "false";
174 }
175 // no break
177 return "$value";
178 case self::TYPE_GAUGE:
179 if (is_int($value)) {
180 return "$value";
181 }
182 return sprintf("%.03f", $value);
184 return $value->format(\DateTimeInterface::ISO8601);
185 case self::TYPE_TEXT:
186 if (substr_count($value, "\n") > 0) {
187 return ">" . str_replace("\n", "\n" . $this->getIndentation($indentation), "\n$value");
188 }
189 return $value;
191 return implode(
192 "\n",
193 array_map(
194 function ($k, $v) use ($indentation) {
195 if ($v->getType() === self::TYPE_COLLECTION) {
196 $split = "\n";
197 } else {
198 $split = " ";
199 }
200 return $this->getIndentation($indentation) . "$k:$split" . $v->toYAML($indentation + 1);
201 },
202 array_keys($value),
203 array_values($value)
204 )
205 );
206 default:
207 throw new \LogicException("Unknown type: " . $this->getType());
208 }
209 }
210
211 public function toArray(int $indentation = 0)
212 {
213 $value = $this->getValue();
214
215 switch ($this->getType()) {
216 case self::TYPE_BOOL:
217 if ($value) {
218 return "true";
219 } else {
220 return "false";
221 }
223 return (string)$value;
224 case self::TYPE_GAUGE:
225 if (is_int($value)) {
226 return (string)$value;
227 }
228 return sprintf("%.03f", $value);
230 return $value->format(\DateTimeInterface::ISO8601);
231 case self::TYPE_TEXT:
232 if (substr_count($value, "\n") > 0) {
233 return ">" . str_replace("\n", "\n" . $this->getIndentation($indentation), "\n$value");
234 }
235 return $value;
237 $result = [];
238 foreach ($value as $key => $val) {
239 $result[$key] = $val->toArray($indentation + 1);
240 }
241 return $result;
242 default:
243 throw new \LogicException("Unknown type: " . $this->getType());
244 }
245 }
246
247 protected function getIndentation(int $indentation = 0)
248 {
249 $res = "";
250 while ($indentation--) {
251 $res .= " ";
252 }
253 return $res;
254 }
255
262 public function extractByStability(string $stability) : array
263 {
264 if ($stability === self::STABILITY_MIXED) {
265 throw new \LogicException("Can not extract by mixed.");
266 }
267
268 if ($this->getStability() === $stability) {
269 return [$this, null];
270 }
271 if ($this->getType() !== self::TYPE_COLLECTION) {
272 return [null, $this];
273 }
274
275 // Now, this is a mixed collection. We need to go down.
276 $values = $this->getValue();
277 $extracted = [];
278 $rest = [];
279 foreach ($values as $k => $v) {
280 list($e, $r) = $v->extractByStability($stability);
281 if ($e !== null) {
282 $extracted[$k] = $e;
283 }
284 if ($r !== null) {
285 $rest[$k] = $r;
286 }
287 }
288
289 if (count($extracted)) {
290 $extracted = new Metric(
292 self::TYPE_COLLECTION,
293 $extracted,
294 $this->getDescription()
295 );
296 } else {
297 $extracted = null;
298 }
299
300 if (count($rest)) {
301 $rest = new Metric(
302 $this->getStability(),
303 self::TYPE_COLLECTION,
304 $rest,
305 $this->getDescription()
306 );
307 } else {
308 $rest = null;
309 }
310
311 return [$extracted, $rest];
312 }
313
314 public function toUIReport(Factory $f, string $name) : Report
315 {
316 $yaml = $this->toYAML();
317 $sub = $f->panel()->sub("", $f->legacy("<pre>" . $yaml . "</pre>"));
318 return $f->panel()->report($name, [$sub]);
319 }
320}
$result
An exception for terminatinating execution or to throw for unit testing.
Builds data types.
Definition: Factory.php:20
A metric is something we can measure about the system.
Definition: Metric.php:18
getIndentation(int $indentation=0)
Definition: Metric.php:247
toYAML(int $indentation=0)
Definition: Metric.php:165
checkStability($stability, $type)
Definition: Metric.php:86
checkValue($type, $value)
Definition: Metric.php:116
extractByStability(string $stability)
The extracted part will be the first entry of the array, the second will be the rest of the metrics.
Definition: Metric.php:262
__construct(string $stability, string $type, $value, string $description=null)
Definition: Metric.php:70
toArray(int $indentation=0)
Definition: Metric.php:211
const TYPE_BOOL
The type of the metric tells what to expect of the values.
Definition: Metric.php:37
toUIReport(Factory $f, string $name)
Definition: Metric.php:314
const STABILITY_CONFIG
The stability of a metric tells how often we expect changes in the metric.
Definition: Metric.php:24
$rest
Definition: goto.php:48
This describes how a Report could be modified during construction of UI.
Definition: Report.php:11
This is how the factory for UI elements looks.
Definition: Factory.php:18
if($format !==null) $name
Definition: metadata.php:230
foreach($_POST as $key=> $value) $res