Skip to content

Commit

Permalink
fix(notification): repair flapping detection on volatile service (#123)
Browse files Browse the repository at this point in the history
* fix(notification): repair flapping detection on volatile service

REFS: MON-11974
  • Loading branch information
rem31 committed Jan 10, 2022
1 parent 10f844f commit e2cfeb4
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 9 deletions.
18 changes: 9 additions & 9 deletions centreon-engine/src/notifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,6 @@ bool notifier::_is_notification_viable_normal(reason_type type
return false;
}

/* On volatile services notifications are always sent */
if (get_is_volatile()) {
logger(dbg_notifications, more)
<< "This is a volatile service notification, so it is sent.";
return true;
}

timeperiod* tp{get_notification_timeperiod()};
timezone_locker lock{get_timezone()};
time_t now;
Expand All @@ -282,6 +275,13 @@ bool notifier::_is_notification_viable_normal(reason_type type
return false;
}

/* On volatile services notifications are always sent */
if (get_is_volatile()) {
logger(dbg_notifications, more)
<< "This is a volatile service notification, so it is sent.";
return true;
}

if (get_state_type() != hard) {
logger(dbg_notifications, more)
<< "This notifier is in soft state, so we won't send notifications.";
Expand Down Expand Up @@ -1093,8 +1093,8 @@ std::unordered_map<std::string, contact*>& notifier::get_contacts() noexcept {
return _contacts;
}

std::unordered_map<std::string, contact*> const& notifier::get_contacts()
const noexcept {
std::unordered_map<std::string, contact*> const& notifier::get_contacts() const
noexcept {
return _contacts;
}

Expand Down
100 changes: 100 additions & 0 deletions centreon-engine/tests/notifications/service_flapping_notification.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,106 @@ TEST_F(ServiceFlappingNotification, CheckFlapping) {
ASSERT_NE(m6, std::string::npos);
}

TEST_F(ServiceFlappingNotification, CheckFlappingWithVolatile) {
config->enable_flap_detection(true);
_service->set_flap_detection_enabled(true);
_service->set_is_volatile(true);
_service->add_flap_detection_on(engine::service::ok);
_service->add_flap_detection_on(engine::service::down);
_service->set_notification_interval(1);
time_t now = 45000;
set_time(now);
_service->set_current_state(engine::service::state_ok);
_service->set_last_hard_state(engine::service::state_ok);
_service->set_last_hard_state_change(50000);
_service->set_state_type(checkable::hard);
_service->set_first_notification_delay(3);
_service->set_max_attempts(1);

// This loop is to store many OK in the state history.
for (int i = 1; i < 22; i++) {
now += 300;
std::cout << "NOW = " << now << std::endl;
set_time(now);
_service->set_last_state(_service->get_current_state());
if (notifier::hard == _service->get_state_type())
_service->set_last_hard_state(_service->get_current_state());

std::ostringstream oss;
std::time_t now{std::time(nullptr)};
oss << '[' << now << ']'
<< " PROCESS_SERVICE_CHECK_RESULT;test_host;test_description;0;service "
"ok";
std::string cmd{oss.str()};
process_external_command(cmd.c_str());
checks::checker::instance().reap();
}

testing::internal::CaptureStdout();
// This loop is to store many CRITICAL or OK in the state history to start the
// flapping.
for (int i = 1; i < 8; i++) {
now += 300;
std::cout << "NOW = " << now << std::endl;
set_time(now);
_service->set_last_state(_service->get_current_state());
if (notifier::hard == _service->get_state_type())
_service->set_last_hard_state(_service->get_current_state());

std::ostringstream oss;
std::time_t now{std::time(nullptr)};
oss << '[' << now << ']'
<< " PROCESS_SERVICE_CHECK_RESULT;test_host;test_description;"
<< ((i % 2 == 1) ? "2;service critical" : "0;service ok");
std::string cmd{oss.str()};
process_external_command(cmd.c_str());
checks::checker::instance().reap();
}

// This loop is to store many CRITICAL in the state history to stop the
// flapping.
for (int i = 1; i < 18; i++) {
std::cout << "Step " << i << ":";
now += 300;
std::cout << "NOW = " << now << std::endl;
set_time(now);
_service->set_last_state(_service->get_current_state());
if (notifier::hard == _service->get_state_type())
_service->set_last_hard_state(_service->get_current_state());
std::ostringstream oss;
std::time_t now{std::time(nullptr)};
oss << '[' << now << ']'
<< " PROCESS_SERVICE_CHECK_RESULT;test_host;test_description;2;service "
"critical";
std::string cmd{oss.str()};
process_external_command(cmd.c_str());
checks::checker::instance().reap();
}

std::string out{testing::internal::GetCapturedStdout()};
size_t m1{out.find("NOW = 53100")};
size_t m2{
out.find("SERVICE NOTIFICATION: "
"admin;test_host;test_description;FLAPPINGSTART (CRITICAL);cmd;",
m1)};
size_t m3{out.find("Step 7:", m2)};
size_t m4{out.find("Step 16:", m3)};
size_t m5{out.find(
"SERVICE FLAPPING ALERT: test_host;test_description;STOPPED;", m4)};
size_t m6{
out.find("SERVICE NOTIFICATION: "
"admin;test_host;test_description;FLAPPINGSTOP (CRITICAL);cmd;",
m5)};
ASSERT_NE(m6, std::string::npos);
size_t m7{out.find("NOW = 57300")};
size_t m8{
out.find("SERVICE NOTIFICATION: "
"admin;test_host;test_description;CRITICAL;cmd;service critical",
m7)};
size_t m9{out.find("NOW = 57600", m8)};
ASSERT_EQ(m9, std::string::npos);
}

TEST_F(ServiceFlappingNotification, CheckFlappingWithHostDown) {
_host->set_current_state(engine::host::state_down);
_host->set_state_type(checkable::hard);
Expand Down

0 comments on commit e2cfeb4

Please sign in to comment.