Skip to content

Commit

Permalink
Show root problem list for objects with problem and are part of depen…
Browse files Browse the repository at this point in the history
…dency
  • Loading branch information
raviks789 committed Sep 23, 2024
1 parent b5a4caa commit a2fb6b0
Show file tree
Hide file tree
Showing 11 changed files with 511 additions and 34 deletions.
88 changes: 57 additions & 31 deletions library/Icingadb/Common/StateBadges.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,6 @@ public function __construct($item)
$this->url = $this->getBaseUrl();
}

/**
* Get the badge base URL
*
* @return Url
*/
abstract protected function getBaseUrl(): Url;

/**
* Get the type of the items
*
Expand All @@ -67,14 +60,27 @@ abstract protected function getType(): string;
*/
abstract protected function getPrefix(): string;

/**
* Get the badge base URL
*
* @return ?Url
*/
protected function getBaseUrl(): ?Url
{
return null;
}

/**
* Get the integer of the given state text
*
* @param string $state
*
* @return int
*/
abstract protected function getStateInt(string $state): int;
protected function getStateInt(string $state): int
{
return 0;
}

/**
* Get the badge URL
Expand Down Expand Up @@ -132,18 +138,25 @@ public function createLink($content, Filter\Rule $filter = null): Link
* Create a state bade
*
* @param string $state
* @param bool $createLink Create link for the badge if true
*
* @return ?BaseHtmlElement
*/
protected function createBadge(string $state)
protected function createBadge(string $state, bool $createLink = true)
{
$key = $this->prefix . "_{$state}";

if (isset($this->item->$key) && $this->item->$key) {
return Html::tag('li', $this->createLink(
new StateBadge($this->item->$key, $state),
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state))
));
$stateBadge = new StateBadge($this->item->$key, $state);

if ($createLink) {
$this->createLink(
$stateBadge,
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state))
);
}

return Html::tag('li', $stateBadge);
}

return null;
Expand All @@ -153,37 +166,50 @@ protected function createBadge(string $state)
* Create a state group
*
* @param string $state
* @param bool $createLink Create link for the badge if true
*
* @return ?BaseHtmlElement
*/
protected function createGroup(string $state)
protected function createGroup(string $state, bool $createLink = true)
{
$content = [];
$handledKey = $this->prefix . "_{$state}_handled";
$unhandledKey = $this->prefix . "_{$state}_unhandled";

if (isset($this->item->$unhandledKey) && $this->item->$unhandledKey) {
$content[] = Html::tag('li', $this->createLink(
new StateBadge($this->item->$unhandledKey, $state),
Filter::all(
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state)),
Filter::equal($this->type . '.state.is_handled', 'n'),
Filter::equal($this->type . '.state.is_reachable', 'y')
)
));
$unhandledStateBadge = new StateBadge($this->item->$unhandledKey, $state);

if ($createLink) {
$unhandledStateBadge = $this->createLink(
$unhandledStateBadge,
Filter::all(
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state)),
Filter::equal($this->type . '.state.is_handled', 'n'),
Filter::equal($this->type . '.state.is_reachable', 'y')
)
);
}

$content[] = Html::tag('li', $unhandledStateBadge);
}

if (isset($this->item->$handledKey) && $this->item->$handledKey) {
$content[] = Html::tag('li', $this->createLink(
new StateBadge($this->item->$handledKey, $state, true),
Filter::all(
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state)),
Filter::any(
Filter::equal($this->type . '.state.is_handled', 'y'),
Filter::equal($this->type . '.state.is_reachable', 'n')
$handledStateBadge = new StateBadge($this->item->$handledKey, $state, true);

if ($createLink) {
$handledStateBadge = $this->createLink(
$handledStateBadge,
Filter::all(
Filter::equal($this->type . '.state.soft_state', $this->getStateInt($state)),
Filter::any(
Filter::equal($this->type . '.state.is_handled', 'y'),
Filter::equal($this->type . '.state.is_reachable', 'n')
)
)
)
));
);
}

$content[] = Html::tag('li', $handledStateBadge);
}

if (empty($content)) {
Expand Down
111 changes: 111 additions & 0 deletions library/Icingadb/Model/RedundancyGroupParentStateSummary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php

/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Icingadb\Model;

use ipl\Sql\Connection;
use ipl\Sql\Expression;

/**
* @property int $parents_acknowledged
* @property int $parents_down_critical_handled
* @property int $parents_down_critical_unhandled
* @property int $parents_pending
* @property int $parents_problems_unacknowledged
* @property int $parents_total
* @property int $parents_up_ok
* @property int $parents_unknown_handled
* @property int $parents_unknown_unhandled
* @property int $parents_warning_handled
* @property int $parents_warning_unhandled
*/
class RedundancyGroupParentStateSummary extends RedundancyGroup
{
public function getSummaryColumns()
{
return [
'parents_problem_handled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host_state.soft_state = 1'
. ' AND (redundancy_group_from_to_host_state.is_handled = \'y\''
. ' OR redundancy_group_from_to_host_state.is_reachable = \'n\') THEN 1 ELSE 0 END'
. '+ CASE WHEN redundancy_group_from_to_service_state.soft_state = 2'
. ' AND (redundancy_group_from_to_service_state.is_handled = \'y\''
. ' OR redundancy_group_from_to_service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)'
),
'parents_problem_unhandled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host_state.soft_state = 1'
. ' AND redundancy_group_from_to_host_state.is_handled = \'n\''
. ' AND redundancy_group_from_to_host_state.is_reachable = \'y\' THEN 1 ELSE 0 END'
. ' + CASE WHEN redundancy_group_from_to_service_state.soft_state = 2'
. ' AND redundancy_group_from_to_service_state.is_handled = \'n\''
. ' AND redundancy_group_from_to_service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)'
),
'parents_pending' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host_state.soft_state = 99 THEN 1 ELSE 0 END'
. '+ CASE WHEN redundancy_group_from_to_service_state.soft_state = 99 THEN 1 ELSE 0 END)'
),
'parents_problems_unacknowledged' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host_state.is_problem = \'y\''
. ' AND redundancy_group_from_to_host_state.is_acknowledged = \'n\' THEN 1 ELSE 0 END'
. '+ CASE WHEN redundancy_group_from_to_service_state.is_problem = \'y\''
. ' AND redundancy_group_from_to_service_state.is_acknowledged = \'n\' THEN 1 ELSE 0 END)'
),
'parents_total' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host.id IS NOT NULL THEN 1 ELSE 0 END)'
. '+ SUM(CASE WHEN redundancy_group_from_to_service.id IS NOT NULL THEN 1 ELSE 0 END)'
),
'parents_ok' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_host_state.soft_state = 0 THEN 1 ELSE 0 END'
. '+ CASE WHEN redundancy_group_from_to_service_state.soft_state = 0 THEN 1 ELSE 0 END)'
),
'parents_unknown_handled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_service_state.soft_state = 3'
. ' AND (redundancy_group_from_to_service_state.is_handled = \'y\''
. ' OR redundancy_group_from_to_service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)'
),
'parents_unknown_unhandled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_service_state.soft_state = 3'
. ' AND redundancy_group_from_to_service_state.is_handled = \'n\''
. ' AND redundancy_group_from_to_service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)'
),
'parents_warning_handled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_service_state.soft_state = 1'
. ' AND (redundancy_group_from_to_service_state.is_handled = \'y\''
. ' OR redundancy_group_from_to_service_state.is_reachable = \'n\') THEN 1 ELSE 0 END)'
),
'parents_warning_unhandled' => new Expression(
'SUM(CASE WHEN redundancy_group_from_to_service_state.soft_state = 1'
. ' AND redundancy_group_from_to_service_state.is_handled = \'n\''
. ' AND redundancy_group_from_to_service_state.is_reachable = \'y\' THEN 1 ELSE 0 END)'
)
];
}

public static function on(Connection $db)
{
$q = parent::on($db)->with([
'from',
'from.to.host',
'from.to.host.state',
'from.to.service',
'from.to.service.state'
]);

/** @var static $m */
$m = $q->getModel();
$q->columns($m->getSummaryColumns());

return $q;
}

public function getColumns(): array
{
return array_merge(parent::getColumns(), $this->getSummaryColumns());
}

public function getDefaultSort()
{
return null;
}
}
3 changes: 2 additions & 1 deletion library/Icingadb/Widget/Detail/HostDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ protected function assemble()
}

$this->add(ObjectDetailExtensionHook::injectExtensions([
0 => $this->createPluginOutput(),
0 => $this->createRootProblems(),
1 => $this->createPluginOutput(),
190 => $this->createServiceStatistics(),
300 => $this->createActions(),
301 => $this->createNotes(),
Expand Down
34 changes: 33 additions & 1 deletion library/Icingadb/Widget/Detail/ObjectDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
use Icinga\Module\Icingadb\Common\Links;
use Icinga\Module\Icingadb\Common\Macros;
use Icinga\Module\Icingadb\Compat\CompatHost;
use Icinga\Module\Icingadb\Compat\CompatService;
use Icinga\Module\Icingadb\Model\CustomvarFlat;
use Icinga\Module\Icingadb\Model\UnreachableParent;
use Icinga\Module\Icingadb\Web\Navigation\Action;
use Icinga\Module\Icingadb\Widget\ItemList\RootProblemList;
use Icinga\Module\Icingadb\Widget\MarkdownText;
use Icinga\Module\Icingadb\Common\ServiceLinks;
use Icinga\Module\Icingadb\Forms\Command\Object\ToggleObjectFeaturesForm;
Expand Down Expand Up @@ -602,4 +603,35 @@ protected function fetchCustomVars()
$this->object->customvar_flat = $customvarFlat->execute();
}
}

protected function createRootProblems(): ?array
{
$rootProblems = UnreachableParent::on($this->getDb(), $this->object)
->with([
'redundancy_group',
'redundancy_group.state',
'host',
'host.state',
'host.icon_image',
'host.state.last_comment',
'service',
'service.state',
'service.icon_image',
'service.state.last_comment',
'service.host',
'service.host.state'
]);

$this->applyRestrictions($rootProblems);

if ($rootProblems->count() > 0) {
$rootProblemList = (new RootProblemList(
$rootProblems->execute()
));

return [HtmlElement::create('h2', null, t('Root Problems')), $rootProblemList];
}

return null;
}
}
3 changes: 2 additions & 1 deletion library/Icingadb/Widget/Detail/ServiceDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ protected function assemble()
}

$this->add(ObjectDetailExtensionHook::injectExtensions([
0 => $this->createPluginOutput(),
0 => $this->createRootProblems(),
1 => $this->createPluginOutput(),
300 => $this->createActions(),
301 => $this->createNotes(),
400 => $this->createComments(),
Expand Down
Loading

0 comments on commit a2fb6b0

Please sign in to comment.