diff --git a/doc/10-icinga-template-library.md b/doc/10-icinga-template-library.md index b9db4e2f711..f7cb867dd27 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 d8e6f20b0c1..a88d7abea58 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" @@ -1905,3 +1906,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 6760160899e..9b9dc42127b 100644 --- a/lib/base/utility.hpp +++ b/lib/base/utility.hpp @@ -137,6 +137,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 6ce28cac440..f01bf03a5ba 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,10 +26,28 @@ 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; - CheckCommand::Ptr command = CheckCommand::ExecuteOverride ? CheckCommand::ExecuteOverride : checkable->GetCheckCommand(); String commandName = command->GetName(); ApiListener::Ptr listener = ApiListener::GetInstance(); @@ -86,7 +105,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 40795495d6b..4c37dd3d010 100644 --- a/lib/methods/icingachecktask.cpp +++ b/lib/methods/icingachecktask.cpp @@ -48,6 +48,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; @@ -151,6 +154,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;