From d18150739f99dd3e9cd4f023f9b87a1d67c6f67f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 31 Oct 2024 16:42:12 +0100 Subject: [PATCH 1/3] schema: Define which state columns are nullable --- library/Icingadb/Model/HostState.php | 63 ++++++++++++------------- library/Icingadb/Model/ServiceState.php | 63 ++++++++++++------------- library/Icingadb/Model/State.php | 47 ++++++++++++++++++ 3 files changed, 109 insertions(+), 64 deletions(-) diff --git a/library/Icingadb/Model/HostState.php b/library/Icingadb/Model/HostState.php index c9500e5fe..12ccd3536 100644 --- a/library/Icingadb/Model/HostState.php +++ b/library/Icingadb/Model/HostState.php @@ -24,38 +24,37 @@ public function getKeyName() public function getColumnDefinitions() { - return [ - 'environment_id' => t('Environment Id'), - 'state_type' => t('Host State Type'), - 'soft_state' => t('Host Soft State'), - 'hard_state' => t('Host Hard State'), - 'previous_soft_state' => t('Host Previous Soft State'), - 'previous_hard_state' => t('Host Previous Hard State'), - 'check_attempt' => t('Host Check Attempt No.'), - 'severity' => t('Host State Severity'), - 'output' => t('Host Output'), - 'long_output' => t('Host Long Output'), - 'performance_data' => t('Host Performance Data'), - 'normalized_performance_data' => t('Host Normalized Performance Data'), - 'check_commandline' => t('Host Check Commandline'), - 'is_problem' => t('Host Has Problem'), - 'is_handled' => t('Host Is Handled'), - 'is_reachable' => t('Host Is Reachable'), - 'is_flapping' => t('Host Is Flapping'), - 'is_overdue' => t('Host Check Is Overdue'), - 'is_acknowledged' => t('Host Is Acknowledged'), - 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), - 'in_downtime' => t('Host In Downtime'), - 'execution_time' => t('Host Check Execution Time'), - 'latency' => t('Host Check Latency'), - 'check_timeout' => t('Host Check Timeout'), - 'check_source' => t('Host Check Source'), - 'last_update' => t('Host Last Update'), - 'last_state_change' => t('Host Last State Change'), - 'next_check' => t('Host Next Check'), - 'next_update' => t('Host Next Update'), - 'affects_children' => t('Host Affects Children'), - ]; + return array_merge_recursive(parent::getColumnDefinitions(), [ + 'state_type' => ['label' => t('Host State Type')], + 'soft_state' => ['label' => t('Host Soft State')], + 'hard_state' => ['label' => t('Host Hard State')], + 'previous_soft_state' => ['label' => t('Host Previous Soft State')], + 'previous_hard_state' => ['label' => t('Host Previous Hard State')], + 'check_attempt' => ['label' => t('Host Check Attempt No.')], + 'severity' => ['label' => t('Host State Severity')], + 'output' => ['label' => t('Host Output')], + 'long_output' => ['label' => t('Host Long Output')], + 'performance_data' => ['label' => t('Host Performance Data')], + 'normalized_performance_data' => ['label' => t('Host Normalized Performance Data')], + 'check_commandline' => ['label' => t('Host Check Commandline')], + 'is_problem' => ['label' => t('Host Has Problem')], + 'is_handled' => ['label' => t('Host Is Handled')], + 'is_reachable' => ['label' => t('Host Is Reachable')], + 'is_flapping' => ['label' => t('Host Is Flapping')], + 'is_overdue' => ['label' => t('Host Check Is Overdue')], + 'is_acknowledged' => ['label' => t('Host Is Acknowledged')], + 'in_downtime' => ['label' => t('Host In Downtime')], + 'execution_time' => ['label' => t('Host Check Execution Time')], + 'latency' => ['label' => t('Host Check Latency')], + 'check_timeout' => ['label' => t('Host Check Timeout')], + 'check_source' => ['label' => t('Host Check Source')], + 'scheduling_source' => ['label' => t('Host Scheduling Source')], + 'last_update' => ['label' => t('Host Last Update')], + 'last_state_change' => ['label' => t('Host Last State Change')], + 'next_check' => ['label' => t('Host Next Check')], + 'next_update' => ['label' => t('Host Next Update')], + 'affects_children' => ['label' => t('Host Affects Children')], + ]); } public function createRelations(Relations $relations) diff --git a/library/Icingadb/Model/ServiceState.php b/library/Icingadb/Model/ServiceState.php index a42a4e239..dcf95e1e1 100644 --- a/library/Icingadb/Model/ServiceState.php +++ b/library/Icingadb/Model/ServiceState.php @@ -26,38 +26,37 @@ public function getKeyName() public function getColumnDefinitions() { - return [ - 'environment_id' => t('Environment Id'), - 'state_type' => t('Service State Type'), - 'soft_state' => t('Service Soft State'), - 'hard_state' => t('Service Hard State'), - 'previous_soft_state' => t('Service Previous Soft State'), - 'previous_hard_state' => t('Service Previous Hard State'), - 'check_attempt' => t('Service Check Attempt No.'), - 'severity' => t('Service State Severity'), - 'output' => t('Service Output'), - 'long_output' => t('Service Long Output'), - 'performance_data' => t('Service Performance Data'), - 'normalized_performance_data' => t('Service Normalized Performance Data'), - 'check_commandline' => t('Service Check Commandline'), - 'is_problem' => t('Service Has Problem'), - 'is_handled' => t('Service Is Handled'), - 'is_reachable' => t('Service Is Reachable'), - 'is_flapping' => t('Service Is Flapping'), - 'is_overdue' => t('Service Check Is Overdue'), - 'is_acknowledged' => t('Service Is Acknowledged'), - 'acknowledgement_comment_id' => t('Acknowledgement Comment Id'), - 'in_downtime' => t('Service In Downtime'), - 'execution_time' => t('Service Check Execution Time'), - 'latency' => t('Service Check Latency'), - 'check_timeout' => t('Service Check Timeout'), - 'check_source' => t('Service Check Source'), - 'last_update' => t('Service Last Update'), - 'last_state_change' => t('Service Last State Change'), - 'next_check' => t('Service Next Check'), - 'next_update' => t('Service Next Update'), - 'affects_children' => t('Service Affects Children'), - ]; + return array_merge_recursive(parent::getColumnDefinitions(), [ + 'state_type' => ['label' => t('Service State Type')], + 'soft_state' => ['label' => t('Service Soft State')], + 'hard_state' => ['label' => t('Service Hard State')], + 'previous_soft_state' => ['label' => t('Service Previous Soft State')], + 'previous_hard_state' => ['label' => t('Service Previous Hard State')], + 'check_attempt' => ['label' => t('Service Check Attempt No.')], + 'severity' => ['label' => t('Service State Severity')], + 'output' => ['label' => t('Service Output')], + 'long_output' => ['label' => t('Service Long Output')], + 'performance_data' => ['label' => t('Service Performance Data')], + 'normalized_performance_data' => ['label' => t('Service Normalized Performance Data')], + 'check_commandline' => ['label' => t('Service Check Commandline')], + 'is_problem' => ['label' => t('Service Has Problem')], + 'is_handled' => ['label' => t('Service Is Handled')], + 'is_reachable' => ['label' => t('Service Is Reachable')], + 'is_flapping' => ['label' => t('Service Is Flapping')], + 'is_overdue' => ['label' => t('Service Check Is Overdue')], + 'is_acknowledged' => ['label' => t('Service Is Acknowledged')], + 'in_downtime' => ['label' => t('Service In Downtime')], + 'execution_time' => ['label' => t('Service Check Execution Time')], + 'latency' => ['label' => t('Service Check Latency')], + 'check_timeout' => ['label' => t('Service Check Timeout')], + 'check_source' => ['label' => t('Service Check Source')], + 'scheduling_source' => ['label' => t('Service Scheduling Source')], + 'last_update' => ['label' => t('Service Last Update')], + 'last_state_change' => ['label' => t('Service Last State Change')], + 'next_check' => ['label' => t('Service Next Check')], + 'next_update' => ['label' => t('Service Next Update')], + 'affects_children' => ['label' => t('Service Affects Children')], + ]); } public function createRelations(Relations $relations) diff --git a/library/Icingadb/Model/State.php b/library/Icingadb/Model/State.php index a4556c1d5..6719c5d14 100644 --- a/library/Icingadb/Model/State.php +++ b/library/Icingadb/Model/State.php @@ -104,6 +104,53 @@ public function getColumns() ]; } + public function getColumnDefinitions() + { + return [ + 'environment_id' => [ + 'label' => t('Environment Id'), + 'nullable' => false + ], + 'state_type' => ['nullable' => false], + 'soft_state' => ['nullable' => false], + 'hard_state' => ['nullable' => false], + 'previous_soft_state' => ['nullable' => false], + 'previous_hard_state' => ['nullable' => false], + 'check_attempt' => ['nullable' => false], + 'severity' => ['nullable' => false], + 'output' => ['nullable' => true], + 'long_output' => ['nullable' => true], + 'performance_data' => ['nullable' => true], + 'normalized_performance_data' => ['nullable' => true], + 'check_commandline' => ['nullable' => true], + 'is_problem' => ['nullable' => false], + 'is_handled' => ['nullable' => false], + 'is_reachable' => ['nullable' => false], + 'is_flapping' => ['nullable' => false], + 'is_overdue' => ['nullable' => false], + 'is_acknowledged' => ['nullable' => false], + 'acknowledgement_comment_id' => [ + 'label' => t('Acknowledgement Comment Id'), + 'nullable' => true + ], + 'last_comment_id' => [ + 'label' => t('Last Comment Id'), + 'nullable' => true + ], + 'in_downtime' => ['nullable' => false], + 'affects_children' => ['nullable' => false], + 'execution_time' => ['nullable' => true], + 'latency' => ['nullable' => true], + 'check_timeout' => ['nullable' => true], + 'check_source' => ['nullable' => true], + 'scheduling_source' => ['nullable' => true], + 'last_update' => ['nullable' => true], + 'last_state_change' => ['nullable' => false], + 'next_check' => ['nullable' => false], + 'next_update' => ['nullable' => false], + ]; + } + public function createBehaviors(Behaviors $behaviors) { $behaviors->add(new BoolCast([ From 6fd3b01d475fd3c2432ab2765047254ab5f5c1ad Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 31 Oct 2024 16:42:54 +0100 Subject: [PATCH 2/3] VolatileStateResults: Only accept null values for nullable columns --- library/Icingadb/Redis/VolatileStateResults.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php index 43446d681..e49f84a17 100644 --- a/library/Icingadb/Redis/VolatileStateResults.php +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -109,7 +109,7 @@ protected function applyRedisUpdates($rows) $showSourceGranted = $this->getAuth()->hasPermission('icingadb/object/show-source'); $getKeysAndBehaviors = function (State $state): array { - return [$state->getColumns(), $this->resolver->getBehaviors($state)]; + return [$state->getColumns(), $this->resolver->getBehaviors($state), $state->getColumnDefinitions()]; }; $states = []; @@ -140,7 +140,7 @@ protected function applyRedisUpdates($rows) $states[$type][bin2hex($row->id)] = $row->state; if (! isset($states[$type]['keys'])) { - [$keys, $behaviors] = $getKeysAndBehaviors($row->state); + [$keys, $behaviors, $definitions] = $getKeysAndBehaviors($row->state); if (! $showSourceGranted) { $keys = array_diff($keys, ['check_commandline']); @@ -148,16 +148,18 @@ protected function applyRedisUpdates($rows) $states[$type]['keys'] = $keys; $states[$type]['behaviors'] = $behaviors; + $states[$type]['definitions'] = $definitions; } if ($type === self::TYPE_SERVICE && $row->host instanceof Host && isset($row->host->id)) { $states[self::TYPE_HOST][bin2hex($row->host->id)] = $row->host->state; if (! isset($states[self::TYPE_HOST]['keys'])) { - [$keys, $behaviors] = $getKeysAndBehaviors($row->host->state); + [$keys, $behaviors, $definitions] = $getKeysAndBehaviors($row->host->state); $states[self::TYPE_HOST]['keys'] = $keys; $states[self::TYPE_HOST]['behaviors'] = $behaviors; + $states[self::TYPE_HOST]['definitions'] = $definitions; } } } @@ -183,8 +185,9 @@ protected function apply(array $states, string $type): void { $keys = $states['keys']; $behaviors = $states['behaviors']; + $definitions = $states['definitions']; - unset($states['keys'], $states['behaviors']); + unset($states['keys'], $states['behaviors'], $states['definitions']); $results = $type === self::TYPE_SERVICE ? IcingaRedis::fetchServiceState(array_keys($states), $keys) @@ -192,7 +195,11 @@ protected function apply(array $states, string $type): void foreach ($results as $id => $data) { foreach ($data as $key => $value) { - $data[$key] = $behaviors->retrieveProperty($value, $key); + if ($value === null && ($definitions[$key]['nullable'] ?? true) === false) { + unset($data[$key]); + } else { + $data[$key] = $behaviors->retrieveProperty($value, $key); + } } $states[$id]->setProperties($data); From cf8aa895562e047264c03b6eb9cadb439b7c36ef Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 11 Dec 2024 11:31:51 +0100 Subject: [PATCH 3/3] VolatileStateResults: Ignore is_reachable fully icinga2 is still too unreliable for quick tests --- library/Icingadb/Redis/VolatileStateResults.php | 1 + 1 file changed, 1 insertion(+) diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php index e49f84a17..c438e4997 100644 --- a/library/Icingadb/Redis/VolatileStateResults.php +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -141,6 +141,7 @@ protected function applyRedisUpdates($rows) if (! isset($states[$type]['keys'])) { [$keys, $behaviors, $definitions] = $getKeysAndBehaviors($row->state); + $keys = array_diff($keys, ['is_reachable']); if (! $showSourceGranted) { $keys = array_diff($keys, ['check_commandline']);