From 20212a0f87f64ebe2bb39937fb9dfe07b1d23bb7 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 9 Apr 2024 11:48:42 +0200 Subject: [PATCH 1/4] VolatileStateResults: Properly handle missing host details --- library/Icingadb/Redis/VolatileStateResults.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icingadb/Redis/VolatileStateResults.php b/library/Icingadb/Redis/VolatileStateResults.php index 941839802..089b93ca6 100644 --- a/library/Icingadb/Redis/VolatileStateResults.php +++ b/library/Icingadb/Redis/VolatileStateResults.php @@ -131,7 +131,7 @@ protected function applyRedisUpdates($rows) } } - if ($type === 'service' && $row->host instanceof Host) { + if ($type === 'service' && $row->host instanceof Host && isset($row->host->id)) { $hostStates[bin2hex($row->host->id)] = $row->host->state; if (empty($hostStateKeys)) { $hostStateKeys = $row->host->state->getColumns(); From a7e76f6f4476603ae2c55c7449ab68b45c75ebb9 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 23 Jul 2024 16:19:39 +0200 Subject: [PATCH 2/4] Try even harder to not fail badly if some results are missing --- library/Icingadb/Common/TicketLinks.php | 2 +- library/Icingadb/Compat/CompatObject.php | 2 +- .../Icingadb/Widget/Detail/EventDetail.php | 50 +++++++++++++------ .../Icingadb/Widget/Detail/ObjectDetail.php | 4 +- .../Widget/Detail/ServiceMetaInfo.php | 8 ++- .../Widget/ItemList/BaseHistoryListItem.php | 14 +++--- .../Widget/ItemTable/StateRowItem.php | 12 ++++- 7 files changed, 66 insertions(+), 26 deletions(-) diff --git a/library/Icingadb/Common/TicketLinks.php b/library/Icingadb/Common/TicketLinks.php index 6cf7e7687..3fb01c60b 100644 --- a/library/Icingadb/Common/TicketLinks.php +++ b/library/Icingadb/Common/TicketLinks.php @@ -51,6 +51,6 @@ public function createTicketLinks($text): string return $tickets->createLinks($text); } - return $text; + return $text ?? ''; } } diff --git a/library/Icingadb/Compat/CompatObject.php b/library/Icingadb/Compat/CompatObject.php index 1d9657db8..8434ced72 100644 --- a/library/Icingadb/Compat/CompatObject.php +++ b/library/Icingadb/Compat/CompatObject.php @@ -61,7 +61,7 @@ public static function fromModel(Model $object) */ public function getName(): string { - return $this->object->name; + return $this->object->name ?? ''; } public function fetch(): bool diff --git a/library/Icingadb/Widget/Detail/EventDetail.php b/library/Icingadb/Widget/Detail/EventDetail.php index cf0e5cfbb..ccbfbc925 100644 --- a/library/Icingadb/Widget/Detail/EventDetail.php +++ b/library/Icingadb/Widget/Detail/EventDetail.php @@ -131,7 +131,9 @@ protected function assembleNotificationEvent(NotificationHistory $notification) new HtmlElement('h2', null, Text::create(t('Event Info'))), new HorizontalKeyValue( t('Sent On'), - DateFormatter::formatDateTime($notification->send_time->getTimestamp()) + isset($notification->send_time) + ? DateFormatter::formatDateTime($notification->send_time->getTimestamp()) + : new EmptyState(t('n. a.')) ) ]; @@ -249,7 +251,9 @@ protected function assembleStateChangeEvent(StateHistory $stateChange) new HtmlElement('h2', null, Text::create(t('Event Info'))), new HorizontalKeyValue( t('Occurred On'), - DateFormatter::formatDateTime($stateChange->event_time->getTimestamp()) + isset($stateChange->event_time) + ? DateFormatter::formatDateTime($stateChange->event_time->getTimestamp()) + : new EmptyState(t('n. a.')) ), new HorizontalKeyValue(t('Scheduling Source'), $stateChange->scheduling_source), new HorizontalKeyValue(t('Check Source'), $stateChange->check_source) @@ -341,29 +345,41 @@ protected function assembleDowntimeEvent(DowntimeHistory $downtime) )); $eventInfo[] = new HorizontalKeyValue( t('Entered On'), - DateFormatter::formatDateTime($downtime->entry_time->getTimestamp()) + isset($downtime->entry_time) + ? DateFormatter::formatDateTime($downtime->entry_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue(t('Author'), [new Icon('user'), $downtime->author]); // TODO: The following should be presented in a specific widget (maybe just like the downtime card) $eventInfo[] = new HorizontalKeyValue( t('Triggered On'), - DateFormatter::formatDateTime($downtime->trigger_time->getTimestamp()) + isset($downtime->trigger_time) + ? DateFormatter::formatDateTime($downtime->trigger_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue( t('Scheduled Start'), - DateFormatter::formatDateTime($downtime->scheduled_start_time->getTimestamp()) + isset($downtime->scheduled_start_time) + ? DateFormatter::formatDateTime($downtime->scheduled_start_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue( t('Actual Start'), - DateFormatter::formatDateTime($downtime->start_time->getTimestamp()) + isset($downtime->start_time) + ? DateFormatter::formatDateTime($downtime->start_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue( t('Scheduled End'), - DateFormatter::formatDateTime($downtime->scheduled_end_time->getTimestamp()) + isset($downtime->scheduled_end_time) + ? DateFormatter::formatDateTime($downtime->scheduled_end_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue( t('Actual End'), - DateFormatter::formatDateTime($downtime->end_time->getTimestamp()) + isset($downtime->end_time) + ? DateFormatter::formatDateTime($downtime->end_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); if ($downtime->is_flexible) { @@ -419,7 +435,9 @@ protected function assembleCommentEvent(CommentHistory $comment) )); $eventInfo[] = new HorizontalKeyValue( t('Entered On'), - DateFormatter::formatDateTime($comment->entry_time->getTimestamp()) + isset($comment->entry_time) + ? DateFormatter::formatDateTime($comment->entry_time->getTimestamp()) + : new EmptyState(t('n. a.')) ); $eventInfo[] = new HorizontalKeyValue(t('Author'), [new Icon('user'), $comment->author]); $eventInfo[] = new HorizontalKeyValue( @@ -487,7 +505,9 @@ protected function assembleFlappingEvent(FlappingHistory $flapping) )), new HorizontalKeyValue( t('Started on'), - DateFormatter::formatDateTime($flapping->start_time->getTimestamp()) + isset($flapping->start_time) + ? DateFormatter::formatDateTime($flapping->start_time->getTimestamp()) + : new EmptyState(t('n. a.')) ) ]; if ($this->event->event_type === 'flapping_start') { @@ -529,7 +549,9 @@ protected function assembleAcknowledgeEvent(AcknowledgementHistory $acknowledgem new HtmlElement('h2', null, Text::create(t('Event Info'))), new HorizontalKeyValue( t('Set on'), - DateFormatter::formatDateTime($acknowledgement->set_time->getTimestamp()) + isset($acknowledgement->set_time) + ? DateFormatter::formatDateTime($acknowledgement->set_time->getTimestamp()) + : new EmptyState(t('n. a.')) ), new HorizontalKeyValue(t('Author'), $acknowledgement->author ? [new Icon('user'), $acknowledgement->author] @@ -555,8 +577,8 @@ protected function assembleAcknowledgeEvent(AcknowledgementHistory $acknowledgem $eventInfo[] = new HorizontalKeyValue( t('Expires On'), $acknowledgement->expire_time - ? DateFormatter::formatDateTime($acknowledgement->expire_time->getTimestamp()) - : new EmptyState(t('Never')) + ? DateFormatter::formatDateTime($acknowledgement->expire_time->getTimestamp()) + : new EmptyState(t('Never')) ); $eventInfo[] = new HorizontalKeyValue(t('Sticky'), isset($acknowledgement->is_sticky) ? ($acknowledgement->is_sticky ? t('Yes') : t('No')) @@ -568,7 +590,7 @@ protected function assembleAcknowledgeEvent(AcknowledgementHistory $acknowledgem $eventInfo[] = new HorizontalKeyValue( t('Cleared on'), DateFormatter::formatDateTime( - $acknowledgement->clear_time + $acknowledgement->clear_time !== null ? $acknowledgement->clear_time->getTimestamp() : $this->event->event_time->getTimestamp() ) diff --git a/library/Icingadb/Widget/Detail/ObjectDetail.php b/library/Icingadb/Widget/Detail/ObjectDetail.php index d3db63111..e64dc050e 100644 --- a/library/Icingadb/Widget/Detail/ObjectDetail.php +++ b/library/Icingadb/Widget/Detail/ObjectDetail.php @@ -112,7 +112,9 @@ protected function createPrintHeader() $info[] = new HorizontalKeyValue( t('Last State Change'), - DateFormatter::formatDateTime($this->object->state->last_state_change->getTimestamp()) + isset($this->object->state->last_state_change) + ? DateFormatter::formatDateTime($this->object->state->last_state_change) + : new EmptyState(t('n. a.')) ); return [ diff --git a/library/Icingadb/Widget/Detail/ServiceMetaInfo.php b/library/Icingadb/Widget/Detail/ServiceMetaInfo.php index cca723763..faca1f921 100644 --- a/library/Icingadb/Widget/Detail/ServiceMetaInfo.php +++ b/library/Icingadb/Widget/Detail/ServiceMetaInfo.php @@ -6,6 +6,8 @@ use Icinga\Date\DateFormatter; use Icinga\Module\Icingadb\Model\Service; +use ipl\I18n\Translation; +use ipl\Web\Widget\EmptyState; use ipl\Web\Widget\VerticalKeyValue; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; @@ -15,6 +17,8 @@ class ServiceMetaInfo extends BaseHtmlElement { + use Translation; + protected $tag = 'div'; protected $defaultAttributes = ['class' => 'object-meta-info']; @@ -33,7 +37,9 @@ protected function assemble() new VerticalKeyValue('service.name', $this->service->name), new VerticalKeyValue( 'last_state_change', - DateFormatter::formatDateTime($this->service->state->last_state_change->getTimestamp()) + isset($this->service->state->last_state_change) + ? DateFormatter::formatDateTime($this->service->state->last_state_change->getTimestamp()) + : (new EmptyState($this->translate('n. a.')))->setTag('span') ) ); diff --git a/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php b/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php index 6999324d5..61da9fd1d 100644 --- a/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php +++ b/library/Icingadb/Widget/ItemList/BaseHistoryListItem.php @@ -94,10 +94,12 @@ protected function assembleCaption(BaseHtmlElement $caption): void t('State Change Rate: %.2f%%; End Threshold: %.2f%%; Flapping for %s'), $this->item->flapping->percent_state_change_end, $this->item->flapping->flapping_threshold_low, - DateFormatter::formatDuration( - $this->item->flapping->end_time->getTimestamp() - - $this->item->flapping->start_time->getTimestamp() - ) + isset($this->item->flapping->end_time) + ? DateFormatter::formatDuration( + $this->item->flapping->end_time->getTimestamp() + - $this->item->flapping->start_time->getTimestamp() + ) + : t('n. a.') )) ->getAttributes() ->add('class', 'plugin-output'); @@ -345,10 +347,10 @@ protected function assembleTitle(BaseHtmlElement $title): void break; case 'notification': - $subjectLabel = sprintf( + $subjectLabel = isset($this->item->notification->type) ? sprintf( NotificationListItem::phraseForType($this->item->notification->type), ucfirst($this->item->object_type) - ); + ) : $this->item->event_type; break; case 'state_change': diff --git a/library/Icingadb/Widget/ItemTable/StateRowItem.php b/library/Icingadb/Widget/ItemTable/StateRowItem.php index 7ca93921c..410ec7e76 100644 --- a/library/Icingadb/Widget/ItemTable/StateRowItem.php +++ b/library/Icingadb/Widget/ItemTable/StateRowItem.php @@ -77,12 +77,20 @@ protected function assembleCell(BaseHtmlElement $cell, string $path, $value) case $path === 'state.last_update': case $path === 'state.last_state_change': $column = substr($path, 6); - $cell->addHtml(new TimeSince($this->item->state->$column->getTimestamp())); + $cell->addHtml( + isset($this->item->state->$column) + ? new TimeSince($this->item->state->$column->getTimestamp()) + : new EmptyState(t('n. a.')) + ); break; case $path === 'state.next_check': case $path === 'state.next_update': $column = substr($path, 6); - $cell->addHtml(new TimeUntil($this->item->state->$column->getTimestamp())); + $cell->addHtml( + isset($this->item->state->$column) + ? new TimeUntil($this->item->state->$column->getTimestamp()) + : new EmptyState(t('n. a.')) + ); break; case $path === 'state.performance_data': case $path === 'state.normalized_performance_data': From ab2485332a8d7220d94a24ce91ef266f475e5720 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 23 Jul 2024 16:23:21 +0200 Subject: [PATCH 3/4] CheckStatistics: Fix incorrect check interval detection --- library/Icingadb/Widget/Detail/CheckStatistics.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Icingadb/Widget/Detail/CheckStatistics.php b/library/Icingadb/Widget/Detail/CheckStatistics.php index 8a826d565..ff458de57 100644 --- a/library/Icingadb/Widget/Detail/CheckStatistics.php +++ b/library/Icingadb/Widget/Detail/CheckStatistics.php @@ -337,7 +337,7 @@ protected function getCheckInterval(): int return $this->object->check_interval; } - $delay = ($this->object->state->execution_time + $this->object->state->latency) / 1000 + 5; + $delay = ($this->object->state->execution_time + $this->object->state->latency / 1000) + 5; $interval = $this->object->state->next_check->getTimestamp() - $this->object->state->last_update->getTimestamp(); From ced20e4a1e8c18c31a99f9feb631c6f49d18e7df Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 24 Jul 2024 16:35:26 +0200 Subject: [PATCH 4/4] phpstan: Update standard baseline --- phpstan-baseline-standard.neon | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/phpstan-baseline-standard.neon b/phpstan-baseline-standard.neon index 994c0d556..a1f2cac67 100644 --- a/phpstan-baseline-standard.neon +++ b/phpstan-baseline-standard.neon @@ -4487,7 +4487,7 @@ parameters: - message: "#^Cannot access property \\$host on mixed\\.$#" - count: 4 + count: 2 path: library/Icingadb/Redis/VolatileStateResults.php - @@ -6960,6 +6960,11 @@ parameters: count: 1 path: library/Icingadb/Widget/ItemList/BaseHistoryListItem.php + - + message: "#^Access to an undefined property object\\:\\:\\$start_time\\.$#" + count: 1 + path: library/Icingadb/Widget/ItemList/BaseHistoryListItem.php + - message: "#^Access to an undefined property object\\:\\:\\$text\\.$#" count: 1 @@ -7070,11 +7075,6 @@ parameters: count: 3 path: library/Icingadb/Widget/ItemList/BaseHistoryListItem.php - - - message: "#^Cannot access property \\$start_time on mixed\\.$#" - count: 1 - path: library/Icingadb/Widget/ItemList/BaseHistoryListItem.php - - message: "#^Cannot access property \\$state_type on mixed\\.$#" count: 3 @@ -7542,22 +7542,22 @@ parameters: - message: "#^Cannot access property \\$last_state_change on mixed\\.$#" - count: 1 + count: 2 path: library/Icingadb/Widget/ItemTable/StateRowItem.php - message: "#^Cannot access property \\$last_update on mixed\\.$#" - count: 1 + count: 2 path: library/Icingadb/Widget/ItemTable/StateRowItem.php - message: "#^Cannot access property \\$next_check on mixed\\.$#" - count: 1 + count: 2 path: library/Icingadb/Widget/ItemTable/StateRowItem.php - message: "#^Cannot access property \\$next_update on mixed\\.$#" - count: 1 + count: 2 path: library/Icingadb/Widget/ItemTable/StateRowItem.php -