parent
e21d288f5b
commit
18b5f715c5
modules/monitoring
application
library/Monitoring
|
@ -1,72 +1,47 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga Web 2.
|
||||
*
|
||||
* Icinga Web 2 - 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}}}
|
||||
|
||||
use \DateTime;
|
||||
use \Exception;
|
||||
use \DateInterval;
|
||||
use Icinga\Web\Hook;
|
||||
use \Zend_Config;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Web\Controller\ActionController;
|
||||
use Icinga\Module\Monitoring\Timeline\TimeLine;
|
||||
use Icinga\Module\Monitoring\Timeline\TimeEntry;
|
||||
use Icinga\Module\Monitoring\Timeline\TimeRange;
|
||||
use Icinga\Module\Monitoring\Web\Widget\TimelineIntervalBox;
|
||||
use Icinga\Module\Monitoring\DataView\EventHistory as EventHistoryView;
|
||||
|
||||
class Monitoring_TimelineController extends ActionController
|
||||
{
|
||||
public function showAction()
|
||||
public function indexAction()
|
||||
{
|
||||
$this->setupIntervalBox();
|
||||
$timeline = new TimeLine();
|
||||
$timeline->setConfiguration(Config::app());
|
||||
//$timeline->setAttrib('data-icinga-component', 'monitoring/timelineComponent');
|
||||
list($displayRange, $forecastRange) = $this->buildTimeRanges($this->getTimelineInterval());
|
||||
$timeline->setTimeRange($displayRange);
|
||||
$timeline->setDisplayData($this->loadData($displayRange));
|
||||
$timeline->setForecastData($this->loadData($forecastRange));
|
||||
$this->view->timeline = $timeline;
|
||||
}
|
||||
list($displayRange, $forecastRange) = $this->buildTimeRanges();
|
||||
|
||||
public function extendAction()
|
||||
{
|
||||
$this->setupIntervalBox();
|
||||
$timeline = new TimeLine();
|
||||
$timeline->setConfiguration(Config::app());
|
||||
list($displayRange, $forecastRange) = $this->buildTimeRanges($this->getTimelineInterval());
|
||||
$timeline->setTimeRange($displayRange);
|
||||
$timeline->setDisplayData($this->loadData($displayRange));
|
||||
$timeline->setForecastData($this->loadData($forecastRange));
|
||||
$this->view->timeline = $timeline;
|
||||
$timeline = new TimeLine(
|
||||
EventHistoryView::fromRequest(
|
||||
$this->getRequest(),
|
||||
array(
|
||||
'name' => 'type',
|
||||
'time' => 'raw_timestamp'
|
||||
)
|
||||
),
|
||||
array(
|
||||
'notify' => array('label' => t('Notifications'), 'color' => 'red'),
|
||||
'hard_state' => array('label' => t('Hard state changes'), 'color' => 'green'),
|
||||
'comment' => array('label' => t('Comments'), 'color' => 'blue'),
|
||||
'ack' => array('label' => t('Acknowledgements'), 'color' => 'black'),
|
||||
'dt_start' => array('label' => t('Started downtimes'), 'color' => 'grey'),
|
||||
'dt_end' => array('label' => t('Ended downtimes'), 'color' => 'white')
|
||||
)
|
||||
);
|
||||
$timeline->setDisplayRange($displayRange);
|
||||
$timeline->setForecastRange($forecastRange);
|
||||
|
||||
// Disable layout as this is an AJAX request
|
||||
$this->_helper->layout()->disableLayout();
|
||||
$this->view->timeline = $timeline;
|
||||
$this->view->intervalFormat = $this->getIntervalFormat();
|
||||
$this->view->switchedContext = $timeline->getCalculationBase(false) !== $timeline->getCalculationBase(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,27 +86,112 @@ class Monitoring_TimelineController extends ActionController
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a new display- and forecast time range
|
||||
* Get an appropriate datetime format string for the chosen interval
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getIntervalFormat()
|
||||
{
|
||||
switch ($this->view->intervalBox->getInterval())
|
||||
{
|
||||
case '1d':
|
||||
return $this->getDateFormat();
|
||||
case '1w':
|
||||
return '\W\e\ek #W \of Y';
|
||||
case '1m':
|
||||
return 'F Y';
|
||||
case '1y':
|
||||
return 'Y';
|
||||
default:
|
||||
return $this->getDateFormat() . ' ' . $this->getTimeFormat();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a preload interval based on the chosen timeline interval
|
||||
*
|
||||
* @return DateInterval The interval to pre-load
|
||||
*/
|
||||
private function getPreloadInterval()
|
||||
{
|
||||
switch ($this->view->intervalBox->getInterval())
|
||||
{
|
||||
case '1d':
|
||||
return DateInterval::createFromDateString('1 week -1 second');
|
||||
case '1w':
|
||||
return DateInterval::createFromDateString('8 weeks -1 second');
|
||||
case '1m':
|
||||
return DateInterval::createFromDateString('6 months -1 second');
|
||||
case '1y':
|
||||
return DateInterval::createFromDateString('4 years -1 second');
|
||||
default:
|
||||
return DateInterval::createFromDateString('1 day -1 second');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrapolate the given datetime based on the chosen timeline interval
|
||||
*
|
||||
* @param DateTime $dateTime The datetime to extrapolate
|
||||
*/
|
||||
private function extrapolateDateTime(DateTime &$dateTime)
|
||||
{
|
||||
switch ($this->view->intervalBox->getInterval())
|
||||
{
|
||||
case '1d':
|
||||
$dateTime->setTimestamp(strtotime('tomorrow', $dateTime->getTimestamp()) - 1);
|
||||
break;
|
||||
case '1w':
|
||||
$dateTime->setTimestamp(strtotime('next monday', $dateTime->getTimestamp()) - 1);
|
||||
break;
|
||||
case '1m':
|
||||
$dateTime->setTimestamp(
|
||||
strtotime(
|
||||
'last day of this month',
|
||||
strtotime(
|
||||
'tomorrow',
|
||||
$dateTime->getTimestamp()
|
||||
) - 1
|
||||
)
|
||||
);
|
||||
break;
|
||||
case '1y':
|
||||
$dateTime->setTimestamp(strtotime('1 january next year', $dateTime->getTimestamp()) - 1);
|
||||
break;
|
||||
default:
|
||||
$hour = $dateTime->format('G');
|
||||
$end = $hour < 4 ? 4 : ($hour < 8 ? 8 : ($hour < 12 ? 12 : ($hour < 16 ? 16 : ($hour < 20 ? 20 : 24))));
|
||||
$dateTime = DateTime::createFromFormat(
|
||||
'd/m/y G:i:s',
|
||||
$dateTime->format('d/m/y') . ($end - 1) . ':59:59'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a display- and forecast time range
|
||||
*
|
||||
* Assembles a time range each for display and forecast purposes based on the start- and
|
||||
* end time if given in the current request otherwise based on the current time and a
|
||||
* end time that is calculated based on the given interval.
|
||||
* end time that is calculated based on the chosen timeline interval.
|
||||
*
|
||||
* @param DateInterval $interval The interval by which to part the time range
|
||||
* @return TimeRange The resulting time range
|
||||
* @throws Exception If a start time is given in the request but no end time
|
||||
* @return array The resulting time ranges
|
||||
*/
|
||||
private function buildTimeRanges(DateInterval $interval)
|
||||
private function buildTimeRanges()
|
||||
{
|
||||
$startTime = DateTime::createFromFormat('Y-m-d_G-i-s', $this->_request->getParam('start'));
|
||||
$endTime = DateTime::createFromFormat('Y-m-d_G-i-s', $this->_request->getParam('end'));
|
||||
$startTime = new DateTime();
|
||||
$startTimestamp = strtotime($this->_request->getParam('start'));
|
||||
if ($startTimestamp !== false) {
|
||||
$startTime->setTimestamp($startTimestamp);
|
||||
}
|
||||
$this->extrapolateDateTime($startTime);
|
||||
|
||||
if (!$startTime) {
|
||||
$startTime = $this->extrapolateDateTime(new DateTime(), $interval);
|
||||
$endTime = clone $startTime;
|
||||
$endTime->sub($this->getPreloadInterval($interval));
|
||||
} elseif (!$endTime) {
|
||||
throw new Exception('Missing end time in request');
|
||||
$endTime = clone $startTime;
|
||||
$endTimestamp = strtotime($this->_request->getParam('end'));
|
||||
if ($endTimestamp !== false) {
|
||||
$endTime->setTimestamp($endTimestamp);
|
||||
} else {
|
||||
$endTime->sub($this->getPreloadInterval());
|
||||
}
|
||||
|
||||
$forecastStart = clone $endTime;
|
||||
|
@ -139,351 +199,50 @@ class Monitoring_TimelineController extends ActionController
|
|||
$forecastEnd = clone $forecastStart;
|
||||
$forecastEnd->sub($endTime->diff($startTime));
|
||||
|
||||
$timelineInterval = $this->getTimelineInterval();
|
||||
return array(
|
||||
new TimeRange($startTime, $endTime, $interval),
|
||||
new TimeRange($forecastStart, $forecastEnd, $interval)
|
||||
new TimeRange($startTime, $endTime, $timelineInterval),
|
||||
new TimeRange($forecastStart, $forecastEnd, $timelineInterval)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrapolate the given datetime based on the given interval
|
||||
* Get the application's global configuration or an empty one
|
||||
*
|
||||
* @param DateTime $dateTime The datetime to extrapolate
|
||||
* @param DateInterval $interval The interval by which to part a time range
|
||||
* @return DateTime The extrapolated datetime
|
||||
* @throws Exception If the given interval is invalid
|
||||
* @return Zend_Config
|
||||
*/
|
||||
private function extrapolateDateTime(DateTime $dateTime, DateInterval $interval)
|
||||
private function getGlobalConfiguration()
|
||||
{
|
||||
if ($interval->h == 4) {
|
||||
$hour = $dateTime->format('G');
|
||||
$end = $hour < 4 ? 4 : ($hour < 8 ? 8 : ($hour < 12 ? 12 : ($hour < 16 ? 16 : ($hour < 20 ? 20 : 24))));
|
||||
$dateTime = DateTime::createFromFormat('d/m/y G:i:s', $dateTime->format('d/m/y') . ($end - 1) . ':59:59');
|
||||
} elseif ($interval->d == 1) {
|
||||
$dateTime->setTimestamp(strtotime('tomorrow', $dateTime->getTimestamp()) - 1);
|
||||
} elseif ($interval->d == 7) {
|
||||
$dateTime->setTimestamp(strtotime('next monday', $dateTime->getTimestamp()) - 1);
|
||||
} elseif ($interval->m == 1) {
|
||||
$dateTime->setTimestamp(
|
||||
strtotime(
|
||||
'last day of this month',
|
||||
strtotime(
|
||||
'tomorrow',
|
||||
$dateTime->getTimestamp()
|
||||
) - 1
|
||||
)
|
||||
);
|
||||
} elseif ($interval->y == 1) {
|
||||
$dateTime->setTimestamp(strtotime('1 january next year', $dateTime->getTimestamp()) - 1);
|
||||
} else {
|
||||
throw new Exception('Invalid interval given. Valid intervals are: 4 hours, 1 day, 1 week, 1 month, 1 year');
|
||||
$globalConfig = Config::app()->global;
|
||||
|
||||
if ($globalConfig === null) {
|
||||
$globalConfig = new Zend_Config(array());
|
||||
}
|
||||
|
||||
return $dateTime;
|
||||
return $globalConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new preload interval
|
||||
* Get the user's preferred time format or the application's default
|
||||
*
|
||||
* Examine the given interval and return a new one that defines how much data should be loaded
|
||||
*
|
||||
* @param DateInterval $interval The interval by which to part a time range
|
||||
* @return DateInterval The interval to load
|
||||
* @throws Exception If the given interval is invalid
|
||||
* @return string
|
||||
*/
|
||||
private function getPreloadInterval(DateInterval $interval)
|
||||
private function getTimeFormat()
|
||||
{
|
||||
if ($interval->h == 4) {
|
||||
return DateInterval::createFromDateString('1 day -1 second');
|
||||
} elseif ($interval->d == 1) {
|
||||
return DateInterval::createFromDateString('1 week -1 second');
|
||||
} elseif ($interval->d == 7) {
|
||||
return DateInterval::createFromDateString('8 weeks -1 second');
|
||||
} elseif ($interval->m == 1) {
|
||||
return DateInterval::createFromDateString('6 months -1 second');
|
||||
} elseif ($interval->y == 1) {
|
||||
return DateInterval::createFromDateString('4 years -1 second');
|
||||
} else {
|
||||
throw new Exception('Invalid interval given. Valid intervals are: 4 hours, 1 day, 1 week, 1 month, 1 year');
|
||||
}
|
||||
$globalConfig = $this->getGlobalConfiguration();
|
||||
$preferences = $this->getRequest()->getUser()->getPreferences();
|
||||
return $preferences->get('app.timeFormat', $globalConfig->get('timeFormat', 'g:i A'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups a set of elements based on a specific range of time
|
||||
* Get the user's preferred date format or the application's default
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @param array $elements The elements to group. Each element need to have a ´time´ property
|
||||
* that defines its position in the given range of time
|
||||
* @param array $attributes The attributes to set on each event group. Need to contain at least
|
||||
* a ´name´ and a ´detailUrl´. The detailUrl need also to contain
|
||||
* placeholders for both the start- and end time of a specific timeframe
|
||||
* @return array A list of event groups suitable to pass to the timeline
|
||||
* @throws ProgrammingError If an element is found that does not match the given range of time
|
||||
* or one of the required attributes is missing
|
||||
* @return string
|
||||
*/
|
||||
private function groupResults(TimeRange $range, array $elements, array $attributes)
|
||||
private function getDateFormat()
|
||||
{
|
||||
$groupCounts = array();
|
||||
foreach ($elements as $element) {
|
||||
$elementTime = new DateTime();
|
||||
$elementTime->setTimestamp($element->time);
|
||||
$timeframeIdentifier = $range->findTimeframe($elementTime, true);
|
||||
|
||||
if ($timeframeIdentifier === null) {
|
||||
$format = 'd/m/y G:i:s';
|
||||
throw new ProgrammingError(
|
||||
'Event result does not match any timeframe in the given range of time: ' .
|
||||
$elementTime->format($format) . ' not in ' . $range->getStart()->format($format) .
|
||||
' -> ' . $range->getEnd()->format($format)
|
||||
);
|
||||
}
|
||||
|
||||
if (array_key_exists($timeframeIdentifier, $groupCounts)) {
|
||||
$groupCounts[$timeframeIdentifier] += 1;
|
||||
} else {
|
||||
$groupCounts[$timeframeIdentifier] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!array_key_exists('name', $attributes) || !array_key_exists('detailUrl', $attributes)) {
|
||||
throw new ProgrammingError('Missing required event group attribute. Either ´name´ or ´detailUrl´');
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
$urlTemplate = $attributes['detailUrl'];
|
||||
foreach ($groupCounts as $timeframeIdentifier => $groupCount) {
|
||||
$timeframe = $range->getTimeframe($timeframeIdentifier);
|
||||
$attributes['dateTime'] = $timeframe->start;
|
||||
$attributes['value'] = $groupCount;
|
||||
$attributes['detailUrl'] = sprintf(
|
||||
$urlTemplate,
|
||||
$timeframe->start->getTimestamp(),
|
||||
$timeframe->end->getTimestamp()
|
||||
);
|
||||
$groups[] = TimeEntry::fromArray($attributes);
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the event groups that the timeline should display
|
||||
*
|
||||
* @param TimeRange $timeRange The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadData(TimeRange $timeRange)
|
||||
{
|
||||
$entries = array_merge(
|
||||
$this->loadInitiatedDowntimes($timeRange),
|
||||
$this->loadFinishedDowntimes($timeRange),
|
||||
$this->loadAcknowledgements($timeRange),
|
||||
$this->loadNotifications($timeRange),
|
||||
$this->loadStateChanges($timeRange),
|
||||
$this->loadComments($timeRange)
|
||||
);
|
||||
|
||||
foreach (Hook::all('timeline') as $timelineProvider) {
|
||||
$entries = array_merge(
|
||||
$entries,
|
||||
$timelineProvider->fetchTimeEntries($timeRange, $this->_request)
|
||||
);
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all problem notifications sent out in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadNotifications(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = notify')
|
||||
->where('state != 0')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Notifications'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=notify&state>0'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all status changes occured in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadStateChanges(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = hard_state')
|
||||
->where('state != 0')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Hard states'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=hard_state&state>0'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all comments made in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadComments(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = comment')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Comments'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=comment'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all acknowledgements placed in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadAcknowledgements(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = ack')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Acknowledgements'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=ack'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all downtimes that were initiated in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadInitiatedDowntimes(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = dt_start')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Initiated downtimes'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=dt_start'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate all downtimes that were finished in the given range of time
|
||||
*
|
||||
* @param TimeRange $range The range of time represented by the timeline
|
||||
* @return array
|
||||
*/
|
||||
private function loadFinishedDowntimes(TimeRange $range)
|
||||
{
|
||||
$query = EventHistoryView::fromRequest(
|
||||
$this->_request,
|
||||
array(
|
||||
'time' => 'timestamp'
|
||||
)
|
||||
)->getQuery();
|
||||
|
||||
$result = $query->where('timestamp <= ' . $range->getStart()->getTimestamp())
|
||||
->where('timestamp > ' . $range->getEnd()->getTimestamp())
|
||||
->where('type = dt_end')
|
||||
->fetchAll();
|
||||
|
||||
return $this->groupResults(
|
||||
$range,
|
||||
$result,
|
||||
array(
|
||||
'name' => t('Finished downtimes'),
|
||||
'detailUrl' => $this->view->baseUrl(
|
||||
'monitoring/list/eventhistory?timestamp<=%s×tamp>=%s&type=dt_end'
|
||||
)
|
||||
)
|
||||
);
|
||||
$globalConfig = $this->getGlobalConfiguration();
|
||||
$preferences = $this->getRequest()->getUser()->getPreferences();
|
||||
return $preferences->get('app.dateFormat', $globalConfig->get('dateFormat', 'd/m/Y'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<?= $this->timeline ?>
|
|
@ -1,29 +1,5 @@
|
|||
<?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\Timeline;
|
||||
|
@ -41,42 +17,49 @@ class TimeEntry
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* The amount of events that are part of this group
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $value;
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* The date and time of this group
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
private $dateTime;
|
||||
protected $dateTime;
|
||||
|
||||
/**
|
||||
* The url to this group's detail view
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $detailUrl;
|
||||
protected $detailUrl;
|
||||
|
||||
/**
|
||||
* The weight of this group
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $weight = 1.0;
|
||||
protected $weight = 1.0;
|
||||
|
||||
/**
|
||||
* The label of this group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $label;
|
||||
|
||||
/**
|
||||
* The color of this group
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $color;
|
||||
protected $color;
|
||||
|
||||
/**
|
||||
* Return a new TimeEntry object with the given attributes being set
|
||||
|
@ -136,12 +119,11 @@ class TimeEntry
|
|||
/**
|
||||
* Return the amount of events in this group
|
||||
*
|
||||
* @param bool $raw Whether to ignore the set weight
|
||||
* @return int
|
||||
*/
|
||||
public function getValue($raw = false)
|
||||
public function getValue()
|
||||
{
|
||||
return $raw ? $this->value : $this->value * $this->weight;
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,6 +186,26 @@ class TimeEntry
|
|||
return $this->weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this group's label
|
||||
*
|
||||
* @param string $label The label to set
|
||||
*/
|
||||
public function setLabel($label)
|
||||
{
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the label of this group
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLabel()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this group's color
|
||||
*
|
||||
|
|
|
@ -1,117 +1,136 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga Web 2.
|
||||
*
|
||||
* Icinga Web 2 - 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\Timeline;
|
||||
|
||||
use \Zend_Config;
|
||||
use \DateTime;
|
||||
use \Exception;
|
||||
use \ArrayIterator;
|
||||
use \IteratorAggregate;
|
||||
use Icinga\Web\Hook;
|
||||
use Icinga\Module\Monitoring\DataView\DataView;
|
||||
|
||||
/**
|
||||
* Represents a set of events in a specific time range
|
||||
* Represents a set of events in a specific range of time
|
||||
*/
|
||||
class TimeLine
|
||||
class TimeLine implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* The range of time represented by this timeline
|
||||
*
|
||||
* @var TimeRange
|
||||
*/
|
||||
private $range;
|
||||
|
||||
/**
|
||||
* The event groups this timeline will display
|
||||
* The resultset returned by the dataview
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $displayData;
|
||||
private $resultset;
|
||||
|
||||
/**
|
||||
* The event groups this timeline uses to calculate forecasts
|
||||
* The groups this timeline uses for display purposes
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $forecastData;
|
||||
|
||||
/**
|
||||
* The maximum diameter each circle can have
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $circleDiameter = 250;
|
||||
|
||||
/**
|
||||
* The unit of a circle's diameter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $diameterUnit = 'px';
|
||||
private $displayGroups;
|
||||
|
||||
/**
|
||||
* The base that is used to calculate each circle's diameter
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
private $calculationBase;
|
||||
protected $calculationBase;
|
||||
|
||||
/**
|
||||
* Set the range of time to represent
|
||||
* The dataview to fetch entries from
|
||||
*
|
||||
* @param TimeRange $range The range of time to represent
|
||||
* @var DataView
|
||||
*/
|
||||
public function setTimeRange(TimeRange $range)
|
||||
protected $dataview;
|
||||
|
||||
/**
|
||||
* The names by which to group entries
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $identifiers;
|
||||
|
||||
/**
|
||||
* The range of time for which to display entries
|
||||
*
|
||||
* @var TimeRange
|
||||
*/
|
||||
protected $displayRange;
|
||||
|
||||
/**
|
||||
* The range of time for which to calculate forecasts
|
||||
*
|
||||
* @var TimeRange
|
||||
*/
|
||||
protected $forecastRange;
|
||||
|
||||
/**
|
||||
* The maximum diameter each circle can have
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
protected $circleDiameter = 100.0;
|
||||
|
||||
/**
|
||||
* The unit of a circle's diameter
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $diameterUnit = 'px';
|
||||
|
||||
/**
|
||||
* Return a iterator for this timeline
|
||||
*
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
$this->range = $range;
|
||||
return new ArrayIterator($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the groups this timeline should display
|
||||
* Create a new timeline
|
||||
*
|
||||
* @param array $entries The TimeEntry objects
|
||||
* The given dataview must provide the following columns:
|
||||
* - name A string identifying an entry (Corresponds to the keys of "$identifiers")
|
||||
* - time A unix timestamp that defines where to place an entry on the timeline
|
||||
*
|
||||
* @param DataView $dataview The dataview to fetch entries from
|
||||
* @param array $identifiers The names by which to group entries
|
||||
*/
|
||||
public function setDisplayData(array $entries)
|
||||
public function __construct(DataView $dataview, array $identifiers)
|
||||
{
|
||||
$this->displayData = $entries;
|
||||
$this->dataview = $dataview;
|
||||
$this->identifiers = $identifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the groups this timeline should use to calculate forecasts
|
||||
* Set the range of time for which to display elements
|
||||
*
|
||||
* @param array $entries The TimeEntry objects
|
||||
* @param TimeRange $range The range of time for which to display elements
|
||||
*/
|
||||
public function setForecastData(array $entries)
|
||||
public function setDisplayRange(TimeRange $range)
|
||||
{
|
||||
$this->forecastData = $entries;
|
||||
$this->displayRange = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the range of time for which to calculate forecasts
|
||||
*
|
||||
* @param TimeRange $range The range of time for which to calculate forecasts
|
||||
*/
|
||||
public function setForecastRange(TimeRange $range)
|
||||
{
|
||||
$this->forecastRange = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum diameter each circle can have
|
||||
*
|
||||
* @param string $width The diameter to set, suffixed with its unit
|
||||
* @throws Exception If the given diameter is invalid
|
||||
* @param string $width The diameter to set, suffixed with its unit
|
||||
*
|
||||
* @throws Exception If the given diameter is invalid
|
||||
*/
|
||||
public function setMaximumCircleWidth($width)
|
||||
{
|
||||
|
@ -124,6 +143,247 @@ class TimeLine
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the circle's diameter for the given event group
|
||||
*
|
||||
* @param TimeEntry $group The group for which to return a circle width
|
||||
* @param int $precision Amount of decimal places to preserve
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function calculateCircleWidth(TimeEntry $group, $precision = 0)
|
||||
{
|
||||
$base = $this->getCalculationBase(true);
|
||||
$factor = log($group->getValue() * $group->getWeight(), $base) / 100;
|
||||
return sprintf('%.' . $precision . 'F%s', $this->circleDiameter * $factor, $this->diameterUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an extrapolated circle width for the given event group
|
||||
*
|
||||
* @param TimeEntry $group The event group for which to return an extrapolated circle width
|
||||
* @param int $precision Amount of decimal places to preserve
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtrapolatedCircleWidth(TimeEntry $group, $precision = 0)
|
||||
{
|
||||
$eventCount = 0;
|
||||
foreach ($this->displayGroups as $groups) {
|
||||
if (array_key_exists($group->getName(), $groups)) {
|
||||
$eventCount += $groups[$group->getName()]->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
$extrapolatedCount = (int) $eventCount / count($this->displayGroups);
|
||||
if ($extrapolatedCount < $group->getValue()) {
|
||||
return $this->calculateCircleWidth($group, $precision);
|
||||
}
|
||||
|
||||
return $this->calculateCircleWidth(
|
||||
TimeEntry::fromArray(
|
||||
array(
|
||||
'value' => $extrapolatedCount,
|
||||
'weight' => $group->getWeight()
|
||||
)
|
||||
),
|
||||
$precision
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base that should be used to calculate circle widths
|
||||
*
|
||||
* @param bool $create Whether to generate a new base if none is known yet
|
||||
*
|
||||
* @return float|null
|
||||
*/
|
||||
public function getCalculationBase($create)
|
||||
{
|
||||
if ($this->calculationBase === null) {
|
||||
// TODO: get base from session
|
||||
if ($create) {
|
||||
$new = $this->generateCalculationBase();
|
||||
if ($new > $this->calculationBase) {
|
||||
// TODO: save base in session
|
||||
$this->calculationBase = $new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->calculationBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new base to calculate circle widths with
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
protected function generateCalculationBase()
|
||||
{
|
||||
$allEntries = $this->groupEntries(
|
||||
array_merge(
|
||||
$this->fetchEntries(),
|
||||
$this->fetchForecasts()
|
||||
),
|
||||
new TimeRange(
|
||||
$this->displayRange->getStart(),
|
||||
$this->forecastRange->getEnd(),
|
||||
$this->displayRange->getInterval()
|
||||
)
|
||||
);
|
||||
|
||||
$highestValue = 0;
|
||||
foreach ($allEntries as $groups) {
|
||||
foreach ($groups as $group) {
|
||||
if ($group->getValue() * $group->getWeight() > $highestValue) {
|
||||
$highestValue = $group->getValue() * $group->getWeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pow($highestValue, 1 / 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all entries and forecasts by using the dataview associated with this timeline
|
||||
*
|
||||
* @return array The dataview's result
|
||||
*/
|
||||
private function fetchResults()
|
||||
{
|
||||
$hookResults = array();
|
||||
foreach (Hook::all('timeline') as $timelineProvider) {
|
||||
$hookResults = array_merge(
|
||||
$hookResults,
|
||||
$timelineProvider->fetchEntries($this->displayRange),
|
||||
$timelineProvider->fetchForecasts($this->forecastRange)
|
||||
);
|
||||
|
||||
foreach ($timelineProvider->getIdentifiers() as $identifier => $attributes) {
|
||||
if (!array_key_exists($identifier, $this->identifiers)) {
|
||||
$this->identifiers[$identifier] = $attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->dataview->getQuery();
|
||||
$queryColumns = $query->getColumns();
|
||||
$query->where(
|
||||
$query->isValidFilterTarget('name') ? 'name' : $queryColumns['name'],
|
||||
array_keys($this->identifiers)
|
||||
)->where('raw_timestamp <= ?', $this->displayRange->getStart()->getTimestamp())
|
||||
->where('raw_timestamp > ?', $this->forecastRange->getEnd()->getTimestamp());
|
||||
|
||||
return array_merge($query->fetchAll(), $hookResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all entries
|
||||
*
|
||||
* @return array The entries to display on the timeline
|
||||
*/
|
||||
protected function fetchEntries()
|
||||
{
|
||||
if ($this->resultset === null) {
|
||||
$this->resultset = $this->fetchResults();
|
||||
}
|
||||
|
||||
$range = $this->displayRange;
|
||||
return array_filter(
|
||||
$this->resultset,
|
||||
function ($e) use ($range) { return $range->validateTime($e->time); }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all forecasts
|
||||
*
|
||||
* @return array The entries to calculate forecasts with
|
||||
*/
|
||||
protected function fetchForecasts()
|
||||
{
|
||||
if ($this->resultset === null) {
|
||||
$this->resultset = $this->fetchResults();
|
||||
}
|
||||
|
||||
$range = $this->forecastRange;
|
||||
return array_filter(
|
||||
$this->resultset,
|
||||
function ($e) use ($range) { return $range->validateTime($e->time); }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the given entries grouped together
|
||||
*
|
||||
* @param array $entries The entries to group
|
||||
* @param TimeRange $timeRange The range of time to group by
|
||||
*
|
||||
* @return array displayGroups The grouped entries
|
||||
*/
|
||||
protected function groupEntries(array $entries, TimeRange $timeRange)
|
||||
{
|
||||
$counts = array();
|
||||
foreach ($entries as $entry) {
|
||||
$entryTime = new DateTime();
|
||||
$entryTime->setTimestamp($entry->time);
|
||||
$timestamp = $timeRange->findTimeframe($entryTime, true);
|
||||
|
||||
if ($timestamp !== null) {
|
||||
if (array_key_exists($entry->name, $counts)) {
|
||||
if (array_key_exists($timestamp, $counts[$entry->name])) {
|
||||
$counts[$entry->name][$timestamp] += 1;
|
||||
} else {
|
||||
$counts[$entry->name][$timestamp] = 1;
|
||||
}
|
||||
} else {
|
||||
$counts[$entry->name][$timestamp] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$groups = array();
|
||||
foreach ($counts as $name => $data) {
|
||||
foreach ($data as $timestamp => $count) {
|
||||
$dateTime = new DateTime();
|
||||
$dateTime->setTimestamp($timestamp);
|
||||
$groups[$timestamp][$name] = TimeEntry::fromArray(
|
||||
array_merge(
|
||||
$this->identifiers[$name],
|
||||
array(
|
||||
'name' => $name,
|
||||
'value' => $count,
|
||||
'dateTime' => $dateTime
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the contents of this timeline as array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function toArray()
|
||||
{
|
||||
$this->displayGroups = $this->groupEntries($this->fetchEntries(), $this->displayRange);
|
||||
|
||||
$array = array();
|
||||
foreach ($this->displayRange as $timestamp => $timeframe) {
|
||||
$array[] = array(
|
||||
$timeframe,
|
||||
array_key_exists($timestamp, $this->displayGroups) ? $this->displayGroups[$timestamp] : array()
|
||||
);
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the legend
|
||||
*/
|
||||
|
@ -225,173 +485,4 @@ class TimeLine
|
|||
$elements[] = '<span id="TimelineEnd"></span>';
|
||||
return implode('', $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return contextless attributes of all available distinct group types
|
||||
*
|
||||
* Returns an associative array where each key refers to the name
|
||||
* and the value to the attributes of a specific group type.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getGroups()
|
||||
{
|
||||
$groups = array();
|
||||
foreach (array_merge($this->displayData, $this->forecastData) as $group) {
|
||||
if (!array_key_exists($group->getName(), $groups)) {
|
||||
$groups[$group->getName()] = array(
|
||||
'color' => $group->getColor(),
|
||||
'weight' => $group->getWeight()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the circle's diameter for the given amount of events
|
||||
*
|
||||
* @param int $eventCount The amount of events represented by the circle
|
||||
* @return int
|
||||
*/
|
||||
private function calculateCircleWidth($eventCount)
|
||||
{
|
||||
if (!isset($this->calculationBase)) {
|
||||
$highestValue = max(
|
||||
array_map(
|
||||
function ($g) { return $g->getValue(); },
|
||||
array_merge($this->displayData, $this->forecastData)
|
||||
)
|
||||
);
|
||||
|
||||
$this->calculationBase = 1;//$this->getRequest()->getParam('calculationBase', 1);
|
||||
while (log($highestValue, $this->calculationBase) > 100) {
|
||||
$this->calculationBase += 0.01;
|
||||
}
|
||||
|
||||
/*$this->addElement(
|
||||
'hidden',
|
||||
'calculationBase',
|
||||
array(
|
||||
'value' => $this->calculationBase
|
||||
)
|
||||
);*/
|
||||
}
|
||||
|
||||
return intval($this->circleDiameter * (log($eventCount, $this->calculationBase) / 100));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an extrapolated event count for the given event group
|
||||
*
|
||||
* @param TimeEntry $eventGroup The event group for which to return an extrapolated event count
|
||||
* @param int $offset The amount of intervals to consider for the extrapolation
|
||||
* @return int
|
||||
*/
|
||||
private function extrapolateEventCount(TimeEntry $eventGroup, $offset)
|
||||
{
|
||||
$start = $eventGroup->getDateTime();
|
||||
$end = clone $start;
|
||||
|
||||
for ($i = 0; $i < $offset; $i++) {
|
||||
$end->sub($this->range->getInterval());
|
||||
}
|
||||
|
||||
$eventCount = 0;
|
||||
foreach ($this->displayData as $group) {
|
||||
if ($group->getName() === $eventGroup->getName() &&
|
||||
$group->getDateTime() <= $start && $group->getDateTime() > $end) {
|
||||
$eventCount += $group->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
$extrapolatedCount = (int) $eventCount / $offset;
|
||||
return $extrapolatedCount > $eventGroup->getValue() ? $extrapolatedCount : $eventGroup->getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a random generated CSS color hex code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getRandomCssColor()
|
||||
{
|
||||
return '#' . str_pad(dechex(rand(256,16777215)), 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an appropriate datetime format string for the current interval
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getIntervalFormat()
|
||||
{
|
||||
$interval = $this->range->getInterval();
|
||||
|
||||
if ($interval->h == 4) {
|
||||
return $this->getDateFormat() . ' ' . $this->getTimeFormat();
|
||||
} elseif ($interval->d == 1) {
|
||||
return $this->getDateFormat();
|
||||
} elseif ($interval->d == 7) {
|
||||
return '\W\e\ek #W \of Y';
|
||||
} elseif ($interval->m == 1) {
|
||||
return 'F Y';
|
||||
} else { // $interval->y == 1
|
||||
return 'Y';
|
||||
}
|
||||
}
|
||||
|
||||
public function setConfiguration($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function getConfiguration()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application's global configuration or an empty one
|
||||
*
|
||||
* @return Zend_Config
|
||||
*/
|
||||
private function getGlobalConfiguration()
|
||||
{
|
||||
$config = $this->getConfiguration();
|
||||
$global = $config->global;
|
||||
|
||||
if ($global === null) {
|
||||
$global = new Zend_Config(array());
|
||||
}
|
||||
|
||||
return $global;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's preferred time format or the application's default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getTimeFormat()
|
||||
{
|
||||
return 'g:i A';
|
||||
$globalConfig = $this->getGlobalConfiguration();
|
||||
$preferences = $this->getUserPreferences();
|
||||
return $preferences->get('app.timeFormat', $globalConfig->get('timeFormat', 'g:i A'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's preferred date format or the application's default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getDateFormat()
|
||||
{
|
||||
return 'd/m/Y';
|
||||
$globalConfig = $this->getGlobalConfiguration();
|
||||
$preferences = $this->getUserPreferences();
|
||||
return $preferences->get('app.dateFormat', $globalConfig->get('dateFormat', 'd/m/Y'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,29 +1,5 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga Web 2.
|
||||
*
|
||||
* Icinga Web 2 - 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\Timeline;
|
||||
|
@ -45,35 +21,35 @@ class TimeRange implements Iterator
|
|||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
private $start;
|
||||
protected $start;
|
||||
|
||||
/**
|
||||
* The end of this time range
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
private $end;
|
||||
protected $end;
|
||||
|
||||
/**
|
||||
* The interval by which this time range is split
|
||||
*
|
||||
* @var DateInterval
|
||||
*/
|
||||
private $interval;
|
||||
protected $interval;
|
||||
|
||||
/**
|
||||
* The current date in the iteration
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
private $current;
|
||||
protected $current;
|
||||
|
||||
/**
|
||||
* Whether the date iteration is negative
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $negative;
|
||||
protected $negative;
|
||||
|
||||
/**
|
||||
* Initialize a new time range
|
||||
|
@ -87,6 +63,7 @@ class TimeRange implements Iterator
|
|||
$this->interval = $interval;
|
||||
$this->start = $start;
|
||||
$this->end = $end;
|
||||
$this->negative = $this->start > $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,6 +116,24 @@ class TimeRange implements Iterator
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given time is within this range of time
|
||||
*
|
||||
* @param int|DateTime $time The timestamp or date and time to check
|
||||
*/
|
||||
public function validateTime($time)
|
||||
{
|
||||
if ($time instanceof DateTime) {
|
||||
$dateTime = $time;
|
||||
} else {
|
||||
$dateTime = new DateTime();
|
||||
$dateTime->setTimestamp($time);
|
||||
}
|
||||
|
||||
return ($this->negative && ($dateTime <= $this->start && $dateTime >= $this->end)) ||
|
||||
(!$this->negative && ($dateTime >= $this->start && $dateTime <= $this->end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate timeframe for the given timeframe start
|
||||
*
|
||||
|
@ -148,7 +143,7 @@ class TimeRange implements Iterator
|
|||
public function getTimeframe($time)
|
||||
{
|
||||
if ($time instanceof DateTime) {
|
||||
$startTime = $time;
|
||||
$startTime = clone $time;
|
||||
} else {
|
||||
$startTime = new DateTime();
|
||||
$startTime->setTimestamp($time);
|
||||
|
@ -174,7 +169,7 @@ class TimeRange implements Iterator
|
|||
* @param DateTime $end The end of the timeframe
|
||||
* @return StdClass
|
||||
*/
|
||||
private function buildTimeframe(DateTime $start, DateTime $end)
|
||||
protected function buildTimeframe(DateTime $start, DateTime $end)
|
||||
{
|
||||
$timeframe = new StdClass();
|
||||
$timeframe->start = $start;
|
||||
|
@ -188,7 +183,6 @@ class TimeRange implements Iterator
|
|||
public function rewind()
|
||||
{
|
||||
$this->current = clone $this->start;
|
||||
$this->negative = $this->start > $this->end;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,47 +1,38 @@
|
|||
<?php
|
||||
// {{{ICINGA_LICENSE_HEADER}}}
|
||||
/**
|
||||
* This file is part of Icinga Web 2.
|
||||
*
|
||||
* Icinga Web 2 - 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\Web\Hook;
|
||||
|
||||
use \Zend_Controller_Request_Abstract;
|
||||
use Icinga\Module\Monitoring\Timeline\TimeRange;
|
||||
|
||||
/**
|
||||
* Base class for TimeEntry providers
|
||||
* Base class for TimeLine providers
|
||||
*/
|
||||
abstract class TimelineProvider
|
||||
{
|
||||
/**
|
||||
* Return a set of TimeEntry objects for the given range of time
|
||||
* Return the names by which to group entries
|
||||
*
|
||||
* @param TimeRange $range The range of time for which to fetch entries
|
||||
* @param Zend_Controller_Request_Abstract $request The current request
|
||||
* @return array
|
||||
* @return array An array with the names as keys and their attribute-lists as values
|
||||
*/
|
||||
abstract public function fetchTimeEntries(TimeRange $range, Zend_Controller_Request_Abstract $request);
|
||||
abstract public function getIdentifiers();
|
||||
|
||||
/**
|
||||
* Return the visible entries supposed to be shown on the timeline
|
||||
*
|
||||
* @param TimeRange $range The range of time for which to fetch entries
|
||||
*
|
||||
* @return array The entries to display on the timeline
|
||||
*/
|
||||
abstract public function fetchEntries(TimeRange $range);
|
||||
|
||||
/**
|
||||
* Return the entries supposed to be used to calculate forecasts
|
||||
*
|
||||
* @param TimeRange $range The range of time for which to fetch forecasts
|
||||
*
|
||||
* @return array The entries to calculate forecasts with
|
||||
*/
|
||||
abstract public function fetchForecasts(TimeRange $range);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue