Merge branch 'master' into feature/setup-wizard-7163
This commit is contained in:
commit
437b41c6c1
library/Icinga/Web
modules/monitoring
|
@ -14,6 +14,18 @@ use Icinga\Web\Form\Element\CsrfCounterMeasure;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for forms providing CSRF protection, confirmation logic and auto submission
|
* Base class for forms providing CSRF protection, confirmation logic and auto submission
|
||||||
|
*
|
||||||
|
* @method $this setDefaults(array $defaults) {
|
||||||
|
* Use `Form::populate()' for setting default values for elements instead because `Form::setDefaults()' does not
|
||||||
|
* create the form via `Form::create()'.
|
||||||
|
*
|
||||||
|
* Due to a BC introduced with https://github.com/mhujer/zf1/commit/244e3d3f88a363ee0ca49cf63eee31f925f515cd
|
||||||
|
* we cannot override this function without running into a strict standards violation on Zend version 1.12.7.
|
||||||
|
*
|
||||||
|
* @param array $defaults
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* }
|
||||||
*/
|
*/
|
||||||
class Form extends Zend_Form
|
class Form extends Zend_Form
|
||||||
{
|
{
|
||||||
|
@ -508,10 +520,10 @@ class Form extends Zend_Form
|
||||||
*
|
*
|
||||||
* @param array $defaults The values to populate the elements with
|
* @param array $defaults The values to populate the elements with
|
||||||
*/
|
*/
|
||||||
public function setDefaults(array $defaults)
|
public function populate(array $defaults)
|
||||||
{
|
{
|
||||||
$this->create($defaults);
|
$this->create($defaults);
|
||||||
return parent::setDefaults($defaults);
|
return parent::populate($defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,622 @@
|
||||||
|
<?php
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
// {{{ICINGA_LICENSE_HEADER}}}
|
||||||
|
|
||||||
|
use Icinga\Chart\GridChart;
|
||||||
|
use Icinga\Chart\Unit\LinearUnit;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $notificationData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $problemData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init data set
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $action
|
||||||
|
* @param bool $title
|
||||||
|
*/
|
||||||
|
protected function addTitleTab($action, $title = false)
|
||||||
|
{
|
||||||
|
$title = $title ?: ucfirst($action);
|
||||||
|
$this->getTabs()->add(
|
||||||
|
$action,
|
||||||
|
array(
|
||||||
|
'title' => $title,
|
||||||
|
'url' => $this->url
|
||||||
|
)
|
||||||
|
)->activate($action);
|
||||||
|
$this->view->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creat full report
|
||||||
|
*/
|
||||||
|
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->healingChart = $this->createHealingChart();
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create data for charts
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function createNotificationData()
|
||||||
|
{
|
||||||
|
$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', 'asc');
|
||||||
|
|
||||||
|
$records = $query->getQuery()->fetchAll();
|
||||||
|
$data = array();
|
||||||
|
$period = $this->createPeriod($interval);
|
||||||
|
|
||||||
|
foreach ($period as $entry) {
|
||||||
|
$id = $this->getPeriodFormat($interval, $entry->getTimestamp());
|
||||||
|
$data[$id] = array($id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($records as $item) {
|
||||||
|
$id = $this->getPeriodFormat($interval, $item->notification_start_time);
|
||||||
|
if (empty($data[$id])) {
|
||||||
|
$data[$id] = array($id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data[$id][1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trend information for notifications
|
||||||
|
*
|
||||||
|
* @return stdClass
|
||||||
|
*/
|
||||||
|
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->order('notification_start_time', 'asc');
|
||||||
|
|
||||||
|
$records = $query->getQuery()->fetchAll();
|
||||||
|
$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 = sprintf(
|
||||||
|
'%.2f',
|
||||||
|
100 - ((100/($yesterday > $today ? $yesterday : $today)) * ($yesterday > $today ? $today : $yesterday))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perfdata for notifications
|
||||||
|
*
|
||||||
|
* @return stdClass
|
||||||
|
*/
|
||||||
|
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->getQuery()->fetchAll();
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Problems for notifications
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function createProblemData()
|
||||||
|
{
|
||||||
|
$interval = $this->getInterval();
|
||||||
|
|
||||||
|
$query = $this->backend->select()->from(
|
||||||
|
'eventhistory',
|
||||||
|
array(
|
||||||
|
'host_name',
|
||||||
|
'service_description',
|
||||||
|
'object_type',
|
||||||
|
'timestamp',
|
||||||
|
'state',
|
||||||
|
'attempt',
|
||||||
|
'max_attempts',
|
||||||
|
'output',
|
||||||
|
'type',
|
||||||
|
'host',
|
||||||
|
'service',
|
||||||
|
'service_host_name'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$query->addFilter(
|
||||||
|
new Icinga\Data\Filter\FilterExpression(
|
||||||
|
'timestamp',
|
||||||
|
'>=',
|
||||||
|
$this->getBeginDate($interval)->getTimestamp()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$query->addFilter(
|
||||||
|
new Icinga\Data\Filter\FilterExpression(
|
||||||
|
'state',
|
||||||
|
'>',
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$defects = array();
|
||||||
|
$records = $query->getQuery()->fetchAll();
|
||||||
|
$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($defects[$id])) {
|
||||||
|
$defects[$id] = array($id, 0);
|
||||||
|
}
|
||||||
|
$defects[$id][1]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $defects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Healing svg image
|
||||||
|
*
|
||||||
|
* @return GridChart
|
||||||
|
*/
|
||||||
|
public function createHealingChart()
|
||||||
|
{
|
||||||
|
$gridChart = new GridChart();
|
||||||
|
|
||||||
|
$gridChart->alignTopLeft();
|
||||||
|
$gridChart->setAxisLabel('', t('Notifications'))
|
||||||
|
->setXAxis(new StaticAxis())
|
||||||
|
->setAxisMin(null, 0)
|
||||||
|
->setYAxis(new LinearUnit(10));
|
||||||
|
|
||||||
|
$interval = $this->getInterval();
|
||||||
|
|
||||||
|
$query = $this->backend->select()->from(
|
||||||
|
'notification',
|
||||||
|
array(
|
||||||
|
'host',
|
||||||
|
'service',
|
||||||
|
'notification_object_id',
|
||||||
|
'notification_output',
|
||||||
|
'notification_contact',
|
||||||
|
'notification_start_time',
|
||||||
|
'notification_state',
|
||||||
|
'acknowledgement_entry_time'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$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', 'asc');
|
||||||
|
|
||||||
|
$records = $query->getQuery()->fetchAll();
|
||||||
|
|
||||||
|
$interval = $this->getInterval();
|
||||||
|
$period = $this->createPeriod($interval);
|
||||||
|
$dAvg = array();
|
||||||
|
$dMax = array();
|
||||||
|
$notifications = array();
|
||||||
|
$rData = array();
|
||||||
|
|
||||||
|
foreach ($period as $entry) {
|
||||||
|
$id = $this->getPeriodFormat($interval, $entry->getTimestamp());
|
||||||
|
$dMax[$id] = array($id, 0);
|
||||||
|
$dAvg[$id] = array($id, 0, 0);
|
||||||
|
$notifications[$id] = array($id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($records as $item) {
|
||||||
|
$id = $this->getPeriodFormat($interval, $item->notification_start_time);
|
||||||
|
|
||||||
|
if ($item->notification_state == '0' && isset($rData[$item->notification_object_id])) {
|
||||||
|
$rData[$item->notification_object_id]['recover'] =
|
||||||
|
$item->notification_start_time - $rData[$item->notification_object_id]['entry'];
|
||||||
|
} elseif ($item->notification_state !== '0') {
|
||||||
|
$recover = 0;
|
||||||
|
if ($item->acknowledgement_entry_time) {
|
||||||
|
$recover = $item->acknowledgement_entry_time - $item->notification_start_time;
|
||||||
|
}
|
||||||
|
$rData[$item->notification_object_id] = array(
|
||||||
|
'id' => $id,
|
||||||
|
'entry' => $item->notification_start_time,
|
||||||
|
'recover' => $recover
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($rData as $item) {
|
||||||
|
$notifications[$item['id']][1]++;
|
||||||
|
|
||||||
|
if ($item['recover'] > $dMax[$item['id']][1]) {
|
||||||
|
$dMax[$item['id']][1] = (int) $item['recover'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$dAvg[$item['id']][1] += (int) $item['recover'];
|
||||||
|
$dAvg[$item['id']][2]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($dAvg as &$item) {
|
||||||
|
if ($item[2] > 0) {
|
||||||
|
$item[1] = ($item[1]/$item[2])/60/60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($dMax as &$item) {
|
||||||
|
$item[1] = $item[1]/60/60;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$gridChart->drawBars(
|
||||||
|
array(
|
||||||
|
'label' => $this->translate('Notifications'),
|
||||||
|
'color' => 'blue',
|
||||||
|
'data' => $notifications,
|
||||||
|
'showPoints' => true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$gridChart->drawLines(
|
||||||
|
array(
|
||||||
|
'label' => $this->translate('Avg (min)'),
|
||||||
|
'color' => 'orange',
|
||||||
|
'data' => $dAvg,
|
||||||
|
'showPoints' => true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$gridChart->drawLines(
|
||||||
|
array(
|
||||||
|
'label' => $this->translate('Max (min)'),
|
||||||
|
'color' => 'red',
|
||||||
|
'data' => $dMax,
|
||||||
|
'showPoints' => true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $gridChart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifications and defects
|
||||||
|
*
|
||||||
|
* @return GridChart
|
||||||
|
*/
|
||||||
|
public function createDefectImage()
|
||||||
|
{
|
||||||
|
$gridChart = new GridChart();
|
||||||
|
|
||||||
|
$gridChart->alignTopLeft();
|
||||||
|
$gridChart->setAxisLabel('', t('Notifications'))
|
||||||
|
->setXAxis(new StaticAxis())
|
||||||
|
->setAxisMin(null, 0)
|
||||||
|
->setYAxis(new 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' => $this->problemData,
|
||||||
|
'showPoints' => true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $gridChart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top recent alerts
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function createRecentAlerts()
|
||||||
|
{
|
||||||
|
$query = $this->backend->select()->from(
|
||||||
|
'notification',
|
||||||
|
array(
|
||||||
|
'host',
|
||||||
|
'service',
|
||||||
|
'notification_output',
|
||||||
|
'notification_contact',
|
||||||
|
'notification_start_time',
|
||||||
|
'notification_state'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$query->order('notification_start_time', 'desc');
|
||||||
|
|
||||||
|
return $query->paginate(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interval selector box
|
||||||
|
*
|
||||||
|
* @return SelectBox
|
||||||
|
*/
|
||||||
|
private function createIntervalBox()
|
||||||
|
{
|
||||||
|
$box = new SelectBox(
|
||||||
|
'intervalBox',
|
||||||
|
array(
|
||||||
|
'1d' => t('One day'),
|
||||||
|
'1w' => t('One week'),
|
||||||
|
'1m' => t('One month'),
|
||||||
|
'1y' => t('One year')
|
||||||
|
),
|
||||||
|
t('Report interval'),
|
||||||
|
'interval'
|
||||||
|
);
|
||||||
|
$box->applyRequest($this->getRequest());
|
||||||
|
return $box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return reasonable date time format for an interval
|
||||||
|
*
|
||||||
|
* @param string $interval
|
||||||
|
* @param string $timestamp
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getPeriodFormat($interval, $timestamp)
|
||||||
|
{
|
||||||
|
$format = '';
|
||||||
|
if ($interval === '1d') {
|
||||||
|
$format = '%H:00:00';
|
||||||
|
} elseif ($interval === '1w') {
|
||||||
|
$format = '%Y-%m-%d';
|
||||||
|
} elseif ($interval === '1m') {
|
||||||
|
$format = '%Y-%m-%d';
|
||||||
|
} elseif ($interval === '1y') {
|
||||||
|
$format = '%Y-%m';
|
||||||
|
}
|
||||||
|
|
||||||
|
return strftime($format, $timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a reasonable period based in interval strings
|
||||||
|
*
|
||||||
|
* @param $interval
|
||||||
|
* @return DatePeriod
|
||||||
|
*/
|
||||||
|
private function createPeriod($interval)
|
||||||
|
{
|
||||||
|
if ($interval === '1d') {
|
||||||
|
return new DatePeriod($this->getBeginDate($interval), new DateInterval('PT1H'), 24);
|
||||||
|
} elseif ($interval === '1w') {
|
||||||
|
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1D'), 7);
|
||||||
|
} elseif ($interval === '1m') {
|
||||||
|
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1D'), 30);
|
||||||
|
} elseif ($interval === '1y') {
|
||||||
|
return new DatePeriod($this->getBeginDate($interval), new DateInterval('P1M'), 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return start timestamps based on interval strings
|
||||||
|
*
|
||||||
|
* @param $interval
|
||||||
|
* @return DateTime|null
|
||||||
|
*/
|
||||||
|
private function getBeginDate($interval)
|
||||||
|
{
|
||||||
|
$new = new DateTime();
|
||||||
|
if ($interval === '1d') {
|
||||||
|
return $new->sub(new DateInterval('P1D'));
|
||||||
|
} elseif ($interval === '1w') {
|
||||||
|
return $new->sub(new DateInterval('P1W'));
|
||||||
|
} elseif ($interval === '1m') {
|
||||||
|
return $new->sub(new DateInterval('P1M'));
|
||||||
|
} elseif ($interval === '1y') {
|
||||||
|
return $new->sub(new DateInterval('P1Y'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter for interval
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws Zend_Controller_Action_Exception
|
||||||
|
*/
|
||||||
|
private function getInterval()
|
||||||
|
{
|
||||||
|
$interval = $this->getParam('interval', '1d');
|
||||||
|
if (false === in_array($interval, array('1d', '1w', '1m', '1y'))) {
|
||||||
|
throw new Zend_Controller_Action_Exception($this->translate('Value for interval not valid'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $interval;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,15 @@ class Zend_View_Helper_MonitoringState extends Zend_View_Helper_Abstract
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function monitoringStateById($id, $type = 'service')
|
||||||
|
{
|
||||||
|
if ($type === 'service') {
|
||||||
|
return $this->servicestates[$id];
|
||||||
|
} elseif ($type === 'host') {
|
||||||
|
return $this->hoststates[$id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Monitoring colors are clustered.
|
* @deprecated Monitoring colors are clustered.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
$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><?= $this->translate('Alert summary'); ?></h1>
|
||||||
|
|
||||||
|
<div class="alertsummary-flex-container">
|
||||||
|
<div class="alertsummary-flex">
|
||||||
|
<h2><?= $this->translate('Notifications and problems'); ?></h2>
|
||||||
|
<div>
|
||||||
|
<?= $defectChart->render(); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="alertsummary-flex">
|
||||||
|
<h2><?= $this->translate('Time to reaction (Ack, Recover)'); ?></h2>
|
||||||
|
<div>
|
||||||
|
<?= $healingChart->render(); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2><?= $this->translate('Trend'); ?></h2>
|
||||||
|
|
||||||
|
<div class="alertsummary-flex-container">
|
||||||
|
<div class="alertsummary-flex">
|
||||||
|
<?= $this->translate('Average') ?>
|
||||||
|
<strong><?= $this->perf->avg; ?></strong>
|
||||||
|
<?= $this->translate('notifications per hour'); ?>,
|
||||||
|
<strong><?= $this->perf->last; ?></strong>
|
||||||
|
<?= $this->translate('in the last hour'); ?>.
|
||||||
|
|
||||||
|
<?= $this->translate('Trend for the last 24h'); ?>
|
||||||
|
(<?= $this->trend->percent; ?>%
|
||||||
|
<strong><?= $this->translate($this->trend->trend); ?></strong>)
|
||||||
|
|
||||||
|
<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): ?>
|
||||||
|
<h2><?= $this->translate('Top 5 recent alerts'); ?></h2>
|
||||||
|
|
||||||
|
<div class="alertsummary-flex-container">
|
||||||
|
<div class="alertsummary-flex">
|
||||||
|
<?= $this->partial('list/notifications.phtml', array(
|
||||||
|
'notifications' => $this->recentAlerts,
|
||||||
|
'compact' => true,
|
||||||
|
'inline' => true
|
||||||
|
)); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h2><?= $this->translate('History'); ?></h2>
|
||||||
|
<div class="alertsummary-flex-container">
|
||||||
|
<div class="alertsummary-flex">
|
||||||
|
<?= $this->partial('list/notifications.phtml', array(
|
||||||
|
'notifications' => $this->notifications,
|
||||||
|
'compact' => true,
|
||||||
|
'inline' => true
|
||||||
|
)); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<?php if (!$this->compact): ?>
|
<?php if (!$this->compact): ?>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<?= $this->tabs ?>
|
<?= $this->tabs ?>
|
||||||
|
@ -10,7 +9,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 +77,6 @@ foreach ($notifications as $notification):
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<?php if (!$this->inline): ?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
|
@ -122,6 +122,18 @@ $section->add($this->translate('Events'), array(
|
||||||
));
|
));
|
||||||
$section->add($this->translate('Timeline'))->setUrl('monitoring/timeline');
|
$section->add($this->translate('Timeline'))->setUrl('monitoring/timeline');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reporting Section
|
||||||
|
*/
|
||||||
|
$section = $this->menuSection($this->translate('Reporting'), array(
|
||||||
|
'icon' => 'img/icons/hostgroup.png',
|
||||||
|
'priority' => 100
|
||||||
|
));
|
||||||
|
|
||||||
|
$section->add($this->translate('Alert Summary'), array(
|
||||||
|
'url' => 'monitoring/alertsummary/index'
|
||||||
|
));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* System Section
|
* System Section
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,7 +18,8 @@ class NotificationQuery extends IdoQuery
|
||||||
'notification' => array(
|
'notification' => array(
|
||||||
'notification_output' => 'n.output',
|
'notification_output' => 'n.output',
|
||||||
'notification_start_time' => 'UNIX_TIMESTAMP(n.start_time)',
|
'notification_start_time' => 'UNIX_TIMESTAMP(n.start_time)',
|
||||||
'notification_state' => 'n.state'
|
'notification_state' => 'n.state',
|
||||||
|
'notification_object_id' => 'n.object_id'
|
||||||
),
|
),
|
||||||
'objects' => array(
|
'objects' => array(
|
||||||
'host' => 'o.name1',
|
'host' => 'o.name1',
|
||||||
|
@ -30,6 +31,11 @@ class NotificationQuery extends IdoQuery
|
||||||
),
|
),
|
||||||
'command' => array(
|
'command' => array(
|
||||||
'notification_command' => 'cmd_o.name1'
|
'notification_command' => 'cmd_o.name1'
|
||||||
|
),
|
||||||
|
'acknowledgement' => array(
|
||||||
|
'acknowledgement_entry_time' => 'UNIX_TIMESTAMP(a.entry_time)',
|
||||||
|
'acknowledgement_author_name' => 'a.author_name',
|
||||||
|
'acknowledgement_comment_data' => 'a.comment_data'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -95,4 +101,13 @@ class NotificationQuery extends IdoQuery
|
||||||
array()
|
array()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function joinAcknowledgement()
|
||||||
|
{
|
||||||
|
$this->select->joinLeft(
|
||||||
|
array('a' => $this->prefix . 'acknowledgements'),
|
||||||
|
'n.object_id = a.object_id',
|
||||||
|
array()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,3 +134,27 @@ span.state.pending {
|
||||||
form.instance-features span.description, form.object-features span.description {
|
form.instance-features span.description, form.object-features span.description {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alertsummary-flex-container {
|
||||||
|
display: -ms-Flexbox;
|
||||||
|
-ms-box-orient: horizontal;
|
||||||
|
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: -moz-flex;
|
||||||
|
display: -ms-flex;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
-webkit-flex-flow: row wrap;
|
||||||
|
-moz-flex-flow: row wrap;
|
||||||
|
-ms-flex-flow: row wrap;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alertsummary-flex {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px #333 solid;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
border-spacing: 10px 10px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue