Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ignoring a list of notification periods for handled problems #34

Merged
merged 2 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/02-Behavior.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,9 @@ Checks the configured notification_period and handles "out of period" as downtim
This was a behavior of the old Top Level View, and is enabled on convert.

Also see [limitations](90-Limits.md) for this setting.

### Ignoring certain notification periods

Option `ignored_notification_periods`

This notification periods will be ignored for "out of period" checking, see above.
1 change: 1 addition & 0 deletions library/Toplevelview/Legacy/LegacyDbHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ protected function buildTree($root_id, $nodes, &$hosts, &$services, &$hostgroups
// add old default behavior for status
$tree->host_never_unhandled = true;
$tree->notification_periods = true;
$tree->ignored_notification_periods = ['notification_none']; // migration for Director
} elseif ($node->level > $currentLevel) {
// level down
$currentParent = $chain[$node->level - 1];
Expand Down
61 changes: 42 additions & 19 deletions library/Toplevelview/Monitoring/HostgroupQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,31 @@
*/
class HostgroupQuery extends IcingaHostgroupQuery
{
use IgnoredNotificationPeriods;
use Options;

public function __construct($ds, $columns = null, $options = null)
{
$this->setOptions($options);
parent::__construct($ds, $columns);
}

public function init()
{
if (($periods = $this->getOption('ignored_notification_periods')) !== null) {
$this->ignoreNotificationPeriods($periods);
}

$patchedColumnMap = array(
'servicestatus' => array(
'service_notifications_enabled' => 'ss.notifications_enabled',
'service_is_flapping' => 'ss.is_flapping',
'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END',
'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
'service_handled_wo_host' => 'CASE WHEN ss.problem_has_been_acknowledged > 0 THEN 1 ELSE 0 END',
'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
'servicestatus' => array(
'service_notifications_enabled' => 'ss.notifications_enabled',
'service_is_flapping' => 'ss.is_flapping',
'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END',
'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
'service_handled_wo_host' => 'CASE WHEN ss.problem_has_been_acknowledged > 0 THEN 1 ELSE 0 END',
'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
),
'hoststatus' => array(
'hoststatus' => array(
'host_notifications_enabled' => 'hs.notifications_enabled',
'host_is_flapping' => 'hs.is_flapping',
'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE CASE WHEN hs.state_type = 1 THEN hs.current_state ELSE hs.last_hard_state END END',
Expand All @@ -30,7 +43,7 @@ public function init()
),
'servicenotificationperiod' => array(
'service_notification_period' => 'ntpo.name1',
'service_in_notification_period' => 'CASE WHEN s.notification_timeperiod_object_id IS NULL THEN 1 ELSE CASE WHEN ntpr.timeperiod_id IS NOT NULL THEN 1 ELSE 0 END END',
'service_in_notification_period' => 'CASE WHEN ntpo.object_id IS NULL THEN 1 ELSE CASE WHEN ntpr.timeperiod_id IS NOT NULL THEN 1 ELSE 0 END END',
),
);

Expand All @@ -45,24 +58,34 @@ public function init()

protected function joinServicenotificationperiod()
{
$extraJoinCond = '';

if ($this->hasIgnoredNotifications()) {
$extraJoinCond .= $this->db->quoteInto(
' AND ntpo.name1 NOT IN (?)',
$this->getIgnoredNotificationPeriods()
);
}

$this->select->joinLeft(
array('ntp' => $this->prefix . 'timeperiods'),
'ntp.timeperiod_object_id = s.notification_timeperiod_object_id AND ntp.config_type = 1 AND ntp.instance_id = s.instance_id',
array()
['ntp' => $this->prefix . 'timeperiods'],
'ntp.timeperiod_object_id = s.notification_timeperiod_object_id'
. ' AND ntp.config_type = 1 AND ntp.instance_id = s.instance_id',
[]
);
$this->select->joinLeft(
array('ntpo' => $this->prefix . 'objects'),
'ntpo.object_id = s.notification_timeperiod_object_id',
array()
['ntpo' => $this->prefix . 'objects'],
'ntpo.object_id = s.notification_timeperiod_object_id' . $extraJoinCond,
[]
);
$this->select->joinLeft(
array('ntpr' => $this->prefix . 'timeperiod_timeranges'),
'ntpr.timeperiod_id = ntp.timeperiod_id
['ntpr' => $this->prefix . 'timeperiod_timeranges'],
"ntpr.timeperiod_id = ntp.timeperiod_id
AND ntpr.day = DAYOFWEEK(CURRENT_DATE()) - 1
AND ntpr.start_sec <= UNIX_TIMESTAMP() - UNIX_TIMESTAMP(CURRENT_DATE())
AND ntpr.end_sec >= UNIX_TIMESTAMP() - UNIX_TIMESTAMP(CURRENT_DATE())
',
array()
",
[]
);
}
}
11 changes: 3 additions & 8 deletions library/Toplevelview/Monitoring/Hostgroupsummary.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,16 @@ class Hostgroupsummary extends IcingaHostgroupsummary
/**
* @param ConnectionInterface $connection
* @param array|null $columns
* @param array|null $options
* @noinspection PhpMissingParentConstructorInspection
*/
public function __construct(
ConnectionInterface $connection,
array $columns = null,
$notification_periods = false,
$host_never_unhandled = false
$options = null
) {
/** @var MonitoringBackend $connection */
$this->connection = $connection;
$this->query = new HostgroupsummaryQuery(
$connection->getResource(),
$columns,
$notification_periods,
$host_never_unhandled
);
$this->query = new HostgroupsummaryQuery($connection->getResource(), $columns, $options);
}
}
16 changes: 7 additions & 9 deletions library/Toplevelview/Monitoring/HostgroupsummaryQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@
*/
class HostgroupsummaryQuery extends IcingaHostgroupsummaryQuery
{
protected $notification_periods = false;
protected $host_never_unhandled = false;
use Options;

public function __construct($ds, $columns = null, $notification_periods = false, $host_never_unhandled = false)
public function __construct($ds, $columns = null, $options = null)
{
$this->notification_periods = $notification_periods;
$this->host_never_unhandled = $host_never_unhandled;
$this->setOptions($options);
parent::__construct($ds, $columns);
}

public function init()
{
if ($this->notification_periods === true) {
if ($this->getOption('notification_periods') === true) {
$serviceOutDowntime = 'service_notifications_enabled = 1 AND service_in_downtime = 0 AND service_in_notification_period = 1';
$serviceInDowntime = '(service_notifications_enabled = 0 OR service_in_downtime = 1 OR service_in_notification_period = 0)';
} else {
Expand All @@ -35,7 +33,7 @@ public function init()
$hostOutDowntime = 'host_notifications_enabled = 1 AND host_in_downtime = 0';
$hostInDowntime = '(host_notifications_enabled = 0 OR host_in_downtime = 1)';

if ($this->host_never_unhandled === true) {
if ($this->getOption('host_never_unhandled') === true) {
$patchServicesHandled = "(service_handled_wo_host = 1 OR service_is_flapping = 1) AND $serviceOutDowntime";
$patchServicesUnhandled = "service_handled_wo_host = 0 AND service_is_flapping = 0 AND $serviceOutDowntime";
} else {
Expand Down Expand Up @@ -77,7 +75,7 @@ protected function createSubQuery($queryName, $columns = array())
{
if ($queryName === 'Hostgroup') {
// use locally patched query
return new HostgroupQuery($this->ds, $columns);
return new HostgroupQuery($this->ds, $columns, $this->options);
} else {
return parent::createSubQuery($queryName, $columns);
}
Expand Down Expand Up @@ -121,7 +119,7 @@ protected function joinBaseTables()
'service_in_downtime',
);

if ($this->notification_periods === true) {
if ($this->getOption('notification_periods') === true) {
$hostColumns['service_in_notification_period'] = new Zend_Db_Expr('NULL');
$serviceColumns['service_in_notification_period'] = 'service_in_notification_period';
}
Expand Down
49 changes: 49 additions & 0 deletions library/Toplevelview/Monitoring/IgnoredNotificationPeriods.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/* Copyright (C) 2019 Icinga Development Team <info@icinga.com> */

namespace Icinga\Module\Toplevelview\Monitoring;

trait IgnoredNotificationPeriods
{
protected $ignoredNotificationPeriods = [];

public function ignoreNotificationPeriod($name)
{
$this->ignoredNotificationPeriods[$name] = true;
return $this;
}

/**
* @param string|array|iterable $list
*
* @return $this
*/
public function ignoreNotificationPeriods($list)
{
if (is_string($list)) {
/** @var string $list */
$this->ignoredNotificationPeriods[$list] = true;
} else {
foreach ($list as $i) {
$this->ignoredNotificationPeriods[$i] = true;
}
}

return $this;
}

public function getIgnoredNotificationPeriods()
{
return array_keys($this->ignoredNotificationPeriods);
}

public function resetIgnoredNotificationPeriods()
{
$this->ignoredNotificationPeriods = [];
}

public function hasIgnoredNotifications()
{
return ! empty($this->ignoredNotificationPeriods);
}
}
33 changes: 33 additions & 0 deletions library/Toplevelview/Monitoring/Options.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/* Copyright (C) 2019 Icinga Development Team <info@icinga.com> */

namespace Icinga\Module\Toplevelview\Monitoring;

trait Options
{
protected $options = [];

public function getOption($key)
{
if (array_key_exists($key, $this->options)) {
return $this->options[$key];
}

return null;
}

public function setOptions($options, $flush = false)
{
if ($flush) {
$this->options = [];
}

if (! empty($options)) {
foreach ($options as $k => $v) {
$this->options[$k] = $v;
}
}

return $this;
}
}
38 changes: 29 additions & 9 deletions library/Toplevelview/Monitoring/ServicestatusQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@
*/
class ServicestatusQuery extends IcingaServicestatusQuery
{
// TODO: not used in this query
//use IgnoredNotificationPeriods;
//use Options;

public function init()
{
/* TODO: not used in this query
if (($periods = $this->getOption('ignored_notification_periods')) !== null) {
$this->ignoreNotificationPeriods($periods);
}
*/

$patchedColumnMap = array(
'servicestatus' => array(
'service_handled_wo_host' => 'CASE WHEN ss.problem_has_been_acknowledged > 0 THEN 1 ELSE 0 END',
),
'servicenotificationperiod' => array(
'service_notification_period' => 'ntpo.name1',
'service_in_notification_period' => 'CASE WHEN s.notification_timeperiod_object_id IS NULL THEN 1 ELSE CASE WHEN ntpr.timeperiod_id IS NOT NULL THEN 1 ELSE 0 END END',
'service_in_notification_period' => 'CASE WHEN ntpo.name1 IS NULL THEN 1 ELSE CASE WHEN ntpr.timeperiod_id IS NOT NULL THEN 1 ELSE 0 END END',
),
);

Expand All @@ -33,24 +43,34 @@ public function init()

protected function joinServicenotificationperiod()
{
$extraJoinCond = '';

/* TODO: not used in this query
if (! empty ($this->ignoredNotificationPeriods)) {
$extraJoinCond .= $this->db->quoteInto(' AND ntpo.name1 NOT IN (?)', $this->ignoredNotificationPeriods);
}
*/

$this->select->joinLeft(
array('ntp' => $this->prefix . 'timeperiods'),
'ntp.timeperiod_object_id = s.notification_timeperiod_object_id AND ntp.config_type = 1 AND ntp.instance_id = s.instance_id',
array()
["ntp" => $this->prefix . 'timeperiods'],
'ntp.timeperiod_object_id = s.notification_timeperiod_object_id'
. ' AND ntp.config_type = 1 AND ntp.instance_id = s.instance_id',
[]
);
$this->select->joinLeft(
array('ntpo' => $this->prefix . 'objects'),
'ntpo.object_id = s.notification_timeperiod_object_id',
array()
['ntpo' => $this->prefix . 'objects'],
'ntpo.object_id = s.notification_timeperiod_object_id'
. $extraJoinCond,
[]
);
$this->select->joinLeft(
array('ntpr' => $this->prefix . 'timeperiod_timeranges'),
['ntpr' => $this->prefix . 'timeperiod_timeranges'],
'ntpr.timeperiod_id = ntp.timeperiod_id
AND ntpr.day = DAYOFWEEK(CURRENT_DATE()) - 1
AND ntpr.start_sec < UNIX_TIMESTAMP() - UNIX_TIMESTAMP(CURRENT_DATE())
AND ntpr.end_sec > UNIX_TIMESTAMP() - UNIX_TIMESTAMP(CURRENT_DATE())
',
array()
[]
);
}
}
8 changes: 6 additions & 2 deletions library/Toplevelview/Tree/TLVHostGroupNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public static function fetch(TLVTree $root)

$names = array_keys($root->registeredObjects['hostgroup']);

$options = [];
foreach (['notification_periods', 'host_never_unhandled', 'ignored_notification_periods'] as $opt) {
$options[$opt] = $root->get($opt);
}

// Note: this uses a patched version of Hostsgroupsummary / HostgroupsummaryQuery !
$hostgroups = new Hostgroupsummary(
$root->getBackend(),
Expand All @@ -49,8 +54,7 @@ public static function fetch(TLVTree $root)
'services_downtime_handled',
'services_downtime_active',
),
$root->get('notification_periods'),
$root->get('host_never_unhandled')
$options
);

$hostgroups->where('hostgroup_name', $names);
Expand Down