From 53848ed5b7abc3b077bc5fff6f7589d7f138bbfa Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Thu, 21 Sep 2017 16:45:37 +0200 Subject: [PATCH] Implement simple-to-use image URLs /graph/* refs #46 --- application/controllers/GraphController.php | 117 ++++++++++++++++++++ library/Graphite/Web/Widget/Graphs.php | 93 +++------------- library/Graphite/Web/Widget/GraphsTrait.php | 98 ++++++++++++++++ 3 files changed, 228 insertions(+), 80 deletions(-) create mode 100644 application/controllers/GraphController.php create mode 100644 library/Graphite/Web/Widget/GraphsTrait.php diff --git a/application/controllers/GraphController.php b/application/controllers/GraphController.php new file mode 100644 index 0000000..d50cba2 --- /dev/null +++ b/application/controllers/GraphController.php @@ -0,0 +1,117 @@ +service = false; + + $this->supplyImage(); + } + + public function serviceAction() + { + $this->supplyImage(); + } + + /** + * Do all monitored object type independend actions + */ + protected function supplyImage() + { + $this->filterParams = clone $this->getRequest()->getUrl()->getParams(); + + foreach ($this->geometryParamsNames as $paramName) { + $this->geometryParams[$paramName] = $this->filterParams->shift($paramName); + } + + $this->collectTemplates(); + $this->collectGraphiteQueries(); + + $charts = []; + foreach ($this->graphiteQueries as $templateName => $graphiteQuery) { + /** @var GraphiteQuery $graphiteQuery */ + + $charts = array_merge($charts, $graphiteQuery->getImages($this->templates[$templateName])); + if (count($charts) > 1) { + throw new HttpBadRequestException('%s', $this->translate( + 'Graphite Web yields more than one metric for the given filter.' + . ' Please specify a more precise filter.' + )); + } + } + + if (empty($charts)) { + throw new HttpNotFoundException('%s', $this->translate('No such graph')); + } + + $image = $charts[0] + ->setStart($this->geometryParams['start']) + ->setUntil($this->geometryParams['end']) + ->setWidth($this->geometryParams['width']) + ->setHeight($this->geometryParams['height']) + ->showLegend((bool) $this->geometryParams['legend']) + ->fetchImage(); + + $this->_helper->layout()->disableLayout(); + + header('Content-Type: image/png'); + header('Content-Disposition: inline; filename="graph.png"'); + echo $image; + exit; + } + + protected function includeTemplate(GraphTemplate $template) + { + return (strpos($template->getFilterString(), '$service') !== false) === $this->service; + } + + protected function filterGraphiteQuery(GraphiteQuery $query) + { + foreach ($this->filterParams->toArray() as list($key, $value)) { + $query->where($key, $value); + } + + return $query; + } +} diff --git a/library/Graphite/Web/Widget/Graphs.php b/library/Graphite/Web/Widget/Graphs.php index fabb210..cad9269 100644 --- a/library/Graphite/Web/Widget/Graphs.php +++ b/library/Graphite/Web/Widget/Graphs.php @@ -22,19 +22,7 @@ use Icinga\Web\Widget\AbstractWidget; abstract class Graphs extends AbstractWidget { - /** - * [$setName => $set] - * - * @var TemplateSet[string] - */ - protected static $templateSets; - - /** - * [$setName => [$templateName => $template]] - * - * @var GraphTemplate[string][string] - */ - protected static $allTemplates = []; + use GraphsTrait; /** * Graph image width @@ -80,11 +68,6 @@ abstract class Graphs extends AbstractWidget */ protected $images; - /** - * @var GraphTemplate[string] - */ - protected $templates; - /** * Factory, based on the given object * @@ -185,77 +168,27 @@ abstract class Graphs extends AbstractWidget return [$params->get($absolute['start'], '-1hours'), $params->get($absolute['end'])]; } - /** - * Initialize {@link templates} - */ - protected function collectTemplates() - { - if (static::$templateSets === null) { - static::$templateSets = (new TemplateStore())->loadTemplateSets(); - } - - foreach (static::$templateSets as $setname => $set) { - /** @var TemplateSet $set */ - - if (array_key_exists('icingaHost', $set->getBasePatterns())) { - if (! isset(static::$allTemplates[$setname])) { - static::$allTemplates[$setname] = $set->loadTemplates(); - } - - foreach (static::$allTemplates[$setname] as $templateName => $template) { - /** @var GraphTemplate $template */ - - if ($this->includeTemplate($template)) { - $this->templates[$templateName] = $template; - } - } - } - } - } - /** * Initialize {@link images} */ protected function collectImages() { - $graphiteWeb = new GraphiteWeb(GraphiteWebClient::getInstance()); - foreach ($this->templates as $templateName => $template) { - /** @var GraphTemplate $template */ + $this->collectGraphiteQueries(); - $this->images[$templateName] = $this->filterGraphiteQuery( - $graphiteWeb->select()->from($template->getFilterString()) - ) - ->getWrappedImageLinks( - $template, - TimeRangePickerTrait::copyAllRangeParameters( - (new UrlParams()) - ->set('template', $templateName) - ->set('start', $this->start) - ->set('width', $this->width) - ->set('height', $this->height) - ) - ); + foreach ($this->graphiteQueries as $templateName => $graphiteQuery) { + $this->images[$templateName] = $graphiteQuery->getWrappedImageLinks( + $this->templates[$templateName], + TimeRangePickerTrait::copyAllRangeParameters( + (new UrlParams()) + ->set('template', $templateName) + ->set('start', $this->start) + ->set('width', $this->width) + ->set('height', $this->height) + ) + ); } } - /** - * Add filters to the given query so that only specific graphs are shown - * - * @param GraphiteQuery $query - * - * @return GraphiteQuery The given query - */ - abstract protected function filterGraphiteQuery(GraphiteQuery $query); - - /** - * Return whether to use the given template - * - * @param GraphTemplate $template - * - * @return bool - */ - abstract protected function includeTemplate(GraphTemplate $template); - /** * Get {@link compact} * diff --git a/library/Graphite/Web/Widget/GraphsTrait.php b/library/Graphite/Web/Widget/GraphsTrait.php new file mode 100644 index 0000000..f94fb21 --- /dev/null +++ b/library/Graphite/Web/Widget/GraphsTrait.php @@ -0,0 +1,98 @@ + $set] + * + * @var TemplateSet[string] + */ + protected static $templateSets; + + /** + * [$setName => [$templateName => $template]] + * + * @var GraphTemplate[string][string] + */ + protected static $allTemplates = []; + + /** + * @var GraphTemplate[string] + */ + protected $templates; + + /** + * @var GraphiteQuery[string] + */ + protected $graphiteQueries; + + /** + * Initialize {@link templates} + */ + protected function collectTemplates() + { + if (static::$templateSets === null) { + static::$templateSets = (new TemplateStore())->loadTemplateSets(); + } + + foreach (static::$templateSets as $setname => $set) { + /** @var TemplateSet $set */ + + if (array_key_exists('icingaHost', $set->getBasePatterns())) { + if (! isset(static::$allTemplates[$setname])) { + static::$allTemplates[$setname] = $set->loadTemplates(); + } + + foreach (static::$allTemplates[$setname] as $templateName => $template) { + /** @var GraphTemplate $template */ + + if ($this->includeTemplate($template)) { + $this->templates[$templateName] = $template; + } + } + } + } + } + + /** + * Initialize {@link graphiteQueries} + */ + protected function collectGraphiteQueries() + { + $graphiteWeb = new GraphiteWeb(GraphiteWebClient::getInstance()); + foreach ($this->templates as $templateName => $template) { + /** @var GraphTemplate $template */ + + $this->graphiteQueries[$templateName] = $this->filterGraphiteQuery( + $graphiteWeb->select()->from($template->getFilterString()) + ); + } + } + + /** + * Return whether to use the given template + * + * @param GraphTemplate $template + * + * @return bool + */ + abstract protected function includeTemplate(GraphTemplate $template); + + /** + * Add filters to the given query so that only specific graphs are shown + * + * @param GraphiteQuery $query + * + * @return GraphiteQuery The given query + */ + abstract protected function filterGraphiteQuery(GraphiteQuery $query); +}