Merge pull request #3098 from Icinga/feature/redesign-tactical-overview
Redesign tactical overview
This commit is contained in:
commit
f908ea42ce
|
@ -0,0 +1,402 @@
|
||||||
|
<?php
|
||||||
|
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
namespace Icinga\Chart;
|
||||||
|
|
||||||
|
use Icinga\Web\Url;
|
||||||
|
|
||||||
|
/** Donut chart implementation */
|
||||||
|
class Donut
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Big label in the middle of the donut, color is critical (red)
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $labelBig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Url behind the big label
|
||||||
|
*
|
||||||
|
* @var Url
|
||||||
|
*/
|
||||||
|
protected $labelBigUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small label in the lower part of the donuts hole
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $labelSmall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thickness of the donut ring
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $thickness = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Radius based of 100 to simplify the calculations
|
||||||
|
*
|
||||||
|
* 100 / (2 * M_PI)
|
||||||
|
*
|
||||||
|
* @var float
|
||||||
|
*/
|
||||||
|
protected $radius = 15.9154943092;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color of the hole in the donut
|
||||||
|
*
|
||||||
|
* Transparent by default so it can be placed anywhere with ease
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $centerColor = 'transparent';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The different colored parts that represent the data
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $slices = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total amount of data units
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $count = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a colored part that represent the data
|
||||||
|
*
|
||||||
|
* @param integer $data Units of data
|
||||||
|
* @param array $attributes HTML attributes for this slice. (For example ['class' => 'slice-state-ok'])
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function addSlice($data, $attributes = array())
|
||||||
|
{
|
||||||
|
$this->slices[] = array($data, $attributes);
|
||||||
|
|
||||||
|
$this->count += $data;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the thickness for this Donut
|
||||||
|
*
|
||||||
|
* @param integer $thickness
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setThickness($thickness)
|
||||||
|
{
|
||||||
|
$this->thickness = $thickness;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Get the thickness for this Donut
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getThickness()
|
||||||
|
{
|
||||||
|
return $this->thickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the center color for this Donut
|
||||||
|
*
|
||||||
|
* @param string $centerColor
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCenterColor($centerColor)
|
||||||
|
{
|
||||||
|
$this->centerColor = $centerColor;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the center color for this Donut
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCenterColor()
|
||||||
|
{
|
||||||
|
return $this->centerColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text of the big label
|
||||||
|
*
|
||||||
|
* @param string $labelBig
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLabelBig($labelBig)
|
||||||
|
{
|
||||||
|
$this->labelBig = $labelBig;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text of the big label
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLabelBig()
|
||||||
|
{
|
||||||
|
return $this->labelBig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the url behind the big label
|
||||||
|
*
|
||||||
|
* @param Url $labelBigUrl
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLabelBigUrl($labelBigUrl)
|
||||||
|
{
|
||||||
|
$this->labelBigUrl = $labelBigUrl;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the url behind the big label
|
||||||
|
*
|
||||||
|
* @return Url
|
||||||
|
*/
|
||||||
|
public function getLabelBigUrl()
|
||||||
|
{
|
||||||
|
return $this->labelBigUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text of the small label
|
||||||
|
*
|
||||||
|
* @param string $labelSmall
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setLabelSmall($labelSmall)
|
||||||
|
{
|
||||||
|
$this->labelSmall = $labelSmall;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text of the small label
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLabelSmall()
|
||||||
|
{
|
||||||
|
return $this->labelSmall;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put together all slices of this Donut
|
||||||
|
*
|
||||||
|
* @return array $svg
|
||||||
|
*/
|
||||||
|
protected function assemble()
|
||||||
|
{
|
||||||
|
// svg tag containing the ring
|
||||||
|
$svg = array(
|
||||||
|
'tag' => 'svg',
|
||||||
|
'attributes' => array(
|
||||||
|
'xmlns' => 'http://www.w3.org/2000/svg',
|
||||||
|
'viewbox' => '0 0 40 40',
|
||||||
|
'class' => 'donut-graph'
|
||||||
|
),
|
||||||
|
'content' => array()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Donut hole
|
||||||
|
$svg['content'][] = array(
|
||||||
|
'tag' => 'circle',
|
||||||
|
'attributes' => array(
|
||||||
|
'cx' => 20,
|
||||||
|
'cy' => 20,
|
||||||
|
'r' => $this->radius,
|
||||||
|
'fill' => $this->getCenterColor()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// When there is no data show gray circle
|
||||||
|
$svg['content'][] = array(
|
||||||
|
'tag' => 'circle',
|
||||||
|
'attributes' => array(
|
||||||
|
'cx' => 20,
|
||||||
|
'cy' => 20,
|
||||||
|
'r' => $this->radius,
|
||||||
|
'fill' => $this->getCenterColor(),
|
||||||
|
'stroke-width' => $this->getThickness(),
|
||||||
|
'class' => 'slice-state-not-checked'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$slices = $this->slices;
|
||||||
|
|
||||||
|
if ($this->count !== 0) {
|
||||||
|
array_walk($slices, function (&$slice) {
|
||||||
|
$slice[0] = round(100 / $this->count * $slice[0], 2);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// on 0 the donut would start at "3 o'clock" and the offset shifts counterclockwise
|
||||||
|
$offset = 25;
|
||||||
|
|
||||||
|
foreach ($slices as $slice) {
|
||||||
|
$svg['content'][] = array(
|
||||||
|
'tag' => 'circle',
|
||||||
|
'attributes' => $slice[1] + array(
|
||||||
|
'cx' => 20,
|
||||||
|
'cy' => 20,
|
||||||
|
'r' => $this->radius,
|
||||||
|
'fill' => 'transparent',
|
||||||
|
'stroke-width' => $this->getThickness(),
|
||||||
|
'stroke-dasharray' => $slice[0] . ' ' . (99.9 - $slice[0]), // 99.9 prevents gaps (slight overlap)
|
||||||
|
'stroke-dashoffset' => $offset
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// negative values shift in the clockwise direction
|
||||||
|
$offset -= $slice[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getLabelBig() || $this->getLabelSmall()) {
|
||||||
|
$labels = array(
|
||||||
|
'tag' => 'div',
|
||||||
|
'attributes' => array(
|
||||||
|
'class' => 'donut-label'
|
||||||
|
),
|
||||||
|
'content' => array()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->getLabelBig()) {
|
||||||
|
$labels['content'][] =
|
||||||
|
array(
|
||||||
|
'tag' => 'a',
|
||||||
|
'attributes' => array(
|
||||||
|
'href' => $this->getLabelBigUrl() ? $this->getLabelBigUrl()->getAbsoluteUrl() : null,
|
||||||
|
'class' => 'donut-label-big'
|
||||||
|
),
|
||||||
|
'content' => $this->shortenLabel($this->getLabelBig())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->getLabelSmall()) {
|
||||||
|
$labels['content'][] = array(
|
||||||
|
'tag' => 'p',
|
||||||
|
'attributes' => array(
|
||||||
|
'class' => 'donut-label-small',
|
||||||
|
'x' => '50%',
|
||||||
|
'y' => '50%'
|
||||||
|
),
|
||||||
|
'content' => $this->getLabelSmall()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$svg['content'][] = $labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $svg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shorten the label to 3 digits if it is numeric
|
||||||
|
*
|
||||||
|
* 10 => 10 ... 1111 => ~1k ... 1888 => ~2k
|
||||||
|
*
|
||||||
|
* @param int|string $label
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function shortenLabel($label)
|
||||||
|
{
|
||||||
|
if (is_numeric($label) && strlen($label) > 3) {
|
||||||
|
return '~' . substr(round($label, -3), 0, 1) . 'k';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $label;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function encode($content)
|
||||||
|
{
|
||||||
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
|
||||||
|
$replaceFlags = ENT_COMPAT | ENT_SUBSTITUTE | ENT_HTML5;
|
||||||
|
} else {
|
||||||
|
$replaceFlags = ENT_COMPAT | ENT_IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return htmlspecialchars($content, $replaceFlags, 'UTF-8', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderAttributes(array $attributes)
|
||||||
|
{
|
||||||
|
$html = [];
|
||||||
|
|
||||||
|
foreach ($attributes as $name => $value) {
|
||||||
|
if ($value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bool($value) && $value) {
|
||||||
|
$html[] = $name;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_array($value)) {
|
||||||
|
$value = implode(' ', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html[] = "$name=\"" . $this->encode($value) . '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' ', $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderContent(array $element)
|
||||||
|
{
|
||||||
|
$tag = $element['tag'];
|
||||||
|
$attributes = isset($element['attributes']) ? $element['attributes'] : array();
|
||||||
|
$content = isset($element['content']) ? $element['content'] : null;
|
||||||
|
|
||||||
|
$html = array(
|
||||||
|
// rtrim because attributes may be empty
|
||||||
|
rtrim("<$tag " . $this->renderAttributes($attributes))
|
||||||
|
. ">"
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($content !== null) {
|
||||||
|
if (is_array($content)) {
|
||||||
|
foreach ($content as $child) {
|
||||||
|
$html[] = is_array($child) ? $this->renderContent($child) : $this->encode($child);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$html[] = $this->encode($content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$html[] = "</$tag>";
|
||||||
|
|
||||||
|
return implode("\n", $html);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$svg = $this->assemble();
|
||||||
|
|
||||||
|
return $this->renderContent($svg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
namespace Icinga\Module\Monitoring\Controllers;
|
namespace Icinga\Module\Monitoring\Controllers;
|
||||||
|
|
||||||
|
use Icinga\Chart\Donut;
|
||||||
use Icinga\Module\Monitoring\Controller;
|
use Icinga\Module\Monitoring\Controller;
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
||||||
|
@ -13,6 +14,7 @@ class TacticalController extends Controller
|
||||||
public function indexAction()
|
public function indexAction()
|
||||||
{
|
{
|
||||||
$this->setAutorefreshInterval(15);
|
$this->setAutorefreshInterval(15);
|
||||||
|
|
||||||
$this->getTabs()->add(
|
$this->getTabs()->add(
|
||||||
'tactical_overview',
|
'tactical_overview',
|
||||||
array(
|
array(
|
||||||
|
@ -24,66 +26,93 @@ class TacticalController extends Controller
|
||||||
'url' => Url::fromRequest()
|
'url' => Url::fromRequest()
|
||||||
)
|
)
|
||||||
)->extend(new DashboardAction())->extend(new MenuAction())->activate('tactical_overview');
|
)->extend(new DashboardAction())->extend(new MenuAction())->activate('tactical_overview');
|
||||||
|
|
||||||
$stats = $this->backend->select()->from(
|
$stats = $this->backend->select()->from(
|
||||||
'statussummary',
|
'statussummary',
|
||||||
array(
|
array(
|
||||||
'hosts_up',
|
'hosts_up',
|
||||||
'hosts_pending',
|
'hosts_down_handled',
|
||||||
'hosts_down',
|
|
||||||
'hosts_down_unhandled',
|
'hosts_down_unhandled',
|
||||||
'hosts_unreachable',
|
'hosts_unreachable_handled',
|
||||||
'hosts_unreachable_unhandled',
|
'hosts_unreachable_unhandled',
|
||||||
|
'hosts_pending',
|
||||||
'services_ok_on_ok_hosts',
|
|
||||||
'services_ok_not_checked_on_ok_hosts',
|
|
||||||
'services_pending_on_ok_hosts',
|
|
||||||
'services_pending_not_checked_on_ok_hosts',
|
|
||||||
'services_warning_handled_on_ok_hosts',
|
|
||||||
'services_warning_unhandled_on_ok_hosts',
|
|
||||||
'services_warning_passive_on_ok_hosts',
|
|
||||||
'services_warning_not_checked_on_ok_hosts',
|
|
||||||
'services_critical_handled_on_ok_hosts',
|
|
||||||
'services_critical_unhandled_on_ok_hosts',
|
|
||||||
'services_critical_passive_on_ok_hosts',
|
|
||||||
'services_critical_not_checked_on_ok_hosts',
|
|
||||||
'services_unknown_handled_on_ok_hosts',
|
|
||||||
'services_unknown_unhandled_on_ok_hosts',
|
|
||||||
'services_unknown_passive_on_ok_hosts',
|
|
||||||
'services_unknown_not_checked_on_ok_hosts',
|
|
||||||
'services_ok_on_problem_hosts',
|
|
||||||
'services_ok_not_checked_on_problem_hosts',
|
|
||||||
'services_pending_on_problem_hosts',
|
|
||||||
'services_pending_not_checked_on_problem_hosts',
|
|
||||||
'services_warning_handled_on_problem_hosts',
|
|
||||||
'services_warning_unhandled_on_problem_hosts',
|
|
||||||
'services_warning_passive_on_problem_hosts',
|
|
||||||
'services_warning_not_checked_on_problem_hosts',
|
|
||||||
'services_critical_handled_on_problem_hosts',
|
|
||||||
'services_critical_unhandled_on_problem_hosts',
|
|
||||||
'services_critical_passive_on_problem_hosts',
|
|
||||||
'services_critical_not_checked_on_problem_hosts',
|
|
||||||
'services_unknown_handled_on_problem_hosts',
|
|
||||||
'services_unknown_unhandled_on_problem_hosts',
|
|
||||||
'services_unknown_passive_on_problem_hosts',
|
|
||||||
'services_unknown_not_checked_on_problem_hosts',
|
|
||||||
|
|
||||||
'hosts_active',
|
|
||||||
'hosts_passive',
|
|
||||||
'hosts_not_checked',
|
'hosts_not_checked',
|
||||||
'services_active',
|
|
||||||
'services_passive',
|
'services_ok',
|
||||||
|
'services_warning_handled',
|
||||||
|
'services_warning_unhandled',
|
||||||
|
'services_critical_handled',
|
||||||
|
'services_critical_unhandled',
|
||||||
|
'services_unknown_handled',
|
||||||
|
'services_unknown_unhandled',
|
||||||
|
'services_pending',
|
||||||
'services_not_checked',
|
'services_not_checked',
|
||||||
'hosts_not_processing_event_handlers',
|
|
||||||
'services_not_processing_event_handlers',
|
|
||||||
'hosts_not_triggering_notifications',
|
|
||||||
'services_not_triggering_notifications',
|
|
||||||
'hosts_without_flap_detection',
|
|
||||||
'services_without_flap_detection',
|
|
||||||
'hosts_flapping',
|
|
||||||
'services_flapping'
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->applyRestriction('monitoring/filter/objects', $stats);
|
$this->applyRestriction('monitoring/filter/objects', $stats);
|
||||||
$this->view->statusSummary = $stats->fetchRow();
|
|
||||||
|
$summary = $stats->fetchRow();
|
||||||
|
|
||||||
|
$hostSummaryChart = new Donut();
|
||||||
|
$hostSummaryChart
|
||||||
|
->addSlice($summary->hosts_up, array('class' => 'slice-state-ok'))
|
||||||
|
->addSlice($summary->hosts_down_handled, array('class' => 'slice-state-critical-handled'))
|
||||||
|
->addSlice($summary->hosts_down_unhandled, array('class' => 'slice-state-critical'))
|
||||||
|
->addSlice($summary->hosts_unreachable_handled, array('class' => 'slice-state-unreachable-handled'))
|
||||||
|
->addSlice($summary->hosts_unreachable_unhandled, array('class' => 'slice-state-unreachable'))
|
||||||
|
->addSlice($summary->hosts_pending, array('class' => 'slice-state-pending'))
|
||||||
|
->addSlice($summary->hosts_not_checked, array('class' => 'slice-state-not-checked'));
|
||||||
|
if ($summary->hosts_down_unhandled > 1) {
|
||||||
|
$hostSummaryChart
|
||||||
|
->setLabelBig($summary->hosts_down_unhandled)
|
||||||
|
->setLabelSmall($this->translate('hosts down'));
|
||||||
|
} elseif ($summary->hosts_down_unhandled === 1) {
|
||||||
|
$hostSummaryChart
|
||||||
|
->setLabelBig($summary->hosts_down_unhandled)
|
||||||
|
->setLabelSmall($this->translate('host down'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$serviceSummaryChart = new Donut();
|
||||||
|
$serviceSummaryChart
|
||||||
|
->addSlice($summary->services_ok, array('class' => 'slice-state-ok'))
|
||||||
|
->addSlice($summary->services_warning_handled, array('class' => 'slice-state-warning-handled'))
|
||||||
|
->addSlice($summary->services_warning_unhandled, array('class' => 'slice-state-warning'))
|
||||||
|
->addSlice($summary->services_critical_handled, array('class' => 'slice-state-critical-handled'))
|
||||||
|
->addSlice($summary->services_critical_unhandled, array('class' => 'slice-state-critical'))
|
||||||
|
->addSlice($summary->services_unknown_handled, array('class' => 'slice-state-unknown-handled'))
|
||||||
|
->addSlice($summary->services_unknown_unhandled, array('class' => 'slice-state-unknown'))
|
||||||
|
->addSlice($summary->services_pending, array('class' => 'slice-state-pending'))
|
||||||
|
->addSlice($summary->services_not_checked, array('class' => 'slice-state-not-checked'));
|
||||||
|
if ($summary->services_critical_unhandled > 1) {
|
||||||
|
$serviceSummaryChart
|
||||||
|
->setLabelBig($summary->services_critical_unhandled)
|
||||||
|
->setLabelSmall($this->translate('services critical'));
|
||||||
|
} elseif ($summary->services_critical_unhandled === 1) {
|
||||||
|
$hostSummaryChart
|
||||||
|
->setLabelBig($summary->hosts_down_unhandled)
|
||||||
|
->setLabelSmall($this->translate('service critical'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->hostStatusSummaryChart = $hostSummaryChart
|
||||||
|
->setLabelBigUrl($this->view->url(
|
||||||
|
'monitoring/list/hosts',
|
||||||
|
array(
|
||||||
|
'host_state' => 1, 'host_handled' => 0,
|
||||||
|
'sort' => 'host_last_check', 'dir' => 'asc'
|
||||||
|
)
|
||||||
|
))
|
||||||
|
->render();
|
||||||
|
$this->view->serviceStatusSummaryChart = $serviceSummaryChart
|
||||||
|
->setLabelBigUrl($this->view->url(
|
||||||
|
'monitoring/list/services',
|
||||||
|
array(
|
||||||
|
'service_state' => 2,
|
||||||
|
'service_handled' => 0,
|
||||||
|
'sort' => 'service_last_check',
|
||||||
|
'dir' => 'asc'
|
||||||
|
)
|
||||||
|
))
|
||||||
|
->render();
|
||||||
|
$this->view->statusSummary = $summary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,121 @@
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<div class="content tactical grid">
|
<div class="content tactical grid">
|
||||||
<div class="boxview" data-base-target="_next">
|
<div class="boxview" data-base-target="_next">
|
||||||
<?php if ($this->statusSummary->hosts_down || $this->statusSummary->hosts_unreachable): ?>
|
<div class="donut-container">
|
||||||
<?= $this->render('tactical/components/problem_hosts.phtml'); ?>
|
<h2><?= $this->translate('Host Summary') ?></h2>
|
||||||
<?php endif ?>
|
<div class="donut">
|
||||||
<?php if ($this->statusSummary->hosts_up || $this->statusSummary->hosts_pending): ?>
|
<?= $hostStatusSummaryChart ?>
|
||||||
<?= $this->render('tactical/components/ok_hosts.phtml'); ?>
|
</div>
|
||||||
<?php endif ?>
|
<table class="donut-table">
|
||||||
|
<tbody>
|
||||||
|
<?php if ($statusSummary->hosts_up): ?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 0, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-ok badge"><?= $statusSummary->hosts_up ?></th>
|
||||||
|
<td><?= $this->translate('Up') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_down_handled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 1, 'host_handled' => 1, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-critical-handled badge"><?= $statusSummary->hosts_down_handled ?></th>
|
||||||
|
<td><?= $this->translate('Down handled') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_down_unhandled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 1, 'host_handled' => 0, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-critical badge"><?= $statusSummary->hosts_down_unhandled ?></th>
|
||||||
|
<td><?= $this->translate('Down') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_unreachable_handled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 2, 'host_handled' => 1, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-unreachable-handled badge"><?= $statusSummary->hosts_unreachable_handled ?></th>
|
||||||
|
<td><?= $this->translate('Unreachable handled') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_unreachable_unhandled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 2, 'host_handled' => 0, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-unreachable badge"><?= $statusSummary->hosts_unreachable_unhandled ?></th>
|
||||||
|
<td><?= $this->translate('Unreachable') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_pending):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_state' => 99, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-pending badge"><?= $statusSummary->hosts_pending ?></th>
|
||||||
|
<td><?= $this->translate('Pending') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->hosts_not_checked):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/hosts', array('host_active_checks_enabled' => 0, 'host_passive_checks_enabled' => 0, 'sort' => 'host_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-not-checked badge"><?= $statusSummary->hosts_not_checked ?></th>
|
||||||
|
<td><?= $this->translate('Not Checked') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="donut-container">
|
||||||
|
<h2><?= $this->translate('Service Summary') ?></h2>
|
||||||
|
<div class="donut">
|
||||||
|
<?= $serviceStatusSummaryChart ?>
|
||||||
|
</div>
|
||||||
|
<table class="donut-table">
|
||||||
|
<tbody>
|
||||||
|
<?php if ($statusSummary->services_ok):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-ok badge"><?= $statusSummary->services_ok ?></th>
|
||||||
|
<td><?= $this->translate('Ok') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_warning_handled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 1, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-warning-handled badge"><?= $statusSummary->services_warning_handled ?></th>
|
||||||
|
<td><?= $this->translate('Warning handled') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_warning_unhandled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 1, 'service_handled' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-warning badge"><?= $statusSummary->services_warning_unhandled ?></th>
|
||||||
|
<td><?= $this->translate('Warning') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_critical_handled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 2, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-critical-handled badge"><?= $statusSummary->services_critical_handled ?></th>
|
||||||
|
<td><?= $this->translate('Critical handled') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_critical_unhandled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 2, 'service_handled' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state state-critical badge"><?= $statusSummary->services_critical_unhandled ?></th>
|
||||||
|
<td><?= $this->translate('Critical') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_unknown_handled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 3, 'service_handled' => 1, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-unknown-handled badge"><?= $statusSummary->services_unknown_handled ?></th>
|
||||||
|
<td><?= $this->translate('Unknown handled') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_unknown_unhandled):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 3, 'service_handled' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-unknown badge"><?= $statusSummary->services_unknown_unhandled ?></th>
|
||||||
|
<td><?= $this->translate('Unknown') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_pending):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_state' => 99, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-pending badge"><?= $statusSummary->services_pending ?></th>
|
||||||
|
<td><?= $this->translate('Pending') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif;
|
||||||
|
if ($statusSummary->services_not_checked):?>
|
||||||
|
<tr href="<?= $this->url('monitoring/list/services', array('service_active_checks_enabled' => 0, 'service_passive_checks_enabled' => 0, 'sort' => 'service_last_check', 'dir' => 'asc')) ?>">
|
||||||
|
<th class="state slice-state-not-checked badge"><?= $statusSummary->services_not_checked ?></th>
|
||||||
|
<td><?= $this->translate('Not Checked') ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -341,3 +341,121 @@ ul.tree li a.error:hover {
|
||||||
right: 6px;
|
right: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slice-state-ok {
|
||||||
|
stroke: @color-ok;
|
||||||
|
background: @color-ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-warning-handled {
|
||||||
|
stroke: @color-warning-handled;
|
||||||
|
background: @color-warning-handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-warning {
|
||||||
|
stroke: @color-warning;
|
||||||
|
background: @color-unreachable-handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-critical-handled {
|
||||||
|
stroke: @color-critical-handled;
|
||||||
|
background: @color-critical-handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-critical {
|
||||||
|
stroke: @color-critical;
|
||||||
|
background: @color-critical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-unknown-handled {
|
||||||
|
stroke: @color-unknown-handled;
|
||||||
|
background: @color-unknown-handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-unknown {
|
||||||
|
stroke: @color-unknown;
|
||||||
|
background: @color-unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-unreachable-handled {
|
||||||
|
stroke: @color-unreachable-handled;
|
||||||
|
background: @color-unreachable-handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-unreachable {
|
||||||
|
stroke: @color-unreachable;
|
||||||
|
background: @color-unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-pending {
|
||||||
|
stroke: @color-pending;
|
||||||
|
background: @color-pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slice-state-not-checked {
|
||||||
|
stroke: @gray-light;
|
||||||
|
background: @gray-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut {
|
||||||
|
width: 22em;
|
||||||
|
height: 22em;
|
||||||
|
min-width: 11.5em;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-graph {
|
||||||
|
width: 22em;
|
||||||
|
height: 22em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-label {
|
||||||
|
font-weight: bold;
|
||||||
|
fill: @text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-label {
|
||||||
|
margin-top: -12.5em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-label-big {
|
||||||
|
color: @color-critical;
|
||||||
|
font-size: 6em;
|
||||||
|
line-height: 0;
|
||||||
|
text-anchor: middle;
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-label-small {
|
||||||
|
fill: @text-color;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-transform: lowercase;
|
||||||
|
text-anchor: middle;
|
||||||
|
-moz-transform: translateY(0.35em);
|
||||||
|
-ms-transform: translateY(0.35em);
|
||||||
|
-webkit-transform: translateY(0.35em);
|
||||||
|
transform: translateY(0.35em);
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-container {
|
||||||
|
display: inline-block;
|
||||||
|
width: 36em;
|
||||||
|
height: 36em;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.donut-table {
|
||||||
|
max-width: 45%;
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: 23em;
|
||||||
|
left: 17.5em;
|
||||||
|
|
||||||
|
& > tbody > tr:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue