ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
5 namespace ILIAS\Setup\Metrics;
6 
9 
17 final 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
176  case self::TYPE_COUNTER:
177  return "$value";
178  case self::TYPE_GAUGE:
179  if (is_int($value)) {
180  return "$value";
181  }
182  return sprintf("%.03f", $value);
183  case self::TYPE_TIMESTAMP:
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;
190  case self::TYPE_COLLECTION:
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  }
222  case self::TYPE_COUNTER:
223  return (string)$value;
224  case self::TYPE_GAUGE:
225  if (is_int($value)) {
226  return (string)$value;
227  }
228  return sprintf("%.03f", $value);
229  case self::TYPE_TIMESTAMP:
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;
236  case self::TYPE_COLLECTION:
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(
291  $stability,
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 }
$rest
Definition: goto.php:48
$result
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
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
A metric is something we can measure about the system.
Definition: Metric.php:17
if($format !==null) $name
Definition: metadata.php:230
This describes how a Report could be modified during construction of UI.
Definition: Report.php:10
foreach($_POST as $key=> $value) $res
checkValue($type, $value)
Definition: Metric.php:116
Builds data types.
Definition: Factory.php:19
toYAML(int $indentation=0)
Definition: Metric.php:165
toUIReport(Factory $f, string $name)
Definition: Metric.php:314
__construct(string $stability, string $type, $value, string $description=null)
Definition: Metric.php:70
getIndentation(int $indentation=0)
Definition: Metric.php:247
checkStability($stability, $type)
Definition: Metric.php:86
const STABILITY_CONFIG
The stability of a metric tells how often we expect changes in the metric.
Definition: Metric.php:24