summaryrefslogtreecommitdiff
path: root/src/Controllers/Metrics/MetricsEngine.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Controllers/Metrics/MetricsEngine.php')
-rw-r--r--src/Controllers/Metrics/MetricsEngine.php137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/Controllers/Metrics/MetricsEngine.php b/src/Controllers/Metrics/MetricsEngine.php
new file mode 100644
index 00000000..eeb47d8a
--- /dev/null
+++ b/src/Controllers/Metrics/MetricsEngine.php
@@ -0,0 +1,137 @@
+<?php
+
+namespace Engelsystem\Controllers\Metrics;
+
+use Engelsystem\Renderer\EngineInterface;
+
+class MetricsEngine implements EngineInterface
+{
+ /**
+ * Render metrics
+ *
+ * @example $data = ['foo' => [['labels' => ['foo'=>'bar'], 'value'=>42]], 'bar'=>123]
+ *
+ * @param string $path
+ * @param mixed[] $data
+ * @return string
+ */
+ public function get($path, $data = []): string
+ {
+ $return = [];
+ foreach ($data as $name => $list) {
+ if (is_int($name)) {
+ $return[] = '# ' . $this->escape($list);
+ continue;
+ }
+
+ $list = is_array($list) ? $list : [$list];
+ $name = 'engelsystem_' . $name;
+
+ if (isset($list['help'])) {
+ $return[] = sprintf('# HELP %s %s', $name, $this->escape($list['help']));
+ unset($list['help']);
+ }
+
+ if (isset($list['type'])) {
+ $return[] = sprintf('# TYPE %s %s', $name, $list['type']);
+ unset($list['type']);
+ }
+
+ $list = (!isset($list['value']) || !isset($list['labels'])) ? $list : [$list];
+ foreach ($list as $row) {
+ $row = is_array($row) ? $row : [$row];
+
+ $return[] = $this->formatData($name, $row);
+ }
+ }
+
+ return implode("\n", $return);
+ }
+
+ /**
+ * @param string $path
+ * @return bool
+ */
+ public function canRender($path): bool
+ {
+ return $path == '/metrics';
+ }
+
+ /**
+ * @param string $name
+ * @param array|mixed $row
+ * @see https://prometheus.io/docs/instrumenting/exposition_formats/
+ * @return string
+ */
+ protected function formatData($name, $row): string
+ {
+ return sprintf(
+ '%s%s %s',
+ $name,
+ $this->renderLabels($row),
+ $this->renderValue($row));
+ }
+
+ /**
+ * @param array|mixed $row
+ * @return mixed
+ */
+ protected function renderLabels($row): string
+ {
+ $labels = [];
+ if (!is_array($row) || empty($row['labels'])) {
+ return '';
+ }
+
+ foreach ($row['labels'] as $type => $value) {
+ $labels[$type] = $type . '="' . $this->formatValue($value) . '"';
+ }
+
+ return '{' . implode(',', $labels) . '}';
+ }
+
+ /**
+ * @param array|mixed $row
+ * @return mixed
+ */
+ protected function renderValue($row)
+ {
+ if (isset($row['value'])) {
+ return $this->formatValue($row['value']);
+ }
+
+ return $this->formatValue(array_pop($row));
+ }
+
+ /**
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function formatValue($value)
+ {
+ if (is_bool($value)) {
+ return (int)$value;
+ }
+
+ return $this->escape($value);
+ }
+
+ /**
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function escape($value)
+ {
+ $replace = [
+ '\\' => '\\\\',
+ '"' => '\\"',
+ "\n" => '\\n',
+ ];
+
+ return str_replace(
+ array_keys($replace),
+ array_values($replace),
+ $value
+ );
+ }
+}