From ce9c390ed9faa1ade9d98698005b4e5a34d0f394 Mon Sep 17 00:00:00 2001
From: Michael Friedrich <michael.friedrich@netways.de>
Date: Mon, 1 Jul 2013 17:25:30 +0200
Subject: [PATCH] flapping: fix division by 0, add compat status, extcmds

and some debug output.

refs #4360
refs #2711
---
 components/compat/compatcomponent.cpp   |  3 +++
 lib/icinga/externalcommandprocessor.cpp |  4 ++++
 lib/icinga/service-check.cpp            | 12 ++++++++++++
 lib/icinga/service-flapping.cpp         |  3 +++
 4 files changed, 22 insertions(+)

diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp
index 16b7aba4f..096fad470 100644
--- a/components/compat/compatcomponent.cpp
+++ b/components/compat/compatcomponent.cpp
@@ -413,6 +413,9 @@ void CompatComponent::DumpServiceStatusAttrs(std::ostream& fp, const Service::Pt
 	   << "\t" << "notifications_enabled=" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
 	   << "\t" << "active_checks_enabled=" << (service->GetEnableActiveChecks() ? 1 : 0) <<"\n"
 	   << "\t" << "passive_checks_enabled=" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
+	   << "\t" << "flap_detection_enabled=" << "\t" << (service->GetEnableFlapping() ? 1 : 0) << "\n"
+	   << "\t" << "is_flapping=" << "\t" << (service->IsFlapping() ? 1 : 0) << "\n"
+	   << "\t" << "percent_state_change=" << "\t" << Convert::ToString(service->GetFlappingCurrent()) << "\n"
 	   << "\t" << "problem_has_been_acknowledged=" << (service->GetAcknowledgement() != AcknowledgementNone ? 1 : 0) << "\n"
 	   << "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
 	   << "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
diff --git a/lib/icinga/externalcommandprocessor.cpp b/lib/icinga/externalcommandprocessor.cpp
index aba9168c2..717f7f003 100644
--- a/lib/icinga/externalcommandprocessor.cpp
+++ b/lib/icinga/externalcommandprocessor.cpp
@@ -118,6 +118,10 @@ void ExternalCommandProcessor::Initialize(void)
 	RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM", &ExternalCommandProcessor::AcknowledgeHostProblem);
 	RegisterCommand("ACKNOWLEDGE_HOST_PROBLEM_EXPIRE", &ExternalCommandProcessor::AcknowledgeHostProblemExpire);
 	RegisterCommand("REMOVE_HOST_ACKNOWLEDGEMENT", &ExternalCommandProcessor::RemoveHostAcknowledgement);
+	RegisterCommand("DISABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::DisableHostFlapping);
+	RegisterCommand("ENABLE_HOST_FLAP_DETECTION", &ExternalCommandProcessor::EnableHostFlapping);
+	RegisterCommand("DISABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::DisableSvcFlapping);
+	RegisterCommand("ENABLE_SVC_FLAP_DETECTION", &ExternalCommandProcessor::EnableSvcFlapping);
 	RegisterCommand("ENABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableHostgroupSvcChecks);
 	RegisterCommand("DISABLE_HOSTGROUP_SVC_CHECKS", &ExternalCommandProcessor::DisableHostgroupSvcChecks);
 	RegisterCommand("ENABLE_SERVICEGROUP_SVC_CHECKS", &ExternalCommandProcessor::EnableServicegroupSvcChecks);
diff --git a/lib/icinga/service-check.cpp b/lib/icinga/service-check.cpp
index 961c21d91..5badf7521 100644
--- a/lib/icinga/service-check.cpp
+++ b/lib/icinga/service-check.cpp
@@ -27,6 +27,7 @@
 #include "base/dynamictype.h"
 #include "base/objectlock.h"
 #include "base/logger_fwd.h"
+#include "base/convert.h"
 #include <boost/smart_ptr/make_shared.hpp>
 #include <boost/foreach.hpp>
 #include <boost/exception/diagnostic_information.hpp>
@@ -460,6 +461,13 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
 
 	olock.Unlock();
 
+	Log(LogDebug, "icinga", "Flapping: Service " +
+			GetName() + " was: " +
+			Convert::ToString(was_flapping) + " is: " +
+			Convert::ToString(was_flapping) + " threshold: " +
+			Convert::ToString(GetFlappingThreshold()) + "% current: " +
+			Convert::ToString(GetFlappingCurrent()) + "%.");
+
 	/* Flush the object so other instances see the service's
 	 * new state when they receive the CheckResult message */
 	Flush();
@@ -495,6 +503,8 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
 		rm.SetParams(params);
 
 		EndpointManager::GetInstance()->SendMulticastMessage(rm);
+
+		Log(LogDebug, "icinga", "Flapping: Service " + GetName() + " started flapping (" + Convert::ToString(GetFlappingThreshold()) + "% < " + Convert::ToString(GetFlappingCurrent()) + "%).");
 	}
 	else if (was_flapping && !is_flapping) {
 		RequestNotifications(NotificationFlappingEnd, cr);
@@ -509,6 +519,8 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
 		rm.SetParams(params);
 
 		EndpointManager::GetInstance()->SendMulticastMessage(rm);
+
+		Log(LogDebug, "icinga", "Flapping: Service " + GetName() + " stopped flapping (" + Convert::ToString(GetFlappingThreshold()) + "% >= " + Convert::ToString(GetFlappingCurrent()) + "%).");
 	}
 	else if (send_notification)
 		RequestNotifications(recovery ? NotificationRecovery : NotificationProblem, cr);
diff --git a/lib/icinga/service-flapping.cpp b/lib/icinga/service-flapping.cpp
index cdac8a310..b3d5106c2 100644
--- a/lib/icinga/service-flapping.cpp
+++ b/lib/icinga/service-flapping.cpp
@@ -38,6 +38,9 @@ double Service::GetFlappingCurrent(void) const
 	if (m_FlappingNegative.IsEmpty() || m_FlappingPositive.IsEmpty())
 		return 0;
 
+	if ((m_FlappingPositive + m_FlappingNegative) <= 0)
+		return 0;
+
 	return 100 * m_FlappingPositive / (m_FlappingPositive + m_FlappingNegative);
 }