From 5a176a7196cab31bfce83dc4963af90ead2e5f16 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 28 Oct 2020 18:42:58 +0100 Subject: [PATCH] icinga, cluster: add option to limit perfdata refs #8124 --- doc/10-icinga-template-library.md | 7 ++++- lib/base/utility.cpp | 46 +++++++++++++++++++++++++++++++ lib/base/utility.hpp | 2 ++ lib/methods/clusterchecktask.cpp | 24 +++++++++++++++- lib/methods/icingachecktask.cpp | 4 +++ 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md index 83377f5c6bc..35eeea0913d 100644 --- a/doc/10-icinga-template-library.md +++ b/doc/10-icinga-template-library.md @@ -83,13 +83,18 @@ Custom variables passed as [command parameters](03-monitoring-basics.md#command- Name | Description -----------------------|--------------- icinga\_min\_version | **Optional.** Required minimum Icinga 2 version, e.g. `2.8.0`. If not satisfied, the state changes to `Critical`. Release packages only. +icinga\_perfdata | **Optional.** Only yield the given performance data. E.g. `[ "*_latency", "*_execution_time" ]` ### cluster Check command for the built-in `cluster` check. This check returns performance data for the current Icinga instance and connected endpoints. -The `cluster` check command does not support any vars. +Custom variables passed as [command parameters](03-monitoring-basics.md#command-passing-parameters): + +Name | Description +-----------------------|--------------- +cluster\_perfdata | **Optional.** Only yield the given performance data. E.g. `[ "*_checks*", "num_*" ]` ### cluster-zone diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 1add7616c61..0d9f7173bdf 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -6,6 +6,7 @@ #include "base/logger.hpp" #include "base/exception.hpp" #include "base/socket.hpp" +#include "base/perfdatavalue.hpp" #include "base/utility.hpp" #include "base/json.hpp" #include "base/objectlock.hpp" @@ -1901,3 +1902,48 @@ bool Utility::ComparePasswords(const String& enteredPassword, const String& actu return result; } + +/** + * Removes all PerfdataValues from perfdata whose labels don't match any pattern of the filter Array. + */ +void Utility::FilterPerfdata(const Array::Ptr& perfdata, const Value& filter) +{ + if (!filter.IsObject()) { + return; + } + + auto filterArray (dynamic_pointer_cast((Object::Ptr)filter)); + + if (!filterArray) { + return; + } + + auto filterStrings (filterArray->ToSet()); + + for (decltype(perfdata->GetLength()) i = 0; i < perfdata->GetLength(); ++i) { + auto item (perfdata->Get(i)); + + if (!item.IsObject()) { + continue; + } + + auto itemPerfdataValue (dynamic_pointer_cast((Object::Ptr)item)); + + if (!itemPerfdataValue) { + continue; + } + + auto label (itemPerfdataValue->GetLabel()); + + for (auto& pattern : filterStrings) { + if (Utility::Match(pattern, label)) { + // continue 2; + goto NextItem; + } + } + + perfdata->Remove(i--); + +NextItem:; + } +} diff --git a/lib/base/utility.hpp b/lib/base/utility.hpp index 4505dc918a5..4149de1e4dd 100644 --- a/lib/base/utility.hpp +++ b/lib/base/utility.hpp @@ -139,6 +139,8 @@ class Utility static bool ComparePasswords(const String& enteredPassword, const String& actualPassword); + static void FilterPerfdata(const Array::Ptr& perfdata, const Value& filter); + #ifdef I2_DEBUG static void SetTime(double); static void IncrementTime(double); diff --git a/lib/methods/clusterchecktask.cpp b/lib/methods/clusterchecktask.cpp index eef3900ea94..34edd8766d7 100644 --- a/lib/methods/clusterchecktask.cpp +++ b/lib/methods/clusterchecktask.cpp @@ -6,6 +6,7 @@ #include "icinga/cib.hpp" #include "icinga/service.hpp" #include "icinga/icingaapplication.hpp" +#include "icinga/macroprocessor.hpp" #include "icinga/checkcommand.hpp" #include "base/application.hpp" #include "base/objectlock.hpp" @@ -25,6 +26,25 @@ void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRe REQUIRE_NOT_NULL(checkable); REQUIRE_NOT_NULL(cr); + CheckCommand::Ptr command = CheckCommand::ExecuteOverride ? CheckCommand::ExecuteOverride : checkable->GetCheckCommand(); + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + MacroProcessor::ResolverList resolvers; + if (MacroResolver::OverrideMacros) + resolvers.emplace_back("override", MacroResolver::OverrideMacros); + + if (service) + resolvers.emplace_back("service", service); + resolvers.emplace_back("host", host); + resolvers.emplace_back("command", command); + resolvers.emplace_back("icinga", IcingaApplication::GetInstance()); + + auto perfdataFilter (MacroProcessor::ResolveMacros("$cluster_perfdata$", resolvers, checkable->GetLastCheckResult(), + nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros)); + if (resolvedMacros && !useResolvedMacros) return; @@ -84,7 +104,9 @@ void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRe } else { /* use feature stats perfdata */ std::pair feature_stats = CIB::GetFeatureStats(); - cr->SetPerformanceData(feature_stats.second); + auto& perfdata (feature_stats.second); + Utility::FilterPerfdata(perfdata, perfdataFilter); + cr->SetPerformanceData(perfdata); cr->SetCommand(commandName); cr->SetState(state); diff --git a/lib/methods/icingachecktask.cpp b/lib/methods/icingachecktask.cpp index d697b6925ed..e21ffda16c0 100644 --- a/lib/methods/icingachecktask.cpp +++ b/lib/methods/icingachecktask.cpp @@ -47,6 +47,9 @@ void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes String icingaMinVersion = MacroProcessor::ResolveMacros("$icinga_min_version$", resolvers, checkable->GetLastCheckResult(), &missingIcingaMinVersion, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros); + auto perfdataFilter (MacroProcessor::ResolveMacros("$icinga_perfdata$", resolvers, checkable->GetLastCheckResult(), + nullptr, MacroProcessor::EscapeCallback(), resolvedMacros, useResolvedMacros)); + if (resolvedMacros && !useResolvedMacros) return; @@ -150,6 +153,7 @@ void IcingaCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes perfdata->Add(new PerfdataValue("sum_bytes_sent_per_second", bytesSentPerSecond)); perfdata->Add(new PerfdataValue("sum_bytes_received_per_second", bytesReceivedPerSecond)); + Utility::FilterPerfdata(perfdata, perfdataFilter); cr->SetPerformanceData(perfdata); ServiceState state = ServiceOK;