summaryrefslogtreecommitdiffstats
path: root/lib/icinga/checkable-flapping.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/icinga/checkable-flapping.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/icinga/checkable-flapping.cpp b/lib/icinga/checkable-flapping.cpp
new file mode 100644
index 0000000..e905e05
--- /dev/null
+++ b/lib/icinga/checkable-flapping.cpp
@@ -0,0 +1,114 @@
+/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
+
+#include "icinga/checkable.hpp"
+#include "icinga/icingaapplication.hpp"
+#include "base/utility.hpp"
+
+using namespace icinga;
+
+template<typename T>
+struct Bitset
+{
+public:
+ Bitset(T value)
+ : m_Data(value)
+ { }
+
+ void Modify(int index, bool bit)
+ {
+ if (bit)
+ m_Data |= 1 << index;
+ else
+ m_Data &= ~(1 << index);
+ }
+
+ bool Get(int index) const
+ {
+ return m_Data & (1 << index);
+ }
+
+ T GetValue() const
+ {
+ return m_Data;
+ }
+
+private:
+ T m_Data{0};
+};
+
+void Checkable::UpdateFlappingStatus(ServiceState newState)
+{
+ Bitset<unsigned long> stateChangeBuf = GetFlappingBuffer();
+ int oldestIndex = GetFlappingIndex();
+
+ ServiceState lastState = GetFlappingLastState();
+ bool stateChange = false;
+
+ int stateFilter = GetFlappingIgnoreStatesFilter();
+
+ /* Only count as state change if no state filter is set or the new state isn't filtered out */
+ if (stateFilter == -1 || !(ServiceStateToFlappingFilter(newState) & stateFilter)) {
+ stateChange = newState != lastState;
+ SetFlappingLastState(newState);
+ }
+
+ stateChangeBuf.Modify(oldestIndex, stateChange);
+ oldestIndex = (oldestIndex + 1) % 20;
+
+ double stateChanges = 0;
+
+ /* Iterate over our state array and compute a weighted total */
+ for (int i = 0; i < 20; i++) {
+ if (stateChangeBuf.Get((oldestIndex + i) % 20))
+ stateChanges += 0.8 + (0.02 * i);
+ }
+
+ double flappingValue = 100.0 * stateChanges / 20.0;
+
+ bool flapping;
+
+ if (GetFlapping())
+ flapping = flappingValue > GetFlappingThresholdLow();
+ else
+ flapping = flappingValue > GetFlappingThresholdHigh();
+
+ SetFlappingBuffer(stateChangeBuf.GetValue());
+ SetFlappingIndex(oldestIndex);
+ SetFlappingCurrent(flappingValue);
+
+ if (flapping != GetFlapping()) {
+ SetFlapping(flapping, true);
+
+ double ee = GetLastCheckResult()->GetExecutionEnd();
+
+ if (GetEnableFlapping() && IcingaApplication::GetInstance()->GetEnableFlapping()) {
+ OnFlappingChange(this, ee);
+ }
+
+ SetFlappingLastChange(ee);
+ }
+}
+
+bool Checkable::IsFlapping() const
+{
+ if (!GetEnableFlapping() || !IcingaApplication::GetInstance()->GetEnableFlapping())
+ return false;
+ else
+ return GetFlapping();
+}
+
+int Checkable::ServiceStateToFlappingFilter(ServiceState state)
+{
+ switch (state) {
+ case ServiceOK:
+ return StateFilterOK;
+ case ServiceWarning:
+ return StateFilterWarning;
+ case ServiceCritical:
+ return StateFilterCritical;
+ case ServiceUnknown:
+ return StateFilterUnknown;
+ default:
+ VERIFY(!"Invalid state type.");
+ }
+}