From c5621b82cfeddee23b81871a53035fde747f73a9 Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Tue, 18 Dec 2018 02:23:44 +0100 Subject: Implemented /metrics endpoint and reimplemented /stats closes #418 (/metrics endpoint) Usage: ```yaml scrape_configs: - job_name: 'engelsystem' static_configs: - targets: ['engelsystem.example.com:80'] ``` --- src/Controllers/Metrics/MetricsEngine.php | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/Controllers/Metrics/MetricsEngine.php (limited to 'src/Controllers/Metrics/MetricsEngine.php') 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 @@ + [['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 + ); + } +} -- cgit v1.2.3-70-g09d2