AlertSummary: Decouple components and use partials

refs #4078
This commit is contained in:
Marius Hein 2014-10-08 13:33:04 +02:00
parent 87a87656d5
commit c48c7f41b7
5 changed files with 249 additions and 52 deletions

View File

@ -6,27 +6,68 @@ use Icinga\Chart\GridChart;
use Icinga\Chart\Unit\StaticAxis; use Icinga\Chart\Unit\StaticAxis;
use Icinga\Module\Monitoring\Controller; use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Web\Widget\SelectBox; use Icinga\Module\Monitoring\Web\Widget\SelectBox;
use Icinga\Web\Url;
class Monitoring_AlertsummaryController extends Controller 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() public function indexAction()
{ {
$this->addTitleTab('alertsummary');
$this->view->intervalBox = $this->createIntervalBox(); $this->view->intervalBox = $this->createIntervalBox();
$this->view->recentAlerts = $this->createRecentAlerts(); $this->view->recentAlerts = $this->createRecentAlerts();
$this->view->interval = $this->getInterval(); $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() private function createNotificationData() {
{
$gridChart = new GridChart();
$interval = $this->getInterval(); $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( $query = $this->backend->select()->from('notification', array(
'host', 'host',
'service', 'service',
@ -46,16 +87,13 @@ class Monitoring_AlertsummaryController extends Controller
$query->order('notification_start_time', 'asc'); $query->order('notification_start_time', 'asc');
$records = $query->paginate(10000); $records = $query->paginate(10000);
$data = array(); $data = array();
$defects = array();
$period = $this->createPeriod($interval); $period = $this->createPeriod($interval);
foreach ($period as $entry) { foreach ($period as $entry) {
$id = $this->getPeriodFormat($interval, $entry->getTimestamp()); $id = $this->getPeriodFormat($interval, $entry->getTimestamp());
$data[$id] = array($id, 0); $data[$id] = array($id, 0);
$defects[$id] = array($id, 0);
} }
foreach ($records as $item) { foreach ($records as $item) {
@ -67,18 +105,118 @@ class Monitoring_AlertsummaryController extends Controller
$data[$id][1]++; $data[$id][1]++;
} }
$gridChart->drawBars( return $data;
array( }
'label' => $this->translate('Notifications'),
'color' => 'green', private function createTrendInformation()
'data' => $data, {
'showPoints' => true $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; $query->order('notification_start_time', 'asc');
$records = null;
$item = null; $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( $query = $this->backend->select()->from('eventhistory', array(
'host_name', 'host_name',
@ -111,27 +249,58 @@ class Monitoring_AlertsummaryController extends Controller
) )
); );
$defects = array();
$records = $query->paginate(10000); $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) { foreach ($records as $item) {
$id = $this->getPeriodFormat($interval, $item->timestamp); $id = $this->getPeriodFormat($interval, $item->timestamp);
if (empty($data[$id])) { if (empty($defects[$id])) {
$defects[$id] = array($id, 0); $defects[$id] = array($id, 0);
} }
$defects[$id][1]++; $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( $gridChart->drawLines(
array( array(
'label' => $this->translate('Defects'), 'label' => $this->translate('Defects'),
'color' => 'red', 'color' => 'red',
'data' => $defects, 'data' => $this->problemData,
'showPoints' => true 'showPoints' => true
) )
); );
$this->view->chart = $gridChart; return $gridChart;
} }
private function createRecentAlerts() private function createRecentAlerts()

View File

@ -32,6 +32,10 @@ class Monitoring_ListController extends Controller
{ {
$this->createTabs(); $this->createTabs();
$this->view->compact = $this->_request->getParam('view') === 'compact'; $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(); $this->url = Url::fromRequest();
} }

View File

@ -1,7 +0,0 @@
<?php if (! $this->compact) { ?>
<div class="svg-container-responsive">
<?= $chart->render(); ?>
</div>
<?php } else { ?>
<?= $chart->render(); ?>
<?php } ?>

View File

@ -2,36 +2,62 @@
$helper = $this->getHelper('MonitoringState'); $helper = $this->getHelper('MonitoringState');
?> ?>
<div class="controls"> <div class="controls">
<?= $this->tabs ?>
<div style="margin: 1em;" class="dontprint"> <div style="margin: 1em;" class="dontprint">
<?= $intervalBox; ?> <?= $intervalBox; ?>
</div> </div>
<?= $this->widget('limiter') ?>
<?= $this->paginationControl($notifications, null, null, array('preserve' => $this->preserve)) ?>
</div> </div>
<div class="content alertsummary"> <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> <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> </div>
<?php if ($this->recentAlerts): ?> <?php if ($this->recentAlerts): ?>
<h2><?= $this->translate('Top 5 recent alerts'); ?></h2> <h2><?= $this->translate('Top 5 recent alerts'); ?></h2>
<table> <?= $this->partial('list/notifications.phtml', array(
<tr> 'notifications' => $this->recentAlerts,
<th><?= $this->translate('Host'); ?></th> 'compact' => true,
<th><?= $this->translate('Service'); ?></th> 'inline' => true
<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>
<?php endif; ?> <?php endif; ?>
<h2><?= $this->translate('History'); ?></h2>
<?= $this->partial('list/notifications.phtml', array(
'notifications' => $this->notifications,
'compact' => true,
'inline' => true
)); ?>
</div> </div>

View File

@ -1,4 +1,4 @@
<?php var_dump($this->compact); ?>
<?php if (!$this->compact): ?> <?php if (!$this->compact): ?>
<div class="controls"> <div class="controls">
<?= $this->tabs ?> <?= $this->tabs ?>
@ -10,7 +10,10 @@
</div> </div>
<?php endif ?> <?php endif ?>
<?php if (! $this->inline): ?>
<div class="content"> <div class="content">
<?php endif; ?>
<?php <?php
if (empty($this->notifications)) { if (empty($this->notifications)) {
@ -75,4 +78,6 @@ foreach ($notifications as $notification):
</tbody> </tbody>
</table> </table>
<?php if (!$this->inline): ?>
</div> </div>
<?php endif; ?>