From d6a32faf967e1988aadb0b30de84c14a81428cb1 Mon Sep 17 00:00:00 2001 From: ccztux Date: Tue, 6 Aug 2024 16:15:38 +0200 Subject: [PATCH 1/3] Fixed missing OK HARD state after OK SOFT. --- src/naemon/checks_service.c | 11 +++++++++++ src/naemon/objects_service.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/naemon/checks_service.c b/src/naemon/checks_service.c index 4fab8215..d8f4aa41 100644 --- a/src/naemon/checks_service.c +++ b/src/naemon/checks_service.c @@ -840,6 +840,9 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* this is a soft recovery */ temp_service->state_type = SOFT_STATE; + /* this is a soft recovery */ + temp_service->last_state_was_soft_recovery = TRUE; + /* log the soft recovery */ log_service_event(temp_service); alert_recorded = NEBATTR_CHECK_ALERT; @@ -851,6 +854,14 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* else no service state change has occurred... */ else { log_debug_info(DEBUGL_CHECKS, 1, "Service did not change state.\n"); + + if (temp_service->last_state_was_soft_recovery == TRUE) { + /* log the hard state after the last check which was a soft recovery */ + log_service_event(temp_service); + alert_recorded = NEBATTR_CHECK_ALERT; + } + + temp_service->last_state_was_soft_recovery = FALSE; } /* should we obsessive over service checks? */ diff --git a/src/naemon/objects_service.h b/src/naemon/objects_service.h index 35031b85..cf5eeb68 100644 --- a/src/naemon/objects_service.h +++ b/src/naemon/objects_service.h @@ -70,6 +70,7 @@ struct service { int acknowledgement_type; time_t acknowledgement_end_time; int host_problem_at_last_check; + int last_state_was_soft_recovery; int check_type; int current_state; int last_state; From 010bd982c61a57dc90d57e22e410272684f42d80 Mon Sep 17 00:00:00 2001 From: zet Date: Wed, 30 Jul 2025 13:36:29 +0200 Subject: [PATCH 2/3] Refactored implementation to avoid introducing a new flag, as suggested in review --- src/naemon/checks_service.c | 43 +++++++++++++++++++++++++----------- src/naemon/objects_service.h | 1 - 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/naemon/checks_service.c b/src/naemon/checks_service.c index 9529c274..603e2d87 100644 --- a/src/naemon/checks_service.c +++ b/src/naemon/checks_service.c @@ -495,6 +495,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue service *master_service = NULL; int state_changes_use_cached_state = TRUE; /* TODO - 09/23/07 move this to a global variable */ int flapping_check_done = FALSE; + int hard_recovery_after_soft = FALSE; /* make sure we have what we need */ if (temp_service == NULL || queued_check_result == NULL) @@ -667,8 +668,8 @@ int handle_async_service_check_result(service *temp_service, check_result *queue } - /* increment the current attempt number if this is a soft state (service was rechecked) */ - if (temp_service->state_type == SOFT_STATE && (temp_service->current_attempt < temp_service->max_attempts)) + /* increment the current attempt number if this is a soft state (service was rechecked) and last state was not ok (no ok soft recovery) */ + if (temp_service->state_type == SOFT_STATE && temp_service->current_attempt < temp_service->max_attempts && temp_service->last_state != STATE_OK) temp_service->current_attempt = temp_service->current_attempt + 1; @@ -694,6 +695,12 @@ int handle_async_service_check_result(service *temp_service, check_result *queue hard_state_change = TRUE; } + /* identify a hard recovery scenario where a soft recovery has stabilized to an OK state */ + if (temp_service->state_type == SOFT_STATE && temp_service->last_state == STATE_OK && temp_service->current_state == STATE_OK) { + log_debug_info(DEBUGL_CHECKS, 2, "Service had a HARD RECOVERY AFTER SOFT RECOVERY!!\n"); + hard_recovery_after_soft = TRUE; + } + /* a state change occurred... */ /* reset last and next notification times and acknowledgement flag if necessary, misc other stuff */ if (state_change == TRUE || hard_state_change == TRUE) { @@ -842,9 +849,6 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* this is a soft recovery */ temp_service->state_type = SOFT_STATE; - /* this is a soft recovery */ - temp_service->last_state_was_soft_recovery = TRUE; - /* log the soft recovery */ log_service_event(temp_service); alert_recorded = NEBATTR_CHECK_ALERT; @@ -855,26 +859,39 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* else no service state change has occurred... */ else { - log_debug_info(DEBUGL_CHECKS, 1, "Service did not change state.\n"); - if (temp_service->last_state_was_soft_recovery == TRUE) { - /* log the hard state after the last check which was a soft recovery */ + /* no state change detected, service remains in the same status */ + if (hard_recovery_after_soft == FALSE) { + log_debug_info(DEBUGL_CHECKS, 1, "Service did not change state.\n"); + + } + + /* service transitioned from SOFT to HARD recovery, update state and generate alert */ + else { + log_debug_info(DEBUGL_CHECKS, 1, "Service experienced a HARD RECOVERY AFTER A SOFT RECOVERY.\n"); + + /* reset state type to HARD for accurate log message classification */ + temp_service->state_type = HARD_STATE; + + /* log the hard recovery */ log_service_event(temp_service); alert_recorded = NEBATTR_CHECK_ALERT; } - - temp_service->last_state_was_soft_recovery = FALSE; } /* should we obsessive over service checks? */ if (obsess_over_services == TRUE) obsessive_compulsive_service_check_processor(temp_service); - /* reset all service variables because its okay now... */ + /* reset state type and last hard state service variables when its ok hard */ + if (temp_service->state_type == HARD_STATE) { + temp_service->state_type = HARD_STATE; + temp_service->last_hard_state = STATE_OK; + } + + /* reset all other service variables because its okay now... */ temp_service->host_problem_at_last_check = FALSE; temp_service->current_attempt = 1; - temp_service->state_type = HARD_STATE; - temp_service->last_hard_state = STATE_OK; temp_service->last_notification = (time_t)0; temp_service->next_notification = (time_t)0; temp_service->current_notification_number = 0; diff --git a/src/naemon/objects_service.h b/src/naemon/objects_service.h index cf5eeb68..35031b85 100644 --- a/src/naemon/objects_service.h +++ b/src/naemon/objects_service.h @@ -70,7 +70,6 @@ struct service { int acknowledgement_type; time_t acknowledgement_end_time; int host_problem_at_last_check; - int last_state_was_soft_recovery; int check_type; int current_state; int last_state; From 1f1db611d092397e078fb8b8c9c19da24738f188 Mon Sep 17 00:00:00 2001 From: zet Date: Wed, 13 Aug 2025 11:55:17 +0200 Subject: [PATCH 3/3] Wording changed. --- src/naemon/checks_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/naemon/checks_service.c b/src/naemon/checks_service.c index 603e2d87..87098321 100644 --- a/src/naemon/checks_service.c +++ b/src/naemon/checks_service.c @@ -668,7 +668,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue } - /* increment the current attempt number if this is a soft state (service was rechecked) and last state was not ok (no ok soft recovery) */ + /* increment the current attempt number if this is a soft state (service was rechecked) and last state was not a OK state */ if (temp_service->state_type == SOFT_STATE && temp_service->current_attempt < temp_service->max_attempts && temp_service->last_state != STATE_OK) temp_service->current_attempt = temp_service->current_attempt + 1;