s around the images * * @var string[] */ protected $classes = []; /** * The amount of graphs to show * * @var int */ protected $maxVisibleGraphs; /** * Whether to serve a transparent dummy image first and let the JS code load the actual graph * * @var bool */ protected $preloadDummy = false; /** * Whether to explicitly display that no graphs were found * * @var bool|null */ protected $showNoGraphsFound; /** * Cache for {@link getGraphsList()} * * @var string */ protected $graphsList; /** * 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(), $object->host_check_command, $object->{'_host_' . Graphs::getObscuredCheckCommandCustomVar()} ); case 'service': /** @var Service $object */ return new ServiceGraphs( $object->getHost()->getName(), $object->getName(), $object->service_check_command, $object->{'_service_' . Graphs::getObscuredCheckCommandCustomVar()} ); } } /** * Get the Icinga custom variable with the "real" check command (if any) of monitored objects we display graphs for * * @return string */ public static function getObscuredCheckCommandCustomVar() { if (static::$obscuredCheckCommandCustomVar === null) { static::$obscuredCheckCommandCustomVar = Config::module('graphite') ->get('icinga', 'customvar_obscured_check_command', 'check_command'); } return static::$obscuredCheckCommandCustomVar; } /** * Constructor * * @param string $checkCommand The check command of the monitored object we display graphs for * @param string|null $obscuredCheckCommand The "real" check command (if any) of the monitored object * we display graphs for */ public function __construct($checkCommand, $obscuredCheckCommand) { $this->checkCommand = $checkCommand; $this->obscuredCheckCommand = $obscuredCheckCommand; } /** * 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(); } $params = $request->getUrl()->getParams(); list($this->start, $this->end) = $this->getRangeFromTimeRangePicker($request); $this->width = $params->shift('width', $this->width); $this->height = $params->shift('height', $this->height); return $this; } /** * Render the graphs list * * @return string */ protected function getGraphsList() { if ($this->graphsList === null) { $result = []; // kind of string builder $filter = $this->getMonitoredObjectFilter(); $imageBaseUrl = $this->preloadDummy ? $this->getDummyImageBaseUrl() : $this->getImageBaseUrl(); $allTemplates = $this->getAllTemplates(); $concreteTemplates = $allTemplates->getTemplates( $this->obscuredCheckCommand === null ? $this->checkCommand : $this->obscuredCheckCommand ); $excludedMetrics = []; foreach ($concreteTemplates as $concreteTemplate) { foreach ($concreteTemplate->getCurves() as $curve) { $excludedMetrics[] = $curve[0]; } } foreach ([ ['template', $concreteTemplates, []], ['default_template', $allTemplates->getDefaultTemplates(), $excludedMetrics], ] as $templateSet) { list($urlParam, $templates, $excludeMetrics) = $templateSet; foreach ($templates as $templateName => $template) { if ($this->designedForMyMonitoredObjectType($template)) { $charts = $template->getCharts( static::getMetricsDataSource(), $filter, $this->checkCommand, $excludeMetrics ); if (! empty($charts)) { $currentGraphs = []; foreach ($charts as $chart) { $metricVariables = $chart->getMetricVariables(); $imageUrl = $this->filterImageUrl($imageBaseUrl->with($metricVariables)) ->setParam($urlParam, $templateName) ->setParam('start', $this->start) ->setParam('end', $this->end) ->setParam('width', $this->width) ->setParam('height', $this->height) ->setParam('cachebuster', time() * 65536 + mt_rand(0, 65535)); if (! $this->compact) { $imageUrl->setParam('legend', 1); } $bestIntersect = -1; $bestPos = count($result); foreach ($result as $graphPos => & $graph) { $currentIntersect = count(array_intersect_assoc($graph[1], $metricVariables)); if ($currentIntersect >= $bestIntersect) { $bestIntersect = $currentIntersect; $bestPos = $graphPos + 1; } } unset($graph); $currentGraphs[] = [ '\"\""width\" height=\"$this->height\">", $metricVariables, $bestPos ]; } foreach (array_reverse($currentGraphs) as $graph) { list($img, $metricVariables, $bestPos) = $graph; array_splice($result, $bestPos, 0, [[$img, $metricVariables]]); } } } } } if (! empty($result)) { foreach ($result as & $graph) { $graph = $graph[0]; } unset($graph); if ($this->maxVisibleGraphs && count($result) > $this->maxVisibleGraphs) { /** @var View $view */ $view = $this->view(); array_splice($result, $this->maxVisibleGraphs, 0, [sprintf( '' . '' . '
', $view->protectId($this->getMonitoredObjectIdentifier()), $view->translate('Show More'), $view->translate('Show Less') )]); $result[] = '
'; } $classes = $this->classes; $classes[] = 'images'; array_unshift($result, '
'); $result[] = '
'; } $this->graphsList = implode($result); } return $this->graphsList; } public function render() { $result = $this->getGraphsList(); if ($result === '' && $this->getShowNoGraphsFound()) { $view = $this->view(); return "

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

"; } return $result; } /** * 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", null]; } $absolute = TimeRangePickerTrait::getAbsoluteRangeParameters(); $start = $params->get($absolute['start']); return [ $start === null ? -TimeRangePickerTrait::getDefaultRelativeTimeRange() : $start, $params->get($absolute['end']) ]; } /** * Return a identifier specifying the monitored object we display graphs for * * @return string */ abstract protected function getMonitoredObjectIdentifier(); /** * Return a filter specifying the monitored object we display graphs for * * @return string[] */ abstract protected function getMonitoredObjectFilter(); /** * Get the base URL to a graph specifying just the monitored object kind * * @return Url */ abstract protected function getImageBaseUrl(); /** * Get the base URL to a dummy image specifying just the monitored object kind * * @return Url */ abstract protected function getDummyImageBaseUrl(); /** * Extend the {@link getImageBaseUrl()}'s result's parameters with the concrete monitored object * * @param Url $url The URL to extend * * @return Url The given URL */ abstract protected function filterImageUrl(Url $url); /** * Return whether the given template is designed for the type of the monitored object we display graphs for * * @param Template $template * * @return bool */ abstract protected function designedForMyMonitoredObjectType(Template $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; } /** * Get the graph image width * * @return string */ public function getWidth() { return $this->width; } /** * Set the graph image width * * @param string $width * * @return $this */ public function setWidth($width) { $this->width = $width; return $this; } /** * Get the graph image height * * @return string */ public function getHeight() { return $this->height; } /** * Set the graph image height * * @param string $height * * @return $this */ public function setHeight($height) { $this->height = $height; return $this; } /** * Get additional CSS classes for the
s around the images * * @return string[] */ public function getClasses() { return $this->classes; } /** * Set additional CSS classes for the
s around the images * * @param string[] $classes * * @return $this */ public function setClasses($classes) { $this->classes = $classes; return $this; } /** * Get the amount of graphs to show * * @return int */ public function getMaxVisbileGraphs() { return $this->maxVisibleGraphs; } /** * Set the amount of graphs to show * * @param int $count * * @return $this */ public function setMaxVisibleGraphs($count) { $this->maxVisibleGraphs = (int) $count; return $this; } /** * Get whether to serve a transparent dummy image first and let the JS code load the actual graph * * @return bool */ public function getPreloadDummy() { return $this->preloadDummy; } /** * Set whether to serve a transparent dummy image first and let the JS code load the actual graph * * @param bool $preloadDummy * * @return $this */ public function setPreloadDummy($preloadDummy = true) { $this->preloadDummy = $preloadDummy; return $this; } /** * Get whether to explicitly display that no graphs were found * * @return bool */ public function getShowNoGraphsFound() { if ($this->showNoGraphsFound === null) { $this->showNoGraphsFound = ! Config::module('graphite')->get('ui', 'disable_no_graphs_found'); } return $this->showNoGraphsFound; } /** * Set whether to explicitly display that no graphs were found * * @param bool $showNoGraphsFound * * @return $this */ public function setShowNoGraphsFound($showNoGraphsFound = true) { $this->showNoGraphsFound = $showNoGraphsFound; return $this; } }