Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

icinga, cluster: add option to limit perfdata #8403

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion doc/10-icinga-template-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a id="itl-icinga-cluster"></a>

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 <a id="itl-icinga-cluster-zone"></a>

Expand Down
46 changes: 46 additions & 0 deletions lib/base/utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<Array>((Object::Ptr)filter));

if (!filterArray) {
return;
}

auto filterStrings (filterArray->ToSet<String>());
Comment on lines +1915 to +1925
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid configuration shouldn't be ignored silently like the first two ifs do (except in the filter == Empty case, but that's valid config). Without having tested this, this also looks to be inconsistent: with (in DSL syntax) filter = 42 it would be ignored whereas I thing filter = [[42]] would throw an exception as [42] can't be casted to String.


for (decltype(perfdata->GetLength()) i = 0; i < perfdata->GetLength(); ++i) {
auto item (perfdata->Get(i));

if (!item.IsObject()) {
continue;
}

auto itemPerfdataValue (dynamic_pointer_cast<PerfdataValue>((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:;
}
Comment on lines +1927 to +1952
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a good place to use std::remove_if. That would avoid the need for goto here and also has linear complexity (though questionably if anyone would notice a difference here).

}
2 changes: 2 additions & 0 deletions lib/base/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 23 additions & 2 deletions lib/methods/clusterchecktask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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();
Expand Down Expand Up @@ -86,7 +105,9 @@ void ClusterCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRe
} else {
/* use feature stats perfdata */
std::pair<Dictionary::Ptr, Array::Ptr> 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);
Expand Down
4 changes: 4 additions & 0 deletions lib/methods/icingachecktask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down