Monitoring/register: Add status summary to the top bar

This commit is contained in:
Eric Lippmann 2013-10-20 16:08:01 +02:00
parent 278f975c48
commit 36e9cdb549
14 changed files with 609 additions and 194 deletions

View File

@ -1,26 +1,14 @@
<?php
use Icinga\Web\Topbar;
?>
<nav class="navbar navbar-default navbar-fixed-top" id="icingatopbar" role="navigation">
<div class="navbar-header">
<a href="<?= $this->baseUrl('/') ?>" class="navbar-brand icinga-logo">Icinga</a>
</div>
<div class="nav navbar-nav icinga-navbar-hosts-container">
<span class="icinga-navbar-pills icinga-navbar-pills-up">999/999</span>
<span class="icinga-navbar-pills icinga-navbar-pills-unreachable">999/999</span>
<span class="icinga-navbar-pills icinga-navbar-pills-down">999/999</span>
</div>
<div class="nav navbar-nav icinga-navbar-services-container">
<span class="icinga-navbar-pills icinga-navbar-pills-ok">999/999</span>
<span class="icinga-navbar-pills icinga-navbar-pills-critical">999/999</span>
<span class="icinga-navbar-pills icinga-navbar-pills-warning">999/999</span>
<span class="icinga-navbar-pills icinga-navbar-pills-unknown">999/999</span>
</div>
<div class="nav navbar-nav icinga-navbar-reload">
<a class="button btn-common btn-small" href="#">
<i class="icinga-icon-refresh"></i>
</a>
</div>
<?php foreach (Topbar::getPartials() as $partial) {
echo $this->partial($partial['viewScriptName'], $partial['moduleName'], $partial['data']);
} ?>
<form class="navbar-form navbar-left">
<div class="form-group">

View File

@ -28,6 +28,7 @@
namespace Icinga\Application\Modules;
use \Exception;
use \Icinga\Application\ApplicationBootstrap;
use \Icinga\Application\Config;
use \Icinga\Application\Icinga;
@ -133,8 +134,12 @@ class Module
public function register()
{
$this->registerAutoloader()
->registerWebIntegration()
->runRegisterScript();
->registerWebIntegration();
try {
$this->runRegisterScript();
} catch (Exception $e) {
return false;
}
return true;
}

View File

@ -1,85 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Hook;
use Icinga\Application\Logger as Logger;
/**
* Class Toptray
* @package Icinga\Web\Hook
*/
abstract class Toptray
{
/**
*
*/
const ALIGN_LEFT = "pull-left";
/**
*
*/
const ALIGN_NONE = "";
/**
*
*/
const ALIGN_RIGHT = "pull-right";
/**
* @var string
*/
protected $align = self::ALIGN_NONE;
/**
* @param $align
*/
public function setAlignment($align)
{
$this->align = $align;
}
/**
* @return string
*/
final public function getWidgetDOM()
{
try {
return '<ul class="nav ' . $this->align . '" >' . $this->buildDOM() . '</ul>';
} catch (\Exception $e) {
Logger::error("Could not create tray widget : %s", $e->getMessage());
return '';
}
}
/**
* @return mixed
*/
abstract protected function buildDOM();
}

View File

@ -0,0 +1,22 @@
<?php
namespace Icinga\Web;
class Topbar
{
private static $partials = array();
public static function addPartial($viewScriptName, $moduleName, $data)
{
self::$partials[] = array(
'viewScriptName' => $viewScriptName,
'moduleName' => $moduleName,
'data' => $data
);
}
public static function getPartials()
{
return self::$partials;
}
}

View File

@ -0,0 +1,65 @@
<div class="nav navbar-nav topbar-host-status-summary">
<span class="topbar-status-up">
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => 4)); ?>" title="Hosts Up">
<?= $hostSummary->hosts_up ?>
</a>
</span>
<span class="topbar-status-down">
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => 36)); ?>" title="Hosts Down Unhandled">
<?= $hostSummary->hosts_down_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => array(33, 34))); ?>" title="Hosts Down Handled">
<?= $hostSummary->hosts_down_handled ?>
</a>
</span>
<span class="topbar-status-unreachable">
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => 68)); ?>" title="Hosts Unreachable Unhandled">
<?= $hostSummary->hosts_unreachable_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => array(65, 66))); ?>" title="Hosts Unreachable Handled">
<?= $hostSummary->hosts_unreachable_handled ?>
</a>
</span>
<span class="topbar-status-pending">
<a href="<?= $this->href('monitoring/list/hosts', array('host_severity' => 20)); ?>" title="Hosts Pending">
<?= $hostSummary->hosts_pending ?>
</a>
</span>
</div>
<div class="nav navbar-nav topbar-service-status-summary">
<span class="topbar-status-ok">
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => 4)); ?>" title="Services Ok">
<?= $serviceSummary->services_ok ?>
</a>
</span>
<span class="topbar-status-critical">
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => 132)); ?>" title="Services Critical Unhandled">
<?= $serviceSummary->services_critical_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => array(129, 130))); ?>" title="Services Critical Handled">
<?= $serviceSummary->services_critical_handled ?>
</a>
</span>
<span class="topbar-status-warning">
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => 36)); ?>" title="Services Warning Unhandled">
<?= $serviceSummary->services_warning_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => array(33, 34))); ?>" title="Services Warning Handled">
<?= $serviceSummary->services_warning_handled ?>
</a>
</span>
<span class="topbar-status-unknown">
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => 68)); ?>" title="Services Unknown Unhandled">
<?= $serviceSummary->services_unknown_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => array(65, 66))); ?>" title="Services Unknown Handled">
<?= $serviceSummary->services_unknown_handled ?>
</a>
</span>
<span class="topbar-status-pending">
<a href="<?= $this->href('monitoring/list/services', array('service_severity' => 20)); ?>" title="Services Pending">
<?= $serviceSummary->services_pending ?>
</a>
</span>
</div>

View File

@ -41,6 +41,7 @@ class DowntimeQuery extends IdoQuery
'downtime_entry_time' => 'UNIX_TIMESTAMP(sd.entry_time)',
'downtime_is_fixed' => 'sd.is_fixed',
'downtime_is_flexible' => 'CASE WHEN sd.is_fixed = 0 THEN 1 ELSE 0 END',
'downtime_scheduled_start_time' => 'UNIX_TIMESTAMP(sd.scheduled_start_time)',
'downtime_start' => "UNIX_TIMESTAMP(CASE WHEN sd.trigger_time != '0000-00-00 00:00:00' then sd.trigger_time ELSE sd.scheduled_start_time END)",
'downtime_end' => 'UNIX_TIMESTAMP(sd.scheduled_end_time)',
'downtime_duration' => 'sd.duration',
@ -49,8 +50,11 @@ class DowntimeQuery extends IdoQuery
'downtime_internal_downtime_id' => 'sd.internal_downtime_id',
),
'objects' => array(
'host' => 'o.name1 COLLATE latin1_general_ci',
'service' => 'o.name2 COLLATE latin1_general_ci'
'host' => 'o.name1 COLLATE latin1_general_ci',
'host_name' => 'o.name1 COLLATE latin1_general_ci',
'service' => 'o.name2 COLLATE latin1_general_ci',
'service_description' => 'o.name2 COLLATE latin1_general_ci'
)
);

View File

@ -0,0 +1,347 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
class HoststatusQuery extends IdoQuery
{
protected $allowCustomVars = true;
protected $columnMap = array(
'hosts' => array(
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1 COLLATE latin1_general_ci',
'host_display_name' => 'h.display_name',
'host_alias' => 'h.alias',
'host_address' => 'h.address',
'host_ipv4' => 'INET_ATON(h.address)',
'host_icon_image' => 'h.icon_image',
'hosts_up' => 'SUM(CASE WHEN hs.has_been_checked != 0 AND hs.has_been_checked IS NOT NULL AND hs.current_state = 0 THEN 1 ELSE 0 END)',
'hosts_unreachable_handled' => 'SUM(CASE WHEN hs.has_been_checked != 0 AND hs.has_been_checked IS NOT NULL AND hs.current_state = 2 AND hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth != 0 THEN 1 ELSE 0 END)',
'hosts_unreachable_unhandled' => 'SUM(CASE WHEN hs.has_been_checked != 0 AND hs.has_been_checked IS NOT NULL AND hs.current_state = 2 AND hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth = 0 THEN 1 ELSE 0 END)',
'hosts_down_handled' => 'SUM(CASE WHEN hs.has_been_checked != 0 AND hs.has_been_checked IS NOT NULL AND hs.current_state = 1 AND hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth != 0 THEN 1 ELSE 0 END)',
'hosts_down_unhandled' => 'SUM(CASE WHEN hs.has_been_checked != 0 AND hs.has_been_checked IS NOT NULL AND hs.current_state = 1 AND hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth = 0 THEN 1 ELSE 0 END)',
'hosts_pending' => 'SUM(CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 1 ELSE 0 END)'
),
'hoststatus' => array(
'problems' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END',
'handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
'unhandled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) = 0 THEN 1 ELSE 0 END',
'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
'host_output' => 'hs.output',
'host_long_output' => 'hs.long_output',
'host_perfdata' => 'hs.perfdata',
'host_problem' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END',
'host_acknowledged' => 'hs.problem_has_been_acknowledged',
'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
'host_does_active_checks' => 'hs.active_checks_enabled',
'host_accepts_passive_checks' => 'hs.passive_checks_enabled',
'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)',
'host_last_hard_state' => 'hs.last_hard_state',
'host_check_command' => 'hs.check_command',
'host_last_check' => 'UNIX_TIMESTAMP(hs.last_check)',
'host_next_check' => 'CASE WHEN hs.should_be_scheduled THEN UNIX_TIMESTAMP(hs.next_check) ELSE NULL END',
'host_check_execution_time' => 'hs.execution_time',
'host_check_latency' => 'hs.latency',
'host_notifications_enabled' => 'hs.notifications_enabled',
'host_last_time_up' => 'hs.last_time_up',
'host_last_time_down' => 'hs.last_time_down',
'host_last_time_unreachable' => 'hs.last_time_unreachable',
'host_current_check_attempt' => 'hs.current_check_attempt',
'host_max_check_attempts' => 'hs.max_check_attempts',
'host_severity' => 'CASE WHEN hs.current_state = 0
THEN
CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
THEN 16
ELSE 0
END
+
CASE WHEN hs.problem_has_been_acknowledged = 1
THEN 2
ELSE
CASE WHEN hs.scheduled_downtime_depth > 0
THEN 1
ELSE 4
END
END
ELSE
CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 16
WHEN hs.current_state = 1 THEN 32
WHEN hs.current_state = 2 THEN 64
ELSE 256
END
+
CASE WHEN hs.problem_has_been_acknowledged = 1
THEN 2
ELSE
CASE WHEN hs.scheduled_downtime_depth > 0
THEN 1
ELSE 4
END
END
END',
),
'hostgroups' => array(
'hostgroup' => 'hgo.name1 COLLATE latin1_general_ci',
),
'contactgroups' => array(
'contactgroup' => 'contactgroup',
),
'contacts' => array(
'contact' => 'hco.name1 COLLATE latin1_general_ci',
),
'services' => array(
'services_cnt' => 'SUM(1)',
'services_ok' => 'SUM(CASE WHEN ss.current_state = 0 THEN 1 ELSE 0 END)',
'services_warning' => 'SUM(CASE WHEN ss.current_state = 1 THEN 1 ELSE 0 END)',
'services_critical' => 'SUM(CASE WHEN ss.current_state = 2 THEN 1 ELSE 0 END)',
'services_unknown' => 'SUM(CASE WHEN ss.current_state = 3 THEN 1 ELSE 0 END)',
'services_pending' => 'SUM(CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 1 ELSE 0 END)',
'services_problem' => 'SUM(CASE WHEN ss.current_state > 0 THEN 1 ELSE 0 END)',
'services_problem_handled' => 'SUM(CASE WHEN ss.current_state > 0 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)',
'services_problem_unhandled' => 'SUM(CASE WHEN ss.current_state > 0 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)',
'services_warning_handled' => 'SUM(CASE WHEN ss.current_state = 1 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)',
'services_critical_handled' => 'SUM(CASE WHEN ss.current_state = 2 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)',
'services_unknown_handled' => 'SUM(CASE WHEN ss.current_state = 3 AND (ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0) THEN 1 ELSE 0 END)',
'services_warning_unhandled' => 'SUM(CASE WHEN ss.current_state = 1 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)',
'services_critical_unhandled' => 'SUM(CASE WHEN ss.current_state = 2 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)',
'services_unknown_unhandled' => 'SUM(CASE WHEN ss.current_state = 3 AND (ss.problem_has_been_acknowledged = 0 AND ss.scheduled_downtime_depth = 0) THEN 1 ELSE 0 END)',
),
);
protected $aggregateColumnIdx = array(
'services_cnt' => true,
'services_problem' => true,
'services_problem_handled' => true,
'services_problem_unhandled' => true,
);
protected $hcgSub;
public function getDefaultColumns()
{
return $this->columnMap['hosts'] + $this->columnMap['hoststatus'];
}
protected function joinBaseTables()
{
// TODO: Shall we always add hostobject?
$this->baseQuery = $this->db->select()->from(
array('ho' => $this->prefix . 'objects'),
array()
)->join(
array('hs' => $this->prefix . 'hoststatus'),
'ho.' . $this->object_id . ' = hs.host_object_id AND ho.is_active = 1 AND ho.objecttype_id = 1',
array()
)->join(
array('h' => $this->prefix . 'hosts'),
'hs.host_object_id = h.host_object_id',
array()
);
$this->joinedVirtualTables = array(
'hosts' => true,
'hoststatus' => true,
);
}
protected function joinStatus()
{
$this->requireVirtualTable('services');
}
protected function joinServiceStatus()
{
$this->requireVirtualTable('services');
}
protected function joinServices()
{
$this->baseQuery->join(
array('s' => $this->prefix . 'services'),
's.host_object_id = h.host_object_id',
array()
)->join(
array('so' => $this->prefix . 'objects'),
"so.$this->object_id = s.service_object_id AND so.is_active = 1",
array()
)->joinLeft(
array('ss' => $this->prefix . 'servicestatus'),
"so.$this->object_id = ss.service_object_id",
array()
);
foreach ($this->getColumns() as $col) {
$real = $this->aliasToColumnName($col);
if (substr($real, 0, 4) === 'SUM(') {
continue;
}
$this->baseQuery->group($real);
}
$this->useSubqueryCount = true;
}
protected function joinHostgroups()
{
if ($this->hasJoinedVirtualTable('services')) {
return $this->joinServiceHostgroups();
} else {
return $this->joinHostHostgroups();
}
}
protected function joinServiceHostgroups()
{
$this->baseQuery->join(
array('hgm' => $this->prefix . 'hostgroup_members'),
'hgm.host_object_id = s.host_object_id',
array()
)->join(
array('hg' => $this->prefix . 'hostgroups'),
'hgm.hostgroup_id = hg.' . $this->hostgroup_id,
array()
)->join(
array('hgo' => $this->prefix . 'objects'),
'hgo.' . $this->object_id . ' = hg.hostgroup_object_id'
. ' AND hgo.is_active = 1',
array()
);
return $this;
}
protected function joinHostHostgroups()
{
$this->baseQuery->join(
array('hgm' => $this->prefix . 'hostgroup_members'),
'hgm.host_object_id = h.host_object_id',
array()
)->join(
array('hg' => $this->prefix . 'hostgroups'),
"hgm.hostgroup_id = hg.$this->hostgroup_id",
array()
)->join(
array('hgo' => $this->prefix . 'objects'),
'hgo.' . $this->object_id . ' = hg.hostgroup_object_id'
. ' AND hgo.is_active = 1',
array()
);
return $this;
}
protected function joinContacts()
{
$this->hcgcSub = $this->db->select()->distinct()->from(
array('hcgc' => $this->prefix . 'host_contactgroups'),
array('host_name' => 'ho.name1')
)->join(
array('cgo' => $this->prefix . 'objects'),
'hcg.contactgroup_object_id = cgo.' . $this->object_id
. ' AND cgo.is_active = 1',
array()
)->join(
array('h' => $this->prefix . 'hosts'),
'hcg.host_id = h.host_id',
array()
)->join(
array('ho' => $this->prefix . 'objects'),
'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1',
array()
);
$this->baseQuery->join(
array('hcg' => $this->hcgSub),
'hcg.host_name = ho.name1',
array()
);
return $this;
}
protected function filterContactgroup($value)
{
$this->hcgSub->where(
$this->prepareFilterStringForColumn(
'cgo.name1 COLLATE latin1_general_ci',
$value
)
);
return $this;
}
protected function joinContactgroups()
{
$this->hcgSub = $this->createContactgroupFilterSubselect();
$this->baseQuery->join(
array('hcg' => $this->hcgSub),
'hcg.object_id = ho.object_id',
array()
);
return $this;
}
protected function createContactgroupFilterSubselect()
{
die((string)$this->db->select()->distinct()->from(
array('hcg' => $this->prefix . 'host_contactgroups'),
array('object_id' => 'ho.object_id')
)->join(
array('cgo' => $this->prefix . 'objects'),
'hcg.contactgroup_object_id = cgo.' . $this->object_id
. ' AND cgo.is_active = 1',
array()
)->join(
array('h' => $this->prefix . 'hosts'),
'hcg.host_id = h.host_id',
array()
)->join(
array('ho' => $this->prefix . 'objects'),
'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1',
array()
));
}
protected function joinServicegroups()
{
// TODO: Only hosts with services having such servicegroups
$this->requireVirtualTable('services');
$this->baseQuery->join(
array('sgm' => $this->prefix . 'servicegroup_members'),
'sgm.service_object_id = s.service_object_id',
array()
)->join(
array('sg' => $this->prefix . 'servicegroups'),
'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
array()
)->join(
array('sgo' => $this->prefix . 'objects'),
'sgo.' . $this->object_id . ' = sg.servicegroup_object_id'
. ' AND sgo.is_active = 1',
array()
);
return $this;
}
}

View File

@ -71,6 +71,7 @@ abstract class DataView implements Filterable
*/
public static function fromRequest($request, array $columns = null)
{
$view = new static(Backend::createBackend($request->getParam('backend')), $columns);
$parser = new UrlViewFilter($view);
$view->getQuery()->setFilter($parser->fromRequest($request));
@ -107,7 +108,6 @@ abstract class DataView implements Filterable
$view->getQuery()->where($key, $value);
}
}
$order = isset($params['order']) ? $params['order'] : null;
if ($order !== null) {
if (strtolower($order) === 'desc') {
@ -154,31 +154,32 @@ abstract class DataView implements Filterable
public function sort($column = null, $order = null)
{
$sortRules = $this->getSortRules();
if ($column === null) {
$sortColumns = reset($sortRules);
if (!isset($sortColumns['columns'])) {
$sortColumns['columns'] = array(key($sortRules));
}
} else {
if (isset($sortRules[$column])) {
$sortColumns = $sortRules[$column];
if ($sortRules !== null) {
if ($column === null) {
$sortColumns = reset($sortRules);
if (!isset($sortColumns['columns'])) {
$sortColumns['columns'] = array($column);
$sortColumns['columns'] = array(key($sortRules));
}
} else {
$sortColumns = array(
'columns' => array($column),
'order' => $order
);
};
}
if (isset($sortRules[$column])) {
$sortColumns = $sortRules[$column];
if (!isset($sortColumns['columns'])) {
$sortColumns['columns'] = array($column);
}
} else {
$sortColumns = array(
'columns' => array($column),
'order' => $order
);
};
}
$order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : self::SORT_ASC) : $order;
$order = ($order === self::SORT_ASC) ? 'ASC' : 'DESC';
$order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : self::SORT_ASC) : $order;
$order = ($order === self::SORT_ASC) ? 'ASC' : 'DESC';
foreach ($sortColumns['columns'] as $column) {
$this->query->order($column, $order);
foreach ($sortColumns['columns'] as $column) {
$this->query->order($column, $order);
}
}
return $this;
}
@ -188,7 +189,10 @@ abstract class DataView implements Filterable
*
* @return array
*/
abstract public function getSortRules();
public function getSortRules()
{
return null;
}
public function getMappedField($field)
{

View File

@ -15,7 +15,9 @@ class Downtime extends DataView
{
return array(
'host',
'host_name',
'service',
'service_description',
'downtime_author',
'downtime_comment',
'downtime_entry_time',

View File

@ -58,7 +58,8 @@ class HostStatus extends DataView
'host_action_url',
'host_notes_url',
'host_percent_state_change',
'host_modified_host_attributes'
'host_modified_host_attributes',
'host_severity'
);
}

View File

@ -0,0 +1,38 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\DataView;
class StatusSummary extends DataView
{
/**
* Retrieve columns provided by this view
*
* @return array
*/
public function getColumns()
{
return array(
'hosts_up',
'hosts_unreachable_handled',
'hosts_unreachable_unhandled',
'hosts_down_handled',
'hosts_down_unhandled',
'hosts_pending',
'services_ok',
'services_critical_handled',
'services_critical_unhandled',
'services_warning_handled',
'services_warning_unhandled',
'services_unknown_handled',
'services_unknown_unhandled',
'services_pending'
);
}
public static function getTableName()
{
return 'hoststatus';
}
}

View File

@ -197,40 +197,24 @@
padding-left: 25px !important;
}
.icinga-navbar-pills-mixin (@color) {
border-color: @color;
color: @color;
.topbar-status-summary-mixin (@backgroundImage) {
background-image: url(@backgroundImage);
background-repeat: no-repeat;
background-position: 5px 50%;
padding-left: 30px !important;
margin-top: 15px;
span:not(:last-child) {
margin-right: 5px;
}
}
.topbar-host-status-summary {
.topbar-status-summary-mixin('../../img/icons/host.png');
}
.topbar-service-status-summary {
.topbar-status-summary-mixin('../../img/icons/service.png');
}
.icinga-navbar-pills-critical {
.icinga-navbar-pills-mixin(@colorCritical);
}
.icinga-navbar-pills-ok {
.icinga-navbar-pills-mixin(@colorOk);
}
.icinga-navbar-pills-warning {
.icinga-navbar-pills-mixin(@colorWarning);
}
.icinga-navbar-pills-unknown {
.icinga-navbar-pills-mixin(@colorWarning);
}
.icinga-navbar-pills-unreachable {
.icinga-navbar-pills-mixin(@colorUnreachable);
}
.icinga-navbar-pills-down {
.icinga-navbar-pills-mixin(@colorDown);
}
.icinga-navbar-pills-up {
.icinga-navbar-pills-mixin(@colorUp);
}
.state-tile (@color) {
.topbar-status-mixin (@color) {
border-style: solid;
border-width: 1px;
padding: 3px 5px 3px 5px;
@ -238,20 +222,39 @@
font-size: 13px;
border-color: @color;
color: @color;
a {
color: inherit;
}
}
.state-tile-up {
.navigation-tile-mixin(@colorUp);
.topbar-status-up {
.topbar-status-mixin(@colorUp);
}
.state-tile-unreachable {
.navigation-tile-mixin(@colorUnreachable);
.topbar-status-down {
.topbar-status-mixin(@colorDown);
}
.state-tile-down {
.navigation-tile-mixin(@colorDown);
.topbar-status-unreachable {
.topbar-status-mixin(@colorUnreachable);
}
.state-tile-pending {
.navigation-tile-mixin(@colorPending);
}
.topbar-status-pending {
.topbar-status-mixin(@colorPending);
}
.topbar-status-ok {
.topbar-status-mixin(@colorOk);
}
.topbar-status-critical {
.topbar-status-mixin(@colorCritical);
}
.topbar-status-warning {
.topbar-status-mixin(@colorWarning);
}
.topbar-status-unknown {
.topbar-status-mixin(@colorUnknown);
}

View File

@ -0,0 +1,44 @@
<?php
use Icinga\Authentication\Manager as AuthManager;
use Icinga\Application\Icinga;
use Icinga\Module\Monitoring\DataView\StatusSummary as StatusSummaryView;
use Icinga\Web\Topbar;
$request = Icinga::app()->getFrontController()->getRequest();
if (AuthManager::getInstance()->isAuthenticated()) {
$hostSummary = StatusSummaryView::fromRequest(
$request,
array(
'hosts_up',
'hosts_unreachable_handled',
'hosts_unreachable_unhandled',
'hosts_down_handled',
'hosts_down_unhandled',
'hosts_pending'
)
)->getQuery()->fetchRow();
$serviceSummary = StatusSummaryView::fromRequest(
$request,
array(
'services_ok',
'services_critical_handled',
'services_critical_unhandled',
'services_warning_handled',
'services_warning_unhandled',
'services_unknown_handled',
'services_unknown_unhandled',
'services_pending'
)
)->getQuery()->fetchRow();
Topbar::addPartial(
'topbar.phtml',
'monitoring',
array('hostSummary' => $hostSummary, 'serviceSummary' => $serviceSummary)
);
}
?>

View File

@ -169,26 +169,3 @@ ul.icinga-subnavigation {
padding-left: 15px;
margin-top: 12px;
}
.icinga-navbar-hosts-container {
background-image: url('../../img/icons/host.png');
background-repeat: no-repeat;
background-position: 5px 50%;
padding-left: 30px !important;
margin-top: 15px;
}
.icinga-navbar-services-container {
background-image: url('../../img/icons/service.png');
background-repeat: no-repeat;
background-position: 5px 50%;
padding-left: 25px !important;
margin-top: 15px;
}
.icinga-navbar-pills {
border-style: solid;
border-width: 1px;
padding: 3px 5px 3px 5px;
border-radius: 3px;
font-size: 13px;
}