Implement event history detail view

refs #3191
This commit is contained in:
Alexander A. Klimov 2017-12-06 17:43:42 +01:00 committed by Eric Lippmann
parent 7e5f5405aa
commit 196cdbe4af
37 changed files with 1019 additions and 14 deletions

View File

@ -0,0 +1,542 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Controllers;
use DateTime;
use DateTimeZone;
use InvalidArgumentException;
use Icinga\Data\Queryable;
use Icinga\Date\DateFormatter;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Util\TimezoneDetect;
use Icinga\Web\Url;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Web\Widget\Tabextension\MenuAction;
use Icinga\Web\Widget\Tabextension\OutputFormat;
class EventController extends Controller
{
/**
* @var string[]
*/
protected $dataViewsByType = array(
'notify' => 'notificationevent',
'comment' => 'commentevent',
'comment_deleted' => 'commentevent',
'ack' => 'commentevent',
'ack_deleted' => 'commentevent',
'dt_comment' => 'commentevent',
'dt_comment_deleted' => 'commentevent',
'flapping' => 'flappingevent',
'flapping_deleted' => 'flappingevent',
'hard_state' => 'statechangeevent',
'soft_state' => 'statechangeevent',
'dt_start' => 'downtimeevent',
'dt_end' => 'downtimeevent'
);
/**
* Cache for {@link time()}
*
* @var DateTimeZone
*/
protected $timeZone;
public function showAction()
{
$type = $this->params->shiftRequired('type');
$id = $this->params->shiftRequired('id');
if (! isset($this->dataViewsByType[$type])
|| $this->applyRestriction(
'monitoring/filter/objects',
$this->backend->select()->from('eventhistory', array('id'))->where('id', $id)
)->fetchRow() === false
) {
$this->httpNotFound($this->translate('Event not found'));
}
$event = $this->query($type, $id)->fetchRow();
if ($event === false) {
$this->httpNotFound($this->translate('Event not found'));
}
$this->view->object = $object = $event->service_description === null
? new Host($this->backend, $event->host_name)
: new Service($this->backend, $event->host_name, $event->service_description);
$object->fetch();
list($icon, $label) = $this->getIconAndLabel($type);
$this->view->details = array_merge(
array(array($this->view->escape($this->translate('Type')), $label)),
$this->getDetails($type, $event)
);
$this->getTabs()
->add('event', array(
'title' => $label,
'label' => $label,
'icon' => $icon,
'url' => Url::fromRequest(),
'active' => true
))
->extend(new OutputFormat())
->extend(new DashboardAction())
->extend(new MenuAction());
}
/**
* Return translated and escaped 'Yes' if the given condition is true, 'No' otherwise, 'N/A' if NULL
*
* @param bool|null $condition
*
* @return string
*/
protected function yesOrNo($condition)
{
if ($condition === null) {
return $this->view->escape($this->translate('N/A'));
}
return $this->view->escape($condition ? $this->translate('Yes') : $this->translate('No'));
}
/**
* Render the given timestamp as human readable HTML in the user agent's timezone or 'N/A' if NULL
*
* @param int|null $stamp
*
* @return string
*/
protected function time($stamp)
{
if ($stamp === null) {
return $this->view->escape($this->translate('N/A'));
}
if ($this->timeZone === null) {
$timezoneDetect = new TimezoneDetect();
$this->timeZone = new DateTimeZone(
$timezoneDetect->success() ? $timezoneDetect->getTimezoneName() : date_default_timezone_get()
);
}
return $this->view->escape(
DateTime::createFromFormat('U', $stamp)->setTimezone($this->timeZone)->format('Y-m-d H:i:s')
);
}
/**
* Render the given duration in seconds as human readable HTML or 'N/A' if NULL
*
* @param int|null $seconds
*
* @return string
*/
protected function duration($seconds)
{
return $this->view->escape(
$seconds === null ? $this->translate('N/A') : DateFormatter::formatDuration($seconds)
);
}
/**
* Render the given percent number as human readable HTML or 'N/A' if NULL
*
* @param float|null $percent
*
* @return string
*/
protected function percent($percent)
{
return $this->view->escape(
$percent === null ? $this->translate('N/A') : sprintf($this->translate('%.2f%%'), $percent)
);
}
/**
* Render the given comment message as HTML or 'N/A' if NULL
*
* @param string|null $message
*
* @return string
*/
protected function comment($message)
{
return $this->view->nl2br($this->view->createTicketLinks($this->view->escapeComment($message)));
}
/**
* Render a link to the given contact or 'N/A' if NULL
*
* @param string|null $name
*
* @return string
*/
protected function contact($name)
{
return $name === null
? $this->view->escape($this->translate('N/A'))
: $this->view->qlink($name, Url::fromPath('monitoring/show/contact', array('contact_name' => $name)));
}
/**
* Render the given monitored object state as human readable HTML or 'N/A' if NULL
*
* @param bool $isService
* @param int|null $state
*
* @return string
*/
protected function state($isService, $state)
{
if ($state === null) {
return $this->view->escape($this->translate('N/A'));
}
try {
$stateText = $isService
? Service::getStateText($state, true)
: Host::getStateText($state, true);
} catch (InvalidArgumentException $e) {
return $this->view->escape($this->translate('N/A'));
}
return '<span class="badge state-' . ($isService ? Service::getStateText($state) : Host::getStateText($state))
. '">&nbsp;</span><span class="state-label">' . $this->view->escape($stateText) . '</span>';
}
/**
* Render the given plugin output as human readable HTML
*
* @param string $output
*
* @return string
*/
protected function pluginOutput($output)
{
return $this->view->getHelper('PluginOutput')->pluginOutput($output);
}
/**
* Return the icon and the label for the given event type
*
* @param string $eventType
*
* @return string[]
*/
protected function getIconAndLabel($eventType)
{
switch ($eventType) {
case 'notify':
return array('bell', $this->translate('Notification', 'tooltip'));
case 'comment':
return array('comment-empty', $this->translate('Comment', 'tooltip'));
case 'comment_deleted':
return array('cancel', $this->translate('Comment removed', 'tooltip'));
case 'ack':
return array('ok', $this->translate('Acknowledged', 'tooltip'));
case 'ack_deleted':
return array('ok', $this->translate('Acknowledgement removed', 'tooltip'));
case 'dt_comment':
return array('plug', $this->translate('Downtime scheduled', 'tooltip'));
case 'dt_comment_deleted':
return array('plug', $this->translate('Downtime removed', 'tooltip'));
case 'flapping':
return array('flapping', $this->translate('Flapping started', 'tooltip'));
case 'flapping_deleted':
return array('flapping', $this->translate('Flapping stopped', 'tooltip'));
case 'hard_state':
return array('warning-empty', $this->translate('Hard state change'));
case 'soft_state':
return array('spinner', $this->translate('Soft state change'));
case 'dt_start':
return array('plug', $this->translate('Downtime started', 'tooltip'));
case 'dt_end':
return array('plug', $this->translate('Downtime ended', 'tooltip'));
}
}
/**
* Return a query for the given event ID of the given type
*
* @param string $type
* @param int $id
*
* @return Queryable
*/
protected function query($type, $id)
{
switch ($this->dataViewsByType[$type]) {
case 'downtimeevent':
return $this->backend->select()
->from('downtimeevent', array(
'entry_time' => 'downtimeevent_entry_time',
'author_name' => 'downtimeevent_author_name',
'comment_data' => 'downtimeevent_comment_data',
'is_fixed' => 'downtimeevent_is_fixed',
'scheduled_start_time' => 'downtimeevent_scheduled_start_time',
'scheduled_end_time' => 'downtimeevent_scheduled_end_time',
'was_started' => 'downtimeevent_was_started',
'actual_start_time' => 'downtimeevent_actual_start_time',
'actual_end_time' => 'downtimeevent_actual_end_time',
'was_cancelled' => 'downtimeevent_was_cancelled',
'is_in_effect' => 'downtimeevent_is_in_effect',
'trigger_time' => 'downtimeevent_trigger_time',
'host_name',
'service_description'
))
->where('downtimeevent_id', $id);
case 'commentevent':
return $this->backend->select()
->from('commentevent', array(
'entry_type' => 'commentevent_entry_type',
'comment_time' => 'commentevent_comment_time',
'author_name' => 'commentevent_author_name',
'comment_data' => 'commentevent_comment_data',
'is_persistent' => 'commentevent_is_persistent',
'comment_source' => 'commentevent_comment_source',
'expires' => 'commentevent_expires',
'expiration_time' => 'commentevent_expiration_time',
'deletion_time' => 'commentevent_deletion_time',
'host_name',
'service_description'
))
->where('commentevent_id', $id);
case 'flappingevent':
return $this->backend->select()
->from('flappingevent', array(
'event_time' => 'flappingevent_event_time',
'reason_type' => 'flappingevent_reason_type',
'percent_state_change' => 'flappingevent_percent_state_change',
'low_threshold' => 'flappingevent_low_threshold',
'high_threshold' => 'flappingevent_high_threshold',
'host_name',
'service_description'
))
->where('flappingevent_id', $id)
->where('flappingevent_event_type', $type);
case 'notificationevent':
return $this->backend->select()
->from('notificationevent', array(
'notification_reason' => 'notificationevent_reason',
'start_time' => 'notificationevent_start_time',
'end_time' => 'notificationevent_end_time',
'state' => 'notificationevent_state',
'output' => 'notificationevent_output',
'long_output' => 'notificationevent_long_output',
'escalated' => 'notificationevent_escalated',
'contacts_notified' => 'notificationevent_contacts_notified',
'host_name',
'service_description'
))
->where('notificationevent_id', $id);
case 'statechangeevent':
return $this->backend->select()
->from('statechangeevent', array(
'state_time' => 'statechangeevent_state_time',
'state' => 'statechangeevent_state',
'current_check_attempt' => 'statechangeevent_current_check_attempt',
'max_check_attempts' => 'statechangeevent_max_check_attempts',
'last_state' => 'statechangeevent_last_state',
'last_hard_state' => 'statechangeevent_last_hard_state',
'output' => 'statechangeevent_output',
'long_output' => 'statechangeevent_long_output',
'host_name',
'service_description'
))
->where('statechangeevent_id', $id)
->where('statechangeevent_state_change', 1)
->where('statechangeevent_state_type', $type);
}
}
/**
* Return the given event's data prepared for a name-value table
*
* @param string $type
* @param \stdClass $event
*
* @return string[][]
*/
protected function getDetails($type, $event)
{
switch ($type) {
case 'dt_start':
case 'dt_end':
$details = array(array(
array($this->translate('Entry time'), $this->time($event->entry_time)),
array($this->translate('Is fixed'), $this->yesOrNo($event->is_fixed)),
array($this->translate('Is in effect'), $this->yesOrNo($event->is_in_effect)),
array($this->translate('Was started'), $this->yesOrNo($event->was_started))
));
if ($type === 'dt_end') {
$details[] = array(
array($this->translate('Was cancelled'), $this->yesOrNo($event->was_cancelled))
);
}
$details[] = array(
array($this->translate('Trigger time'), $this->time($event->trigger_time)),
array($this->translate('Scheduled start time'), $this->time($event->scheduled_start_time)),
array($this->translate('Actual start time'), $this->time($event->actual_start_time)),
array($this->translate('Scheduled end time'), $this->time($event->scheduled_end_time))
);
if ($type === 'dt_end') {
$details[] = array(
array($this->translate('Actual end time'), $this->time($event->actual_end_time)))
;
}
$details[] = array(
array($this->translate('Author'), $this->contact($event->author_name)),
array($this->translate('Comment'), $this->comment($event->comment_data))
);
return call_user_func_array('array_merge', $details);
case 'comment':
case 'comment_deleted':
case 'ack':
case 'ack_deleted':
case 'dt_comment':
case 'dt_comment_deleted':
switch ($event->entry_type) {
case 'comment':
$entryType = $this->translate('User comment');
break;
case 'downtime':
$entryType = $this->translate('Scheduled downtime');
break;
case 'flapping':
$entryType = $this->translate('Flapping');
break;
case 'ack':
$entryType = $this->translate('Acknowledgement');
break;
default:
$entryType = $this->translate('N/A');
}
switch ($event->comment_source) {
case 'icinga':
$commentSource = $this->translate('Icinga');
break;
case 'user':
$commentSource = $this->translate('User');
break;
default:
$commentSource = $this->translate('N/A');
}
return array(
array($this->translate('Time'), $this->time($event->comment_time)),
array($this->translate('Source'), $this->view->escape($commentSource)),
array($this->translate('Entry type'), $this->view->escape($entryType)),
array($this->translate('Author'), $this->contact($event->author_name)),
array($this->translate('Is persistent'), $this->yesOrNo($event->is_persistent)),
array($this->translate('Expires'), $this->yesOrNo($event->expires)),
array($this->translate('Expiration time'), $this->time($event->expiration_time)),
array($this->translate('Deletion time'), $this->time($event->deletion_time)),
array($this->translate('Message'), $this->comment($event->comment_data))
);
case 'flapping':
case 'flapping_deleted':
switch ($event->reason_type) {
case 'stopped':
$reasonType = $this->translate('Flapping stopped normally');
break;
case 'disabled':
$reasonType = $this->translate('Flapping was disabled');
break;
default:
$reasonType = $this->translate('N/A');
}
return array(
array($this->translate('Event time'), $this->time($event->event_time)),
array($this->translate('Reason'), $this->view->escape($reasonType)),
array($this->translate('State change'), $this->percent($event->percent_state_change)),
array($this->translate('Low threshold'), $this->percent($event->low_threshold)),
array($this->translate('High threshold'), $this->percent($event->high_threshold))
);
case 'notify':
switch ($event->notification_reason) {
case 'normal_notification':
$notificationReason = $this->translate('Normal notification');
break;
case 'ack':
$notificationReason = $this->translate('Problem acknowledgement');
break;
case 'flapping_started':
$notificationReason = $this->translate('Flapping started');
break;
case 'flapping_stopped':
$notificationReason = $this->translate('Flapping stopped');
break;
case 'flapping_disabled':
$notificationReason = $this->translate('Flapping was disabled');
break;
case 'dt_start':
$notificationReason = $this->translate('Downtime started');
break;
case 'dt_end':
$notificationReason = $this->translate('Downtime ended');
break;
case 'dt_cancel':
$notificationReason = $this->translate('Downtime was cancelled');
break;
case 'custom_notification':
$notificationReason = $this->translate('Custom notification');
break;
default:
$notificationReason = $this->translate('N/A');
}
$details = array(
array($this->translate('Start time'), $this->time($event->start_time)),
array($this->translate('End time'), $this->time($event->end_time)),
array($this->translate('Reason'), $this->view->escape($notificationReason)),
array(
$this->translate('State'),
$this->state($event->service_description !== null, $event->state)
),
array($this->translate('Escalated'), $this->yesOrNo($event->escalated)),
array($this->translate('Contacts notified'), (int) $event->contacts_notified),
array(
$this->translate('Output'),
$this->pluginOutput($event->output) . $this->pluginOutput($event->long_output)
)
);
return $details;
case 'hard_state':
case 'soft_state':
$isService = $event->service_description !== null;
$details = array(
array($this->translate('State time'), $this->time($event->state_time)),
array($this->translate('State'), $this->state($isService, $event->state)),
array($this->translate('Check attempt'), $this->view->escape(sprintf(
$this->translate('%d of %d'),
(int) $event->current_check_attempt,
(int) $event->max_check_attempts
))),
array($this->translate('Last state'), $this->state($isService, $event->last_state)),
array($this->translate('Last hard state'), $this->state($isService, $event->last_hard_state)),
array(
$this->translate('Output'),
$this->pluginOutput($event->output) . $this->pluginOutput($event->long_output)
)
);
return $details;
}
}
}

View File

@ -547,6 +547,7 @@ class ListController extends Controller
);
$query = $this->backend->select()->from('eventhistory', array(
'id',
'host_name',
'host_display_name',
'service_description',

View File

@ -0,0 +1,28 @@
<?php
use Icinga\Module\Monitoring\Object\Service;
/** @var string[][] $details */
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
/** @var \Icinga\Web\View $this */
?>
<div class="controls">
<?php
if (! $this->compact) {
echo $this->tabs;
}
echo $object instanceof Service
? '<h2>' . $this->translate('Current Service State') . '</h2>' . $this->render('partials/object/service-header.phtml')
: '<h2>' . $this->translate('Current Host State') . '</h2>' . $this->render('partials/object/host-header.phtml');
?>
</div>
<div class="content">
<h2><?= $this->escape($this->translate('Event Details')) ?></h2>
<table class="event-details name-value-table" data-base-target="_next">
<?php
foreach ($details as $detail) {
echo '<tr><th>' . $this->escape($detail[0]) . '</th><td>' . $detail[1] . '</td></tr>';
}
?>
</table>
</div>

View File

@ -1,6 +1,8 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Web\Url;
use Icinga\Web\UrlParams;
function contactsLink($match, $view) {
$links = array();
@ -35,8 +37,9 @@ $history->limit($limit * $page);
$dateFormat = $this->translate('%A, %B %e, %Y', 'date.verbose');
$lastDate = null;
$flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
$rowAction = Url::fromPath('monitoring/event/show');
?>
<table class="state-table" data-base-target="_next"<?php if (isset($tableCssClass)): ?> class="<?=$tableCssClass ?>"<?php endif ?>>
<table class="table-row-selectable state-table" data-base-target="_next"<?php if (isset($tableCssClass)): ?> class="<?=$tableCssClass ?>"<?php endif ?>>
<tbody>
<?php foreach ($history->peekAhead() as $event):
$icon = '';
@ -44,6 +47,11 @@ $flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
$isService = isset($event->service_description);
$msg = $event->output;
$stateName = 'no-state';
$rowAction->setParams(new UrlParams())->addParams(array(
'type' => $event->type,
'id' => $event->id
));
switch ($event->type) {
case 'notify':
$icon = 'bell';
@ -134,7 +142,7 @@ $flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
<th colspan="2"><?= $currentDate ?></th>
</tr>
<?php endif ?>
<tr>
<tr href="<?= $rowAction ?>">
<td class="state-col state-<?= $stateName ?>">
<?php if ($history->getIteratorPosition() % $limit === 0): ?>
<a id="page-<?= $history->getIteratorPosition() / $limit + 1 ?>"></a>
@ -163,7 +171,6 @@ $flappingMsg = $this->translate('Flapping with a %.2f%% state change rate');
'service' => $event->service_description
),
array(
'class' => 'rowaction',
'title' => sprintf(
$this->translate('Show detailed information for service %s on host %s'),
$event->service_display_name,

View File

@ -1,6 +1,11 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Web\Url;
/** @var Host $object */
$url = Url::fromRequest();
$linkHostName = ! ($url->getPath() === 'monitoring/host/show' && $url->getParam('host') === $object->host_name);
?>
<table class="state-table host-detail-state">
<tr>
@ -15,10 +20,20 @@ use Icinga\Module\Monitoring\Object\Host;
</td>
<td>
<?= $this->iconImage()->host($object) ?>
<?php
if ($linkHostName) {
echo '<a href="' . Url::fromPath('monitoring/host/show', array('host' => $object->host_name)) . '">';
}
?>
<span class="selectable"><?= $this->escape($object->host_display_name) ?></span>
<?php if ($object->host_display_name !== $object->host_name): ?>
<span class="selectable host-meta">&#40;<?= $this->escape($object->host_name) ?>&#41;</span>
<?php endif ?>
<?php
if ($linkHostName) {
echo '</a>';
}
?>
<?php if ($object->host_alias !== $object->host_display_name && $object->host_alias !== $object->host_name): ?>
<div class="selectable host-meta">
<?= $this->escape($this->translate('Alias', 'host') . ': ' . $object->host_alias) ?>

View File

@ -1,7 +1,12 @@
<?php
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
use Icinga\Web\Url;
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
$url = Url::fromRequest();
$linkServiceName = ! ($url->getPath() === 'monitoring/service/show' && $url->getParam('service') === $object->service_description);
?>
<table class="state-table service-detail-state">
<tr>
@ -16,10 +21,12 @@ use Icinga\Module\Monitoring\Object\Service;
</td>
<td>
<?= $this->iconImage()->host($object) ?>
<a href="<?= Url::fromPath('monitoring/host/show', array('host' => $object->host_name)) ?>">
<span class="selectable"><?= $this->escape($object->host_display_name) ?></span>
<?php if ($object->host_display_name !== $object->host_name): ?>
<span class="selectable host-meta">&#40;<?= $this->escape($object->host_name) ?>&#41;</span>
<?php endif ?>
</a>
<?= $this->hostFlags($object) ?>
<?php if ($object->host_address6 && $object->host_address6 !== $object->host_name): ?>
<div class="selectable host-meta" title="<?= $this->translate('IPv6 address') ?>">
@ -45,10 +52,24 @@ use Icinga\Module\Monitoring\Object\Service;
</td>
<td>
<?= $this->iconImage()->service($object) ?>
<?= $this->translate('Service') ?>&#58; <span class="selectable"><?= $this->escape($object->service_display_name) ?></span>
<?= $this->translate('Service') ?>&#58;
<?php
if ($linkServiceName) {
echo '<a href="' . Url::fromPath('monitoring/service/show', array(
'host' => $object->host_name,
'service' => $object->service_description
)) . '">';
}
?>
<span class="selectable"><?= $this->escape($object->service_display_name) ?></span>
<?php if ($object->service_display_name !== $object->service_description): ?>
<span class="selectable service-meta">&#40;<?= $this->escape($object->service_description) ?>&#41;</span>
<?php endif ?>
<?php
if ($linkServiceName) {
echo '</a>';
}
?>
<?= $this->serviceFlags($object) ?>
</td>
</tr>

View File

@ -17,6 +17,7 @@ class CommentdeletionhistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'commenthistory' => array(
'id' => 'cdh.id',
'object_type' => 'cdh.object_type'
),
'history' => array(

View File

@ -0,0 +1,39 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host and service comment entry and deletion events
*/
class CommenteventQuery extends IdoQuery
{
protected $columnMap = array(
'commentevent' => array(
'commentevent_id' => 'ch.commenthistory_id',
'commentevent_entry_type' => "(CASE ch.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' ELSE NULL END)",
'commentevent_comment_time' => 'UNIX_TIMESTAMP(ch.comment_time)',
'commentevent_author_name' => 'ch.author_name',
'commentevent_comment_data' => 'ch.comment_data',
'commentevent_is_persistent' => 'ch.is_persistent',
'commentevent_comment_source' => "(CASE ch.comment_source WHEN 0 THEN 'icinga' WHEN 1 THEN 'user' ELSE NULL END)",
'commentevent_expires' => 'ch.expires',
'commentevent_expiration_time' => 'UNIX_TIMESTAMP(ch.expiration_time)',
'commentevent_deletion_time' => 'UNIX_TIMESTAMP(ch.deletion_time)'
),
'object' => array(
'host_name' => 'o.name1',
'service_description' => 'o.name2'
)
);
protected function joinBaseTables()
{
$this->select()
->from(array('ch' => $this->prefix . 'commenthistory'), array())
->join(array('o' => $this->prefix . 'objects'), 'ch.object_id = o.object_id', array());
$this->joinedVirtualTables['commentevent'] = true;
$this->joinedVirtualTables['object'] = true;
}
}

View File

@ -17,6 +17,7 @@ class CommenthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'commenthistory' => array(
'id' => 'ch.id',
'object_type' => 'ch.object_type'
),
'history' => array(

View File

@ -17,6 +17,7 @@ class DowntimeendhistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'downtimehistory' => array(
'id' => 'deh.id',
'object_type' => 'deh.object_type'
),
'history' => array(

View File

@ -0,0 +1,42 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host and service downtime events
*/
class DowntimeeventQuery extends IdoQuery
{
protected $columnMap = array(
'downtimeevent' => array(
'downtimeevent_id' => 'dth.downtimehistory_id',
'downtimeevent_entry_time' => 'UNIX_TIMESTAMP(dth.entry_time)',
'downtimeevent_author_name' => 'dth.author_name',
'downtimeevent_comment_data' => 'dth.comment_data',
'downtimeevent_is_fixed' => 'dth.is_fixed',
'downtimeevent_scheduled_start_time' => 'UNIX_TIMESTAMP(dth.scheduled_start_time)',
'downtimeevent_scheduled_end_time' => 'UNIX_TIMESTAMP(dth.scheduled_end_time)',
'downtimeevent_was_started' => 'dth.was_started',
'downtimeevent_actual_start_time' => 'UNIX_TIMESTAMP(dth.actual_start_time)',
'downtimeevent_actual_end_time' => 'UNIX_TIMESTAMP(dth.actual_end_time)',
'downtimeevent_was_cancelled' => 'dth.was_cancelled',
'downtimeevent_is_in_effect' => 'dth.is_in_effect',
'downtimeevent_trigger_time' => 'UNIX_TIMESTAMP(dth.trigger_time)'
),
'object' => array(
'host_name' => 'o.name1',
'service_description' => 'o.name2'
)
);
protected function joinBaseTables()
{
$this->select()
->from(array('dth' => $this->prefix . 'downtimehistory'), array())
->join(array('o' => $this->prefix . 'objects'), 'dth.object_id = o.object_id', array());
$this->joinedVirtualTables['downtimeevent'] = true;
$this->joinedVirtualTables['object'] = true;
}
}

View File

@ -17,6 +17,7 @@ class DowntimestarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'downtimehistory' => array(
'id' => 'dsh.id',
'object_type' => 'dsh.object_type'
),
'history' => array(

View File

@ -28,6 +28,7 @@ class EventhistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'eventhistory' => array(
'id' => 'eh.id',
'cnt_notification' => "SUM(CASE eh.type WHEN 'notify' THEN 1 ELSE 0 END)",
'cnt_hard_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
'cnt_soft_state' => "SUM(CASE eh.type WHEN 'hard_state' THEN 1 ELSE 0 END)",
@ -51,6 +52,7 @@ class EventhistoryQuery extends IdoQuery
protected function joinBaseTables()
{
$columns = array(
'id',
'timestamp',
'output',
'type',

View File

@ -0,0 +1,36 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host and service flapping events
*/
class FlappingeventQuery extends IdoQuery
{
protected $columnMap = array(
'flappingevent' => array(
'flappingevent_id' => 'fh.flappinghistory_id',
'flappingevent_event_time' => 'UNIX_TIMESTAMP(fh.event_time)',
'flappingevent_event_type' => "(CASE fh.event_type WHEN 1000 THEN 'flapping' WHEN 1001 THEN 'flapping_deleted' ELSE NULL END)",
'flappingevent_reason_type' => "(CASE fh.reason_type WHEN 1 THEN 'stopped' WHEN 2 THEN 'disabled' ELSE NULL END)",
'flappingevent_percent_state_change' => 'fh.percent_state_change',
'flappingevent_low_threshold' => 'fh.low_threshold',
'flappingevent_high_threshold' => 'fh.high_threshold'
),
'object' => array(
'host_name' => 'o.name1',
'service_description' => 'o.name2'
)
);
protected function joinBaseTables()
{
$this->select()
->from(array('fh' => $this->prefix . 'flappinghistory'), array())
->join(array('o' => $this->prefix . 'objects'), 'fh.object_id = o.object_id', array());
$this->joinedVirtualTables['flappingevent'] = true;
$this->joinedVirtualTables['object'] = true;
}
}

View File

@ -17,6 +17,7 @@ class FlappingstarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'flappinghistory' => array(
'id' => 'fsh.id',
'object_type' => 'fsh.object_type'
),
'history' => array(

View File

@ -28,6 +28,7 @@ class HostcommenthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'commenthistory' => array(
'id' => 'hch.commenthistory_id',
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'object_id' => 'hch.object_id',

View File

@ -28,6 +28,7 @@ class HostdowntimestarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'downtimehistory' => array(
'id' => 'hdh.downtimehistory_id',
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'object_id' => 'hdh.object_id',

View File

@ -28,6 +28,7 @@ class HostflappingstarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'flappinghistory' => array(
'id' => 'hfh.flappinghistory_id',
'host_name' => 'ho.name1',
'object_id' => 'hfh.object_id',
'object_type' => '(\'host\')',

View File

@ -27,6 +27,7 @@ class HostnotificationQuery extends IdoQuery
'host_display_name' => 'h.display_name COLLATE latin1_general_ci'
),
'history' => array(
'id' => 'hn.notification_id',
'output' => null,
'state' => 'hn.state',
'timestamp' => 'UNIX_TIMESTAMP(hn.start_time)',

View File

@ -61,6 +61,7 @@ class HoststatehistoryQuery extends IdoQuery
'service_host_name' => 'so.name1'
),
'statehistory' => array(
'id' => 'hh.statehistory_id',
'host' => 'ho.name1 COLLATE latin1_general_ci',
'host_name' => 'ho.name1',
'object_id' => 'hh.object_id',

View File

@ -0,0 +1,52 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host and service notification events
*/
class NotificationeventQuery extends IdoQuery
{
protected $columnMap = array(
'notificationevent' => array(
'notificationevent_id' => 'n.notification_id',
'notificationevent_reason' => <<<EOF
(CASE n.notification_reason
WHEN 0 THEN 'normal_notification'
WHEN 1 THEN 'ack'
WHEN 2 THEN 'flapping_started'
WHEN 3 THEN 'flapping_stopped'
WHEN 4 THEN 'flapping_disabled'
WHEN 5 THEN 'dt_start'
WHEN 6 THEN 'dt_end'
WHEN 7 THEN 'dt_cancel'
WHEN 99 THEN 'custom_notification'
ELSE NULL
END)
EOF
,
'notificationevent_start_time' => 'UNIX_TIMESTAMP(n.start_time)',
'notificationevent_end_time' => 'UNIX_TIMESTAMP(n.end_time)',
'notificationevent_state' => 'n.state',
'notificationevent_output' => 'n.output',
'notificationevent_long_output' => 'n.long_output',
'notificationevent_escalated' => 'n.escalated',
'notificationevent_contacts_notified' => 'n.contacts_notified'
),
'object' => array(
'host_name' => 'o.name1',
'service_description' => 'o.name2'
)
);
protected function joinBaseTables()
{
$this->select()
->from(array('n' => $this->prefix . 'notifications'), array())
->join(array('o' => $this->prefix . 'objects'), 'n.object_id = o.object_id', array());
$this->joinedVirtualTables['notificationevent'] = true;
$this->joinedVirtualTables['object'] = true;
}
}

View File

@ -22,6 +22,7 @@ class NotificationhistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'history' => array(
'id' => 'n.id',
'object_type' => 'n.object_type',
'output' => 'n.output',
'state' => 'n.state',

View File

@ -28,6 +28,7 @@ class ServicecommenthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'commenthistory' => array(
'id' => 'sch.commenthistory_id',
'host' => 'so.name1 COLLATE latin1_general_ci',
'host_name' => 'so.name1',
'object_id' => 'sch.object_id',

View File

@ -28,6 +28,7 @@ class ServicedowntimestarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'downtimehistory' => array(
'id' => 'sdh.downtimehistory_id',
'host' => 'so.name1 COLLATE latin1_general_ci',
'host_name' => 'so.name1',
'object_id' => 'sdh.object_id',

View File

@ -28,6 +28,7 @@ class ServiceflappingstarthistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'flappinghistory' => array(
'id' => 'sfh.flappinghistory_id',
'host_name' => 'so.name1',
'object_id' => 'sfh.object_id',
'object_type' => '(\'service\')',

View File

@ -21,6 +21,7 @@ class ServicenotificationQuery extends IdoQuery
'notification_contact_name' => 'co.name1'
),
'history' => array(
'id' => 'sn.notification_id',
'output' => null,
'state' => 'sn.state',
'timestamp' => 'UNIX_TIMESTAMP(sn.start_time)',

View File

@ -58,6 +58,7 @@ class ServicestatehistoryQuery extends IdoQuery
'service_display_name' => 's.display_name COLLATE latin1_general_ci'
),
'statehistory' => array(
'id' => 'sh.statehistory_id',
'host' => 'so.name1 COLLATE latin1_general_ci',
'host_name' => 'so.name1',
'object_id' => 'sh.object_id',

View File

@ -0,0 +1,40 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
/**
* Query for host and service state change events
*/
class StatechangeeventQuery extends IdoQuery
{
protected $columnMap = array(
'statechangeevent' => array(
'statechangeevent_id' => 'sh.statehistory_id',
'statechangeevent_state_time' => 'UNIX_TIMESTAMP(sh.state_time)',
'statechangeevent_state_change' => 'sh.state_change',
'statechangeevent_state' => 'sh.state',
'statechangeevent_state_type' => "(CASE sh.state_type WHEN 0 THEN 'soft_state' WHEN 1 THEN 'hard_state' ELSE NULL END)",
'statechangeevent_current_check_attempt' => 'sh.current_check_attempt',
'statechangeevent_max_check_attempts' => 'sh.max_check_attempts',
'statechangeevent_last_state' => 'sh.last_state',
'statechangeevent_last_hard_state' => 'sh.last_hard_state',
'statechangeevent_output' => 'sh.output',
'statechangeevent_long_output' => 'sh.long_output'
),
'object' => array(
'host_name' => 'o.name1',
'service_description' => 'o.name2'
)
);
protected function joinBaseTables()
{
$this->select()
->from(array('sh' => $this->prefix . 'statehistory'), array())
->join(array('o' => $this->prefix . 'objects'), 'sh.object_id = o.object_id', array());
$this->joinedVirtualTables['statechangeevent'] = true;
$this->joinedVirtualTables['object'] = true;
}
}

View File

@ -17,6 +17,7 @@ class StatehistoryQuery extends IdoQuery
*/
protected $columnMap = array(
'statehistory' => array(
'id' => 'sth.id',
'object_type' => 'sth.object_type'
),
'history' => array(

View File

@ -0,0 +1,30 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Commentevent extends DataView
{
public function getColumns()
{
return array(
'commentevent_id',
'commentevent_entry_type',
'commentevent_comment_time',
'commentevent_author_name',
'commentevent_comment_data',
'commentevent_is_persistent',
'commentevent_comment_source',
'commentevent_expires',
'commentevent_expiration_time',
'commentevent_deletion_time',
'host_name',
'service_description'
);
}
public function getStaticFilterColumns()
{
return array('commentevent_id');
}
}

View File

@ -0,0 +1,33 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Downtimeevent extends DataView
{
public function getColumns()
{
return array(
'downtimeevent_id',
'downtimeevent_entry_time',
'downtimeevent_author_name',
'downtimeevent_comment_data',
'downtimeevent_is_fixed',
'downtimeevent_scheduled_start_time',
'downtimeevent_scheduled_end_time',
'downtimeevent_was_started',
'downtimeevent_actual_start_time',
'downtimeevent_actual_end_time',
'downtimeevent_was_cancelled',
'downtimeevent_is_in_effect',
'downtimeevent_trigger_time',
'host_name',
'service_description'
);
}
public function getStaticFilterColumns()
{
return array('downtimeevent_id');
}
}

View File

@ -11,6 +11,7 @@ class EventHistory extends DataView
public function getColumns()
{
return array(
'id',
'instance_name',
'cnt_notification',
'cnt_hard_state',

View File

@ -0,0 +1,27 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Flappingevent extends DataView
{
public function getColumns()
{
return array(
'flappingevent_id',
'flappingevent_event_time',
'flappingevent_event_type',
'flappingevent_reason_type',
'flappingevent_percent_state_change',
'flappingevent_low_threshold',
'flappingevent_high_threshold',
'host_name',
'service_description'
);
}
public function getStaticFilterColumns()
{
return array('flappingevent_id');
}
}

View File

@ -0,0 +1,29 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Notificationevent extends DataView
{
public function getColumns()
{
return array(
'notificationevent_id',
'notificationevent_reason',
'notificationevent_start_time',
'notificationevent_end_time',
'notificationevent_state',
'notificationevent_output',
'notificationevent_long_output',
'notificationevent_escalated',
'notificationevent_contacts_notified',
'host_name',
'service_description'
);
}
public function getStaticFilterColumns()
{
return array('notificationevent_id');
}
}

View File

@ -0,0 +1,31 @@
<?php
/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */
namespace Icinga\Module\Monitoring\DataView;
class Statechangeevent extends DataView
{
public function getColumns()
{
return array(
'statechangeevent_id',
'statechangeevent_state_time',
'statechangeevent_state_change',
'statechangeevent_state',
'statechangeevent_state_type',
'statechangeevent_current_check_attempt',
'statechangeevent_max_check_attempts',
'statechangeevent_last_state',
'statechangeevent_last_hard_state',
'statechangeevent_output',
'statechangeevent_long_output',
'host_name',
'service_description'
);
}
public function getStaticFilterColumns()
{
return array('statechangeevent_id');
}
}

View File

@ -603,6 +603,7 @@ abstract class MonitoredObject implements Filterable
->from(
'eventhistory',
array(
'id',
'object_type',
'host_name',
'host_display_name',

View File

@ -585,6 +585,17 @@ form.instance-features span.description, form.object-features span.description {
}
}
.event-details {
.badge {
font-size: 0.6em;
margin-right: 0.5em;
}
.state-label {
vertical-align: middle;
}
}
//p.pluginoutput {
// width: 100%;
// white-space: pre-wrap;