ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
Metric.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
21 namespace ILIAS\Setup\Metrics;
22 
25 
33 final class Metric
34 {
38  // Config metrics only change when some administrator explicitely changes
39  // a configuration.
40  public const STABILITY_CONFIG = "config";
41  // Stable metric only change occassionally when some change in the installation
42  // happened, e.g. a config change or an update.
43  public const STABILITY_STABLE = "stable";
44  // Volatile metrics may change at every time even unexpectedly.
45  public const STABILITY_VOLATILE = "volatile";
46  // This should only be used for collections with mixed content.
47  public const STABILITY_MIXED = "mixed";
48 
52  // Simply a yes or a no.
53  public const TYPE_BOOL = "bool";
54  // A number that always increases.
55  public const TYPE_COUNTER = "counter";
56  // A numeric value to measure some quantity of the installation.
57  public const TYPE_GAUGE = "gauge";
58  // A timestamp to inform about a certain event in the installation.
59  public const TYPE_TIMESTAMP = "timestamp";
60  // Some textual information about the installation. Prefer using one of the
61  // other types.
62  public const TYPE_TEXT = "text";
63  // A collection of metrics that contains multiple named metrics.
64  public const TYPE_COLLECTION = "collection";
65 
69  protected string $stability;
70 
74  protected string $type;
75 
79  protected $value;
80 
81 
82  protected ?string $description;
83 
84  public function __construct(
85  string $stability,
86  string $type,
87  $value,
88  string $description = null
89  ) {
90  $this->checkStability($stability, $type);
91  $this->checkType($type);
92  $this->checkValue($type, $value);
93 
94  $this->stability = $stability;
95  $this->type = $type;
96  $this->value = $value;
97  $this->description = $description;
98  }
99 
100  protected function checkStability(string $stability, string $type): void
101  {
102  if (
103  $stability !== self::STABILITY_CONFIG
104  && $stability !== self::STABILITY_STABLE
105  && $stability !== self::STABILITY_VOLATILE
106  && !($stability === self::STABILITY_MIXED && $type === self::TYPE_COLLECTION)
107  ) {
108  throw new \InvalidArgumentException(
109  "Invalid stability for metric: $stability"
110  );
111  }
112  }
113 
114  protected function checkType($type): void
115  {
116  if (
117  $type !== self::TYPE_BOOL
118  && $type !== self::TYPE_COUNTER
119  && $type !== self::TYPE_GAUGE
120  && $type !== self::TYPE_TIMESTAMP
121  && $type !== self::TYPE_TEXT
122  && $type !== self::TYPE_COLLECTION
123  ) {
124  throw new \InvalidArgumentException(
125  "Invalid type for metric: $type"
126  );
127  }
128  }
129 
130  protected function checkValue($type, $value): void
131  {
132  if (
133  ($type === self::TYPE_BOOL && !is_bool($value))
134  || ($type === self::TYPE_COUNTER && !is_int($value))
135  || ($type === self::TYPE_GAUGE && !(is_int($value) || is_float($value)))
136  || ($type === self::TYPE_TIMESTAMP && !($value instanceof \DateTimeImmutable))
137  || ($type === self::TYPE_TEXT && !is_string($value))
138  || ($type === self::TYPE_COLLECTION && !is_array($value))
139  ) {
140  throw new \InvalidArgumentException(
141  "Invalid type " . gettype($value) . " for metric of type $type"
142  );
143  }
144 
145  if ($type === self::TYPE_COLLECTION) {
146  foreach ($value as $v) {
147  if (!($v instanceof Metric)) {
148  throw new \InvalidArgumentException(
149  "Every element of a collection needs to be a metric, found " . gettype($v)
150  );
151  }
152  }
153  }
154  }
155 
156  public function getStability(): string
157  {
158  return $this->stability;
159  }
160 
161  public function getType(): string
162  {
163  return $this->type;
164  }
165 
169  public function getValue()
170  {
171  return $this->value;
172  }
173 
174  public function getDescription(): ?string
175  {
176  return $this->description;
177  }
178 
179  public function toYAML(int $indentation = 0): string
180  {
181  $value = $this->getValue();
182  switch ($this->getType()) {
183  case self::TYPE_BOOL:
184  if ($value) {
185  return "true";
186  } else {
187  return "false";
188  }
189  // no break
190  case self::TYPE_COUNTER:
191  return "$value";
192  case self::TYPE_GAUGE:
193  if (is_int($value)) {
194  return "$value";
195  }
196  return sprintf("%.03f", $value);
197  case self::TYPE_TIMESTAMP:
198  return $value->format(\DateTimeInterface::ISO8601);
199  case self::TYPE_TEXT:
200  if (substr_count($value, "\n") > 0) {
201  return ">" . str_replace("\n", "\n" . $this->getIndentation($indentation), "\n$value");
202  }
203  return $value;
204  case self::TYPE_COLLECTION:
205  return implode(
206  "\n",
207  array_map(
208  function (string $k, Metric $v) use ($indentation): string {
209  if ($v->getType() === self::TYPE_COLLECTION) {
210  $split = "\n";
211  } else {
212  $split = " ";
213  }
214  return $this->getIndentation($indentation) . "$k:$split" . $v->toYAML($indentation + 1);
215  },
216  array_keys($value),
217  array_values($value)
218  )
219  );
220  default:
221  throw new \LogicException("Unknown type: " . $this->getType());
222  }
223  }
224 
225  public function toArray(int $indentation = 0)
226  {
227  $value = $this->getValue();
228 
229  switch ($this->getType()) {
230  case self::TYPE_BOOL:
231  if ($value) {
232  return "true";
233  } else {
234  return "false";
235  }
236  // no break
237  case self::TYPE_COUNTER:
238  return (string) $value;
239  case self::TYPE_GAUGE:
240  if (is_int($value)) {
241  return (string) $value;
242  }
243  return sprintf("%.03f", $value);
244  case self::TYPE_TIMESTAMP:
245  return $value->format(\DateTimeInterface::ISO8601);
246  case self::TYPE_TEXT:
247  if (substr_count($value, "\n") > 0) {
248  return ">" . str_replace("\n", "\n" . $this->getIndentation($indentation), "\n$value");
249  }
250  return $value;
251  case self::TYPE_COLLECTION:
252  $result = [];
253  foreach ($value as $key => $val) {
254  $result[$key] = $val->toArray($indentation + 1);
255  }
256  return $result;
257  default:
258  throw new \LogicException("Unknown type: " . $this->getType());
259  }
260  }
261 
262  protected function getIndentation(int $indentation = 0): string
263  {
264  $res = "";
265  while ($indentation--) {
266  $res .= " ";
267  }
268  return $res;
269  }
270 
277  public function extractByStability(string $stability): array
278  {
279  if ($stability === self::STABILITY_MIXED) {
280  throw new \LogicException("Can not extract by mixed.");
281  }
282 
283  if ($this->getStability() === $stability) {
284  return [$this, null];
285  }
286  if ($this->getType() !== self::TYPE_COLLECTION) {
287  return [null, $this];
288  }
289 
290  // Now, this is a mixed collection. We need to go down.
291  $values = $this->getValue();
292  $extracted = [];
293  $rest = [];
294  foreach ($values as $k => $v) {
295  list($e, $r) = $v->extractByStability($stability);
296  if ($e !== null) {
297  $extracted[$k] = $e;
298  }
299  if ($r !== null) {
300  $rest[$k] = $r;
301  }
302  }
303 
304  if ($extracted !== []) {
305  $extracted = new Metric(
306  $stability,
307  self::TYPE_COLLECTION,
308  $extracted,
309  $this->getDescription()
310  );
311  } else {
312  $extracted = null;
313  }
314 
315  if ($rest !== []) {
316  $rest = new Metric(
317  $this->getStability(),
318  self::TYPE_COLLECTION,
319  $rest,
320  $this->getDescription()
321  );
322  } else {
323  $rest = null;
324  }
325 
326  return [$extracted, $rest];
327  }
328 
329  public function toUIReport(Factory $f, string $name): Report
330  {
331  $yaml = $this->toYAML();
332  $sub = $f->panel()->sub("", $f->legacy("<pre>" . $yaml . "</pre>"));
333  return $f->panel()->report($name, [$sub]);
334  }
335 }
$res
Definition: ltiservices.php:69
$rest
Definition: goto.php:49
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:277
toArray(int $indentation=0)
Definition: Metric.php:225
checkStability(string $stability, string $type)
Definition: Metric.php:100
const TYPE_BOOL
The type of the metric tells what to expect of the values.
Definition: Metric.php:53
A metric is something we can measure about the system.
Definition: Metric.php:33
if($format !==null) $name
Definition: metadata.php:247
This describes how a Report could be modified during construction of UI.
Definition: Report.php:26
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
string $key
Consumer key/client ID value.
Definition: System.php:193
checkValue($type, $value)
Definition: Metric.php:130
toYAML(int $indentation=0)
Definition: Metric.php:179
toUIReport(Factory $f, string $name)
Definition: Metric.php:329
__construct(string $stability, string $type, $value, string $description=null)
Definition: Metric.php:84
getIndentation(int $indentation=0)
Definition: Metric.php:262
const STABILITY_CONFIG
The stability of a metric tells how often we expect changes in the metric.
Definition: Metric.php:40