From e750c302dd8c1dc18fe2a36c2d5bfaf3eaf2723f Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 19 Sep 2017 17:18:40 +0200 Subject: [PATCH] Load graphs' s synchronously refs #48 --- application/controllers/ShowController.php | 116 -------- application/views/scripts/list/hosts.phtml | 4 +- application/views/scripts/list/services.phtml | 4 +- application/views/scripts/show/host.phtml | 40 --- application/views/scripts/show/service.phtml | 40 --- library/Graphite/EmbedGraphs.php | 66 ----- .../Monitoring/DetailviewExtension.php | 25 +- library/Graphite/Web/Widget/Graphs.php | 259 ++++++++++++++++++ library/Graphite/Web/Widget/Graphs/Host.php | 37 +++ .../Graphite/Web/Widget/Graphs/Service.php | 48 ++++ public/css/module.less | 2 +- 11 files changed, 353 insertions(+), 288 deletions(-) delete mode 100644 application/views/scripts/show/host.phtml delete mode 100644 application/views/scripts/show/service.phtml delete mode 100644 library/Graphite/EmbedGraphs.php create mode 100644 library/Graphite/Web/Widget/Graphs.php create mode 100644 library/Graphite/Web/Widget/Graphs/Host.php create mode 100644 library/Graphite/Web/Widget/Graphs/Service.php diff --git a/application/controllers/ShowController.php b/application/controllers/ShowController.php index 3b85366..71b6948 100644 --- a/application/controllers/ShowController.php +++ b/application/controllers/ShowController.php @@ -144,122 +144,6 @@ class ShowController extends Controller $this->view->image = $img->fetchImage(); } - public function hostAction() - { - $this->handleDatasourceToggles(); - $this->handleGraphParams(); - $hostname = $this->view->hostname = $this->params->get('host'); - if (! $hostname) { - throw new NotFoundError('Host is required'); - } - - $view = $this->view; - $this->getTabs()->add('host', array( - 'label' => $this->translate('Graphite - Single Host'), - 'url' => $this->getRequest()->getUrl() - ))->activate('host'); - - $imgs = array(); - $this->view->templates = array(); - - foreach ($this->templateStore->loadTemplateSets() as $setname => $set) { - - $patterns = $set->getBasePatterns(); - if (! array_key_exists('icingaHost', $patterns)) continue; - - foreach ($set->loadTemplates() as $key => $template) { - if (strpos($template->getFilterString(), '$service') !== false) continue; - - $imgParams = (new UrlParams()) - ->set('template', $key) - ->set('start', $view->start) - ->set('width', $view->width) - ->set('height', $view->height); - - if ($this->view->disabledDatasources) { - $imgParams->set('disabled', $this->view->disabledDatasources); - foreach ($this->view->disabledDatasources as $dis) { - if ($template->hasDatasource($dis)) { - $template->getDatasource($dis)->disable(); - } - } - } - - $this->view->templates[$key] = $template; - - $imgs[$key] = $this->graphiteWeb - ->select() - ->from($template->getFilterString()) - ->where('hostname', $hostname) - ->getWrappedImageLinks($template, TimeRangePickerTrait::copyAllRangeParameters($imgParams)); - - } - } - - $view->images = $imgs; - } - - public function serviceAction() - { - $this->handleDatasourceToggles(); - $this->handleGraphParams(); - $hostname = $this->view->hostname = $this->params->get('host'); - $service = $this->view->service = $this->params->get('service'); - if (! $hostname) { - throw new NotFoundError('Host is required'); - } - if (! $service) { - throw new NotFoundError('Service is required'); - } - $this->getTabs()->add('service', array( - 'label' => $this->translate('Graphite - Single service'), - 'url' => $this->getRequest()->getUrl() - ))->activate('service'); - - $view = $this->view; - - $imgs = array(); - $this->view->templates = array(); - - foreach ($this->templateStore->loadTemplateSets() as $setname => $set) { - - $patterns = $set->getBasePatterns(); - if (! array_key_exists('icingaHost', $patterns)) continue; - - foreach ($set->loadTemplates() as $key => $template) { - if (strpos($template->getFilterString(), '$service') === false) continue; - - $imgParams = (new UrlParams()) - ->set('template', $key) - ->set('start', $view->start) - ->set('width', $view->width) - ->set('height', $view->height);; - - if ($this->view->disabledDatasources) { - $imgParams->set('disabled', $this->view->disabledDatasources); - foreach ($this->view->disabledDatasources as $dis) { - if ($template->hasDatasource($dis)) { - $template->getDatasource($dis)->disable(); - } - - } - } - - $this->view->templates[$key] = $template; - - $imgs[$key] = $this->graphiteWeb - ->select() - ->from($template->getFilterString()) - ->where('hostname', $hostname) - ->where('service', $service) - ->getWrappedImageLinks($template, TimeRangePickerTrait::copyAllRangeParameters($imgParams)); - - } - } - - $view->images = $imgs; - } - public function XXXserviceAction() { $this->handleDatasourceToggles(); diff --git a/application/views/scripts/list/hosts.phtml b/application/views/scripts/list/hosts.phtml index 73b9938..c7ffd23 100644 --- a/application/views/scripts/list/hosts.phtml +++ b/application/views/scripts/list/hosts.phtml @@ -1,6 +1,6 @@ getFilter()->isEmpty()) { ) . ''; } - echo EmbedGraphs::host($host->host_name); + echo (new Host($host->host_name))->setCompact()->handleRequest(); echo ''; } diff --git a/application/views/scripts/list/services.phtml b/application/views/scripts/list/services.phtml index 1f108c8..ef8a395 100644 --- a/application/views/scripts/list/services.phtml +++ b/application/views/scripts/list/services.phtml @@ -1,6 +1,6 @@ getFilter()->isEmpty()) { ) . ''; } - echo EmbedGraphs::service($service->host_name, $service->service_description); + echo (new Service($service->host_name, $service->service_description))->setCompact()->handleRequest(); } if (! $compact && $services->hasMore()) { diff --git a/application/views/scripts/show/host.phtml b/application/views/scripts/show/host.phtml deleted file mode 100644 index 712cded..0000000 --- a/application/views/scripts/show/host.phtml +++ /dev/null @@ -1,40 +0,0 @@ - -
-tabs ?> -

hostname ?>

-
- - -
-images as $type => $imgs): ?> - 0): ?> - -
-{$this->escape(ucfirst($type))}"; - echo $this->partial( - 'show/legend.phtml', - array( - 'template' => $this->templates[$type], - 'disabledDatasources' => $this->disabledDatasources - ) - ); -} -?> - $url): ?> - - -
- - - - - -

translate('No graphs found') ?>

- - -
diff --git a/application/views/scripts/show/service.phtml b/application/views/scripts/show/service.phtml deleted file mode 100644 index ddabecd..0000000 --- a/application/views/scripts/show/service.phtml +++ /dev/null @@ -1,40 +0,0 @@ - -
-tabs ?> -

hostname ?>: service ?>

-
- - -
-images as $type => $imgs): ?> - 0): ?> - -
-{$this->escape(ucfirst($type))}"; - echo $this->partial( - 'show/legend.phtml', - array( - 'template' => $this->templates[$type], - 'disabledDatasources' => $this->disabledDatasources - ) - ); -} -?> - $url): ?> - - -
- - - - - -

translate('No graphs found') ?>

- - -
diff --git a/library/Graphite/EmbedGraphs.php b/library/Graphite/EmbedGraphs.php deleted file mode 100644 index 66212fc..0000000 --- a/library/Graphite/EmbedGraphs.php +++ /dev/null @@ -1,66 +0,0 @@ -href('graphite/show/host', ['host' => $host])); - } - - /** - * Embed all graphs of the given service of the given host - * - * @param string $host - * @param string $service - * - * @return string - */ - public static function service($host, $service) - { - return static::url(static::getView()->href('graphite/show/service', [ - 'host' => $host, - 'service' => $service - ])); - } - - /** - * Return a
which causes the framework JS to embed the given URL - * - * @param Url $url - * - * @return string - */ - protected static function url(Url $url) - { - TimeRangePickerTrait::copyAllRangeParameters($url->getParams()); - - // TODO(ak): EL says "
is enough", - // but this seems not to work for me - return '
'; - } - - /** - * Get the current response view - * - * @return View - */ - protected static function getView() - { - return Icinga::app()->getViewRenderer()->view; - } -} diff --git a/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php b/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php index 541b8b0..e6c8b25 100644 --- a/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php +++ b/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php @@ -2,37 +2,20 @@ namespace Icinga\Module\Graphite\ProvidedHook\Monitoring; -use Icinga\Module\Graphite\EmbedGraphs; use Icinga\Module\Graphite\Web\Controller\TimeRangePickerTrait; +use Icinga\Module\Graphite\Web\Widget\Graphs; use Icinga\Module\Monitoring\Hook\DetailviewExtensionHook; -use Icinga\Module\Monitoring\Object\Host; use Icinga\Module\Monitoring\Object\MonitoredObject; -use Icinga\Module\Monitoring\Object\Service; class DetailviewExtension extends DetailviewExtensionHook { use TimeRangePickerTrait; public function getHtmlForObject(MonitoredObject $object) - { - switch ($object->getType()) { - case 'host': - /** @var Host $object */ - return $this->getGeneric() . EmbedGraphs::host($object->getName()); - case 'service': - /** @var Service $object */ - return $this->getGeneric() . EmbedGraphs::service($object->getHost()->getName(), $object->getName()); - } - } - - /** - * Get monitored object type independend HTML to use - * - * @return string - */ - protected function getGeneric() { $this->handleTimeRangePickerRequest(); - return '

' . mt('graphite', 'Graphs') . '

' . $this->renderTimeRangePicker($this->getView()); + return '

' . mt('graphite', 'Graphs') . '

' + . $this->renderTimeRangePicker($this->getView()) + . Graphs::forMonitoredObject($object)->setCompact()->handleRequest(); } } diff --git a/library/Graphite/Web/Widget/Graphs.php b/library/Graphite/Web/Widget/Graphs.php new file mode 100644 index 0000000..788d481 --- /dev/null +++ b/library/Graphite/Web/Widget/Graphs.php @@ -0,0 +1,259 @@ + [$title => $url]] + * + * @var string[string][string] + */ + protected $images; + + /** + * @var GraphTemplate[string] + */ + protected $templates; + + /** + * Factory, based on the given object + * + * @param MonitoredObject $object + * + * @return static + */ + public static function forMonitoredObject(MonitoredObject $object) + { + switch ($object->getType()) { + case 'host': + /** @var Host $object */ + return (new HostGraphs($object->getName())); + + case 'service': + /** @var Service $object */ + return (new ServiceGraphs($object->getHost()->getName(), $object->getName())); + } + } + + /** + * Process the given request using this widget + * + * @param Request $request The request to be processed + * + * @return $this + */ + public function handleRequest(Request $request = null) + { + if ($request === null) { + $request = Icinga::app()->getRequest(); + } + + $this->handleGraphParams($request); + $this->collectTemplates(); + $this->collectImages(); + + return $this; + } + + public function render() + { + /** @var View $view */ + $view = $this->view(); + $rendered = ''; + + foreach ($this->images as $type => $images) { + if (count($images) > 0) { + $rendered .= '
'; + + if (! $this->compact) { + $rendered .= "

{$view->escape(ucfirst($type))}

{$view->partial( + 'show/legend.phtml', + ['template' => $this->templates[$type]] + )}"; + } + + foreach ($images as $title => $url) { + $rendered .= "\"\"width\" height=\"$this->height\" />"; + } + + $rendered .= '
'; + } + } + + return $rendered ?: "

{$view->escape($view->translate('No graphs found'))}

"; + } + + /** + * Handle the given request's parameters + * + * @param Request $request + */ + protected function handleGraphParams(Request $request) + { + $params = $request->getUrl()->getParams(); + list($this->start, $this->end) = $this->getRangeFromTimeRangePicker($request); + $this->width = $params->shift('width', '300'); + $this->height = $params->shift('height', '150'); + } + + /** + * Get time range parameters for Graphite from the URL + * + * @param Request $request The request to be used + * + * @return string[] + */ + protected function getRangeFromTimeRangePicker(Request $request) + { + $params = $request->getUrl()->getParams(); + $relative = $params->get(TimeRangePickerTrait::getRelativeRangeParameter()); + if ($relative !== null) { + return ["-{$relative}s", null]; + } + + $absolute = TimeRangePickerTrait::getAbsoluteRangeParameters(); + return [$params->get($absolute['start'], '-1hours'), $params->get($absolute['end'])]; + } + + /** + * Initialize {@link templates} + */ + protected function collectTemplates() + { + foreach ((new TemplateStore())->loadTemplateSets() as $setname => $set) { + /** @var TemplateSet $set */ + + if (array_key_exists('icingaHost', $set->getBasePatterns())) { + foreach ($set->loadTemplates() 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->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) + ) + ); + } + } + + /** + * 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} + * + * @return bool + */ + public function getCompact() + { + return $this->compact; + } + + /** + * Set {@link compact} + * + * @param bool $compact + * + * @return $this + */ + public function setCompact($compact = true) + { + $this->compact = $compact; + return $this; + } +} diff --git a/library/Graphite/Web/Widget/Graphs/Host.php b/library/Graphite/Web/Widget/Graphs/Host.php new file mode 100644 index 0000000..91c387b --- /dev/null +++ b/library/Graphite/Web/Widget/Graphs/Host.php @@ -0,0 +1,37 @@ +host = $host; + } + + protected function filterGraphiteQuery(GraphiteQuery $query) + { + return $query->where('hostname', $this->host); + } + + protected function includeTemplate(GraphTemplate $template) + { + return strpos($template->getFilterString(), '$service') === false; + } +} diff --git a/library/Graphite/Web/Widget/Graphs/Service.php b/library/Graphite/Web/Widget/Graphs/Service.php new file mode 100644 index 0000000..8aafb2a --- /dev/null +++ b/library/Graphite/Web/Widget/Graphs/Service.php @@ -0,0 +1,48 @@ +host = $host; + $this->service = $service; + } + + protected function filterGraphiteQuery(GraphiteQuery $query) + { + return $query + ->where('hostname', $this->host) + ->where('service', $this->service); + } + + protected function includeTemplate(GraphTemplate $template) + { + return strpos($template->getFilterString(), '$service') !== false; + } +} diff --git a/public/css/module.less b/public/css/module.less index 89a8e94..5ee9fdf 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -55,7 +55,7 @@ div.graphs-host { vertical-align: top; margin-right: 2em; - > div.container[data-icinga-url] { + > p { width: 300px; } }