diff --git a/modules/monitoring/application/controllers/AlertsummaryController.php b/modules/monitoring/application/controllers/AlertsummaryController.php index bc4f41115..238dd59d2 100644 --- a/modules/monitoring/application/controllers/AlertsummaryController.php +++ b/modules/monitoring/application/controllers/AlertsummaryController.php @@ -6,27 +6,68 @@ use Icinga\Chart\GridChart; use Icinga\Chart\Unit\StaticAxis; use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Web\Widget\SelectBox; +use Icinga\Web\Url; class Monitoring_AlertsummaryController extends Controller { + protected $url; + + private $notificationData; + + private $problemData; + + public function init() + { + $tabs = $this->getTabs(); + if (in_array($this->_request->getActionName(), array( + 'alertsummary', + ))) { + $tabs->extend(new OutputFormat())->extend(new DashboardAction()); + } + + $this->url = Url::fromRequest(); + + $this->notificationData = $this->createNotificationData(); + $this->problemData = $this->createProblemData(); + } + + protected function addTitleTab($action, $title = false) + { + $title = $title ?: ucfirst($action); + $this->getTabs()->add($action, array( + 'title' => $title, + // 'url' => Url::fromPath('monitoring/list/' . $action) + 'url' => $this->url + ))->activate($action); + $this->view->title = $title; + } + public function indexAction() { + $this->addTitleTab('alertsummary'); $this->view->intervalBox = $this->createIntervalBox(); $this->view->recentAlerts = $this->createRecentAlerts(); $this->view->interval = $this->getInterval(); + $this->view->defectChart = $this->createDefectImage(); + $this->view->perf = $this->createNotificationPerfdata(); + $this->view->trend = $this->createTrendInformation(); + + $this->setAutorefreshInterval(15); + $query = $this->backend->select()->from('notification', array( + 'host', + 'service', + 'notification_output', + 'notification_contact', + 'notification_start_time', + 'notification_state' + )); + + $this->view->notifications = $query->paginate(); } - public function defectimageAction() - { - $gridChart = new GridChart(); + private function createNotificationData() { $interval = $this->getInterval(); - $gridChart->alignTopLeft(); - $gridChart->setAxisLabel('', t('Services')) - ->setXAxis(new StaticAxis()) - ->setAxisMin(null, 0) - ->setYAxis(new \Icinga\Chart\Unit\LinearUnit(10)); - $query = $this->backend->select()->from('notification', array( 'host', 'service', @@ -46,16 +87,13 @@ class Monitoring_AlertsummaryController extends Controller $query->order('notification_start_time', 'asc'); - $records = $query->paginate(10000); $data = array(); - $defects = array(); $period = $this->createPeriod($interval); foreach ($period as $entry) { $id = $this->getPeriodFormat($interval, $entry->getTimestamp()); $data[$id] = array($id, 0); - $defects[$id] = array($id, 0); } foreach ($records as $item) { @@ -67,18 +105,118 @@ class Monitoring_AlertsummaryController extends Controller $data[$id][1]++; } - $gridChart->drawBars( - array( - 'label' => $this->translate('Notifications'), - 'color' => 'green', - 'data' => $data, - 'showPoints' => true + return $data; + } + + private function createTrendInformation() + { + $date = new DateTime(); + + $beginDate = $date->sub(new DateInterval('P3D')); + $query = $this->backend->select()->from('notification', array( + 'host', + 'service', + 'notification_output', + 'notification_contact', + 'notification_start_time', + 'notification_state' + )); + + $query->setFilter( + new Icinga\Data\Filter\FilterExpression( + 'n.start_time', + '>=', + $beginDate->format('Y-m-d H:i:s') ) ); - $query = null; - $records = null; - $item = null; + $query->order('notification_start_time', 'asc'); + + $records = $query->paginate(10000); + $slots = array(); + + $period = new DatePeriod($beginDate, new DateInterval('P1D'), 2, DatePeriod::EXCLUDE_START_DATE); + foreach ($period as $entry) { + $slots[$entry->format('Y-m-d')] = 0; + } + + foreach ($records as $item) { + $id = strftime('%Y-%m-%d', $item->notification_start_time); + if (isset($slots[$id])) { + $slots[$id]++; + } + } + + $yesterday = array_shift($slots); + $today = array_shift($slots); + + $out = new stdClass(); + if ($yesterday === $today) { + $out->trend = 'unchanged'; + } elseif ($yesterday > $today) { + $out->trend = 'down'; + } else { + $out->trend = 'up'; + } + + if ($yesterday <= 0) { + $out->percent = 100; + } elseif ($yesterday === $today) { + $out->percent = 0; + } else { + $out->percent = 100 - + ((100/($yesterday > $today ? $yesterday : $today)) * ($yesterday > $today ? $today : $yesterday)); + } + + return $out; + } + + private function createNotificationPerfdata() + { + $interval = $this->getInterval(); + + $query = $this->backend->select()->from('notification', array( + 'host', + 'service', + 'notification_output', + 'notification_contact', + 'notification_start_time', + 'notification_state' + )); + + $query->setFilter( + new Icinga\Data\Filter\FilterExpression( + 'n.start_time', + '>=', + $this->getBeginDate($interval)->format('Y-m-d H:i:s') + ) + ); + + $query->order('notification_start_time', 'desc'); + + $records = $query->paginate(10000); + $slots = array(); + + foreach ($records as $item) { + $id = strftime('%Y-%m-%d %H:%I:00', $item->notification_start_time); + + if (empty($slots[$id])) { + $slots[$id] = 0; + } + + $slots[$id]++; + } + + $out = new stdClass(); + $out->avg = sprintf('%.2f', array_sum($slots) / count($slots)); + $out->last = array_shift($slots); + + return $out; + } + + private function createProblemData() + { + $interval = $this->getInterval(); $query = $this->backend->select()->from('eventhistory', array( 'host_name', @@ -111,27 +249,58 @@ class Monitoring_AlertsummaryController extends Controller ) ); + $defects = array(); $records = $query->paginate(10000); + $period = $this->createPeriod($interval); + + foreach ($period as $entry) { + $id = $this->getPeriodFormat($interval, $entry->getTimestamp()); + $defects[$id] = array($id, 0); + } foreach ($records as $item) { $id = $this->getPeriodFormat($interval, $item->timestamp); - if (empty($data[$id])) { + if (empty($defects[$id])) { $defects[$id] = array($id, 0); } - $defects[$id][1]++; } + return $defects; + } + + public function createDefectImage() + { + $gridChart = new GridChart(); + $interval = $this->getInterval(); + + $gridChart->alignTopLeft(); + $gridChart->setAxisLabel('', t('Services')) + ->setXAxis(new StaticAxis()) + ->setAxisMin(null, 0) + ->setYAxis(new \Icinga\Chart\Unit\LinearUnit(10)); + + + + $gridChart->drawBars( + array( + 'label' => $this->translate('Notifications'), + 'color' => 'green', + 'data' => $this->notificationData, + 'showPoints' => true + ) + ); + $gridChart->drawLines( array( 'label' => $this->translate('Defects'), 'color' => 'red', - 'data' => $defects, + 'data' => $this->problemData, 'showPoints' => true ) ); - $this->view->chart = $gridChart; + return $gridChart; } private function createRecentAlerts() diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index 9648145b7..1c8f671a0 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -32,6 +32,10 @@ class Monitoring_ListController extends Controller { $this->createTabs(); $this->view->compact = $this->_request->getParam('view') === 'compact'; + if ($this->_request->getParam('view') === 'inline') { + $this->view->compact = true; + $this->view->inline = true; + } $this->url = Url::fromRequest(); } diff --git a/modules/monitoring/application/views/scripts/alertsummary/defectimage.phtml b/modules/monitoring/application/views/scripts/alertsummary/defectimage.phtml index 91f20a837..e69de29bb 100644 --- a/modules/monitoring/application/views/scripts/alertsummary/defectimage.phtml +++ b/modules/monitoring/application/views/scripts/alertsummary/defectimage.phtml @@ -1,7 +0,0 @@ -<?php if (! $this->compact) { ?> - <div class="svg-container-responsive"> - <?= $chart->render(); ?> - </div> -<?php } else { ?> - <?= $chart->render(); ?> -<?php } ?> diff --git a/modules/monitoring/application/views/scripts/alertsummary/index.phtml b/modules/monitoring/application/views/scripts/alertsummary/index.phtml index 9fd3350c3..44a22eaa4 100644 --- a/modules/monitoring/application/views/scripts/alertsummary/index.phtml +++ b/modules/monitoring/application/views/scripts/alertsummary/index.phtml @@ -2,36 +2,62 @@ $helper = $this->getHelper('MonitoringState'); ?> <div class="controls"> + <?= $this->tabs ?> <div style="margin: 1em;" class="dontprint"> <?= $intervalBox; ?> </div> + <?= $this->widget('limiter') ?> + <?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?> </div> <div class="content alertsummary"> - <h1>Alert summary</h1> + <h1><?= $this->translate('Alert summary'); ?></h1> + + <h2><?= $this->translate('Notifications'); ?></h2> + + <div class="svg-container-responsive"> + <?= $defectChart->render(); ?> + </div> + + <h2><?= $this->translate('Trend'); ?></h2> - <h2>Notifications</h2> <div> - <?= $this->action('defectimage', 'alertsummary', 'monitoring', array('interval' => $this->interval)); ?> + <?= $this->translate('Average') ?> + <strong><?= $this->perf->avg; ?></strong> + <?= $this->translate('notifications per hour'); ?>, + <strong><?= $this->perf->last; ?></strong> + <?= $this->translate('in the last hour'); ?>. + </div> + + <div> + <?= $this->translate('Trend, problems in 24h'); ?> + (<?= $this->trend->percent; ?>% + <?= $this->translate($this->trend->trend); ?>) + + <span> + <?php if ($this->trend->trend === 'up'): ?> + <?= $this->icon('up.png'); ?> + <?php elseif ($this->trend->trend === 'unchanged'): ?> + <?= $this->icon('next.png'); ?> + <?php else: ?> + <?= $this->icon('down.png'); ?> + <?php endif; ?> + </span> </div> <?php if ($this->recentAlerts): ?> <h2><?= $this->translate('Top 5 recent alerts'); ?></h2> - <table> - <tr> - <th><?= $this->translate('Host'); ?></th> - <th><?= $this->translate('Service'); ?></th> - <th><?= $this->translate('State'); ?></th> - <th><?= $this->translate('Timestamp'); ?></th> - </tr> - <?php foreach ($this->recentAlerts as $alert): ?> - <tr> - <td><?= $alert->host; ?></td> - <td><?= $alert->service; ?></td> - <td><?= ucfirst($helper->monitoringStateById($alert->notification_state, $alert->service ? 'service' : 'host')) ?></td> - <td><?= $this->prefixedTimeSince($alert->notification_start_time, true) ?></td> - </tr> - <?php endforeach; ?> - </table> + <?= $this->partial('list/notifications.phtml', array( + 'notifications' => $this->recentAlerts, + 'compact' => true, + 'inline' => true + )); ?> <?php endif; ?> + + <h2><?= $this->translate('History'); ?></h2> + <?= $this->partial('list/notifications.phtml', array( + 'notifications' => $this->notifications, + 'compact' => true, + 'inline' => true + )); ?> </div> \ No newline at end of file diff --git a/modules/monitoring/application/views/scripts/list/notifications.phtml b/modules/monitoring/application/views/scripts/list/notifications.phtml index 826254fd8..fcfea9055 100644 --- a/modules/monitoring/application/views/scripts/list/notifications.phtml +++ b/modules/monitoring/application/views/scripts/list/notifications.phtml @@ -1,4 +1,4 @@ - +<?php var_dump($this->compact); ?> <?php if (!$this->compact): ?> <div class="controls"> <?= $this->tabs ?> @@ -10,7 +10,10 @@ </div> <?php endif ?> +<?php if (! $this->inline): ?> <div class="content"> +<?php endif; ?> + <?php if (empty($this->notifications)) { @@ -75,4 +78,6 @@ foreach ($notifications as $notification): </tbody> </table> +<?php if (!$this->inline): ?> </div> +<?php endif; ?>