Mismatching apply rules and parent objects: give time by rule and per object

This commit is contained in:
Alexander A. Klimov 2022-11-14 17:21:15 +01:00
parent 2e38e24a31
commit 3ef0917dd9
17 changed files with 241 additions and 148 deletions

View File

@ -421,7 +421,7 @@ void ConfigObject::OnAllConfigLoaded()
m_Zone = ctype->GetObject(zoneName); m_Zone = ctype->GetObject(zoneName);
} }
void ConfigObject::CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void ConfigObject::CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
/* Nothing to do here. */ /* Nothing to do here. */
} }

View File

@ -14,7 +14,7 @@ namespace icinga
{ {
class ConfigType; class ConfigType;
class TotalTimeSpentOnApplyMismatches; class TimeSpentOnApplyMismatches;
/** /**
* A dynamic object that can be instantiated from the configuration file. * A dynamic object that can be instantiated from the configuration file.
@ -56,7 +56,7 @@ public:
virtual void Resume(); virtual void Resume();
virtual void OnConfigLoaded(); virtual void OnConfigLoaded();
virtual void CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); virtual void CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
virtual void OnAllConfigLoaded(); virtual void OnAllConfigLoaded();
virtual void OnStateLoaded(); virtual void OnStateLoaded();

View File

@ -2,6 +2,7 @@
#include "config/applyrule.hpp" #include "config/applyrule.hpp"
#include "base/logger.hpp" #include "base/logger.hpp"
#include <algorithm>
#include <set> #include <set>
#include <unordered_set> #include <unordered_set>
@ -198,9 +199,45 @@ void ApplyRule::CheckMatches(const ApplyRule::Ptr& rule, Type* sourceType, bool
} }
} }
double TotalTimeSpentOnApplyMismatches::AsSeconds() const static double MonotonicTicksToSeconds(std::chrono::steady_clock::rep ticks)
{ {
using namespace std::chrono; using namespace std::chrono;
return duration<double, seconds::period>(steady_clock::duration(m_MonotonicTicks.load())).count(); return duration<double, seconds::period>(steady_clock::duration(ticks)).count();
}
double TimeSpentOnApplyMismatches::GetTotal()
{
std::chrono::steady_clock::rep total = 0;
{
boost::shared_lock<boost::shared_mutex> lock (m_Mutex);
for (auto& kv : m_ByRule) {
total += kv.second.MonotonicTicks.load();
}
}
return MonotonicTicksToSeconds(total);
}
std::vector<TimeSpentOnApplyMismatches::BadRule> TimeSpentOnApplyMismatches::GetWorstRules()
{
std::vector<BadRule> worstRules;
{
boost::shared_lock<boost::shared_mutex> lock (m_Mutex);
for (auto& kv : m_ByRule) {
worstRules.push_back({
kv.first, kv.second.ParentObjects.load(),MonotonicTicksToSeconds(kv.second.MonotonicTicks.load())
});
}
}
std::sort(worstRules.begin(), worstRules.end(), [](const BadRule& lhs, const BadRule& rhs) {
return lhs.SpentTime / lhs.ParentObjects > rhs.SpentTime / rhs.ParentObjects;
});
return worstRules;
} }

View File

@ -5,12 +5,18 @@
#include "config/i2-config.hpp" #include "config/i2-config.hpp"
#include "config/expression.hpp" #include "config/expression.hpp"
#include "base/atomic.hpp"
#include "base/debuginfo.hpp" #include "base/debuginfo.hpp"
#include "base/shared-object.hpp" #include "base/shared-object.hpp"
#include "base/type.hpp" #include "base/type.hpp"
#include <atomic>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <chrono> #include <chrono>
#include <cstdint>
#include <map>
#include <unordered_map> #include <unordered_map>
#include <utility>
#include <vector>
namespace icinga namespace icinga
{ {
@ -114,28 +120,44 @@ private:
class BenchmarkApplyRuleEvaluation; class BenchmarkApplyRuleEvaluation;
class TotalTimeSpentOnApplyMismatches class TimeSpentOnApplyMismatches
{ {
friend BenchmarkApplyRuleEvaluation; friend BenchmarkApplyRuleEvaluation;
public: public:
TotalTimeSpentOnApplyMismatches() = default; struct BadRule
TotalTimeSpentOnApplyMismatches(const TotalTimeSpentOnApplyMismatches&) = delete; {
TotalTimeSpentOnApplyMismatches(TotalTimeSpentOnApplyMismatches&&) = delete; ApplyRule::Ptr Rule;
TotalTimeSpentOnApplyMismatches& operator=(const TotalTimeSpentOnApplyMismatches&) = delete; uint_fast32_t ParentObjects;
TotalTimeSpentOnApplyMismatches& operator=(TotalTimeSpentOnApplyMismatches&&) = delete; double SpentTime;
};
double AsSeconds() const; TimeSpentOnApplyMismatches() = default;
TimeSpentOnApplyMismatches(const TimeSpentOnApplyMismatches&) = delete;
TimeSpentOnApplyMismatches(TimeSpentOnApplyMismatches&&) = delete;
TimeSpentOnApplyMismatches& operator=(const TimeSpentOnApplyMismatches&) = delete;
TimeSpentOnApplyMismatches& operator=(TimeSpentOnApplyMismatches&&) = delete;
double GetTotal();
std::vector<BadRule> GetWorstRules();
private: private:
Atomic<std::chrono::steady_clock::rep> m_MonotonicTicks {0}; struct PerRule
{
std::atomic<uint_fast32_t> ParentObjects;
std::atomic<std::chrono::steady_clock::rep> MonotonicTicks;
};
boost::shared_mutex m_Mutex;
std::map<ApplyRule::Ptr, PerRule> m_ByRule;
}; };
class BenchmarkApplyRuleEvaluation class BenchmarkApplyRuleEvaluation
{ {
public: public:
inline BenchmarkApplyRuleEvaluation(TotalTimeSpentOnApplyMismatches& totalTimeSpentOnMismatches, const bool& ruleMatched) inline BenchmarkApplyRuleEvaluation(TimeSpentOnApplyMismatches& timeSpentOnMismatches,
: m_TotalTimeSpentOnMismatches(totalTimeSpentOnMismatches), const ApplyRule::Ptr& rule, const bool& ruleMatched)
: m_TimeSpentOnMismatches(timeSpentOnMismatches), m_Rule(rule),
m_RuleMatched(ruleMatched), m_Start(std::chrono::steady_clock::now()) m_RuleMatched(ruleMatched), m_Start(std::chrono::steady_clock::now())
{ } { }
@ -147,14 +169,32 @@ public:
inline ~BenchmarkApplyRuleEvaluation() inline ~BenchmarkApplyRuleEvaluation()
{ {
if (!m_RuleMatched) { if (!m_RuleMatched) {
m_TotalTimeSpentOnMismatches.m_MonotonicTicks.fetch_add( auto diff (std::chrono::steady_clock::now() - m_Start);
(std::chrono::steady_clock::now() - m_Start).count() TimeSpentOnApplyMismatches::PerRule* total = nullptr;
); auto& mtbr (m_TimeSpentOnMismatches.m_ByRule);
{
boost::shared_lock<boost::shared_mutex> lock (m_TimeSpentOnMismatches.m_Mutex);
auto perRule (mtbr.find(m_Rule));
if (perRule != mtbr.end()) {
total = &perRule->second;
}
}
if (!total) {
boost::unique_lock<boost::shared_mutex> lock (m_TimeSpentOnMismatches.m_Mutex);
total = &mtbr[m_Rule];
}
total->ParentObjects.fetch_add(1);
total->MonotonicTicks.fetch_add(diff.count());
} }
} }
private: private:
TotalTimeSpentOnApplyMismatches& m_TotalTimeSpentOnMismatches; TimeSpentOnApplyMismatches& m_TimeSpentOnMismatches;
const ApplyRule::Ptr& m_Rule;
const bool& m_RuleMatched; const bool& m_RuleMatched;
std::chrono::steady_clock::time_point m_Start; std::chrono::steady_clock::time_point m_Start;
}; };

View File

@ -387,7 +387,7 @@ ConfigItem::Ptr ConfigItem::GetByTypeAndName(const Type::Ptr& type, const String
bool ConfigItem::CommitNewItems( bool ConfigItem::CommitNewItems(
const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems, const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches
) )
{ {
typedef std::pair<ConfigItem::Ptr, bool> ItemPair; typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
@ -598,14 +598,14 @@ bool ConfigItem::CommitNewItems(
auto items (itemsByType.find(loadDep)); auto items (itemsByType.find(loadDep));
if (items != itemsByType.end()) { if (items != itemsByType.end()) {
upq.ParallelFor(items->second, [&type, &notified_items, &totalTimeSpentOnApplyMismatches](const ItemPair& ip) { upq.ParallelFor(items->second, [&type, &notified_items, &timeSpentOnApplyMismatches](const ItemPair& ip) {
const ConfigItem::Ptr& item = ip.first; const ConfigItem::Ptr& item = ip.first;
if (!item->m_Object) if (!item->m_Object)
return; return;
ActivationScope ascope(item->m_ActivationContext); ActivationScope ascope(item->m_ActivationContext);
item->m_Object->CreateChildObjects(type, totalTimeSpentOnApplyMismatches); item->m_Object->CreateChildObjects(type, timeSpentOnApplyMismatches);
notified_items++; notified_items++;
}); });
} }
@ -623,7 +623,7 @@ bool ConfigItem::CommitNewItems(
return false; return false;
// Make sure to activate any additionally generated items // Make sure to activate any additionally generated items
if (!CommitNewItems(context, upq, newItems, totalTimeSpentOnApplyMismatches)) if (!CommitNewItems(context, upq, newItems, timeSpentOnApplyMismatches))
return false; return false;
} }
} }
@ -636,9 +636,9 @@ bool ConfigItem::CommitItems(const ActivationContext::Ptr& context, WorkQueue& u
if (!silent) if (!silent)
Log(LogInformation, "ConfigItem", "Committing config item(s)."); Log(LogInformation, "ConfigItem", "Committing config item(s).");
TotalTimeSpentOnApplyMismatches totalTimeSpentOnApplyMismatches; TimeSpentOnApplyMismatches timeSpentOnApplyMismatches;
if (!CommitNewItems(context, upq, newItems, totalTimeSpentOnApplyMismatches)) { if (!CommitNewItems(context, upq, newItems, timeSpentOnApplyMismatches)) {
upq.ReportExceptions("config"); upq.ReportExceptions("config");
for (const ConfigItem::Ptr& item : newItems) { for (const ConfigItem::Ptr& item : newItems) {
@ -652,11 +652,23 @@ bool ConfigItem::CommitItems(const ActivationContext::Ptr& context, WorkQueue& u
if (!silent) { if (!silent) {
Log(LogNotice, "ConfigItem") Log(LogNotice, "ConfigItem")
<< "Spent " << totalTimeSpentOnApplyMismatches.AsSeconds() << "Spent " << timeSpentOnApplyMismatches.GetTotal()
<< " seconds on evaluating mismatching apply rules and parent objects." << " seconds on evaluating mismatching apply rules and parent objects."
<< " (This summary isn't aware of apply rules being evaluated in parallel." << " (This summary isn't aware of apply rules being evaluated in parallel."
<< " Therefore consider dividing the number by amount of CPU cores according to htop.)"; << " Therefore consider dividing the number by amount of CPU cores according to htop.)";
if (LogDebug >= Logger::GetMinLogSeverity()) {
for (auto& perRule: timeSpentOnApplyMismatches.GetWorstRules()) {
std::ostringstream oss;
ShowCodeLocation(oss, perRule.Rule->GetDebugInfo());
Log(LogDebug, "ConfigItem")
<< "Spent " << (perRule.SpentTime * 1000 / perRule.ParentObjects)
<< "ms on evaluating apply rule per mismatching parent object (total: "
<< (perRule.SpentTime * 1000) << "ms): " << oss.str();
}
}
/* log stats for external parsers */ /* log stats for external parsers */
typedef std::map<Type::Ptr, int> ItemCountMap; typedef std::map<Type::Ptr, int> ItemCountMap;
ItemCountMap itemCounts; ItemCountMap itemCounts;

View File

@ -101,7 +101,7 @@ private:
static bool CommitNewItems( static bool CommitNewItems(
const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems, const ActivationContext::Ptr& context, WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches
); );
}; };

View File

@ -62,12 +62,12 @@ bool Dependency::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, cons
return true; return true;
} }
bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule& rule, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter) bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyRule::Ptr& rule, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter)
{ {
bool match = false; bool match = false;
BenchmarkApplyRuleEvaluation bare (totalTimeSpentOnApplyMismatches, match); BenchmarkApplyRuleEvaluation bare (timeSpentOnApplyMismatches, rule, match);
auto& di (rule.GetDebugInfo()); auto& di (rule->GetDebugInfo());
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
@ -75,11 +75,11 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
ScriptFrame frame (false); ScriptFrame frame (false);
if (rule.GetScope() || rule.GetFTerm()) { if (rule->GetScope() || rule->GetFTerm()) {
frame.Locals = new Dictionary(); frame.Locals = new Dictionary();
if (rule.GetScope()) { if (rule->GetScope()) {
rule.GetScope()->CopyTo(frame.Locals); rule->GetScope()->CopyTo(frame.Locals);
} }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals); checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
@ -88,80 +88,80 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
frame.Locals = checkable->GetFrozenLocalsForApply(); frame.Locals = checkable->GetFrozenLocalsForApply();
} }
if (rule.GetFTerm()) { if (rule->GetFTerm()) {
Value vinstances; Value vinstances;
try { try {
vinstances = rule.GetFTerm()->Evaluate(frame); vinstances = rule->GetFTerm()->Evaluate(frame);
} catch (const std::exception&) { } catch (const std::exception&) {
/* Silently ignore errors here and assume there are no instances. */ /* Silently ignore errors here and assume there are no instances. */
return false; return false;
} }
if (vinstances.IsObjectType<Array>()) { if (vinstances.IsObjectType<Array>()) {
if (!rule.GetFVVar().IsEmpty()) if (!rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
ObjectLock olock(arr); ObjectLock olock(arr);
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule->GetName();
frame.Locals->Set(rule.GetFKVar(), instance, true); frame.Locals->Set(rule->GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, *rule, skipFilter))
match = true; match = true;
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) if (rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
Dictionary::Ptr dict = vinstances; Dictionary::Ptr dict = vinstances;
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first, true); frame.Locals->Set(rule->GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second, true); frame.Locals->Set(rule->GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule->GetName() + kv.first, frame, *rule, skipFilter))
match = true; match = true;
} }
} }
} else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { } else if (EvaluateApplyRuleInstance(checkable, rule->GetName(), frame, *rule, skipFilter)) {
match = true; match = true;
} }
return match; return match;
} }
void Dependency::EvaluateApplyRules(const Host::Ptr& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Dependency::EvaluateApplyRules(const Host::Ptr& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(Dependency::TypeInstance, Host::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(Dependency::TypeInstance, Host::TypeInstance)) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedHostRules(Dependency::TypeInstance, host->GetName())) { for (auto& rule : ApplyRule::GetTargetedHostRules(Dependency::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }
void Dependency::EvaluateApplyRules(const Service::Ptr& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Dependency::EvaluateApplyRules(const Service::Ptr& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(Dependency::TypeInstance, Service::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(Dependency::TypeInstance, Service::TypeInstance)) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedServiceRules(Dependency::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) { for (auto& rule : ApplyRule::GetTargetedServiceRules(Dependency::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }

View File

@ -3,6 +3,7 @@
#ifndef DEPENDENCY_H #ifndef DEPENDENCY_H
#define DEPENDENCY_H #define DEPENDENCY_H
#include "config/applyrule.hpp"
#include "icinga/i2-icinga.hpp" #include "icinga/i2-icinga.hpp"
#include "icinga/dependency-ti.hpp" #include "icinga/dependency-ti.hpp"
@ -34,8 +35,8 @@ public:
void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
/* Note: Only use them for unit test mocks. Prefer OnConfigLoaded(). */ /* Note: Only use them for unit test mocks. Prefer OnConfigLoaded(). */
void SetParent(intrusive_ptr<Checkable> parent); void SetParent(intrusive_ptr<Checkable> parent);
@ -53,8 +54,8 @@ private:
static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter); static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter);
static bool EvaluateApplyRule( static bool EvaluateApplyRule(
const Checkable::Ptr& checkable, const ApplyRule& rule, const Checkable::Ptr& checkable, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter = false TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter = false
); );
}; };

View File

@ -47,19 +47,19 @@ void Host::OnAllConfigLoaded()
} }
} }
void Host::CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Host::CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
if (childType == ScheduledDowntime::TypeInstance) if (childType == ScheduledDowntime::TypeInstance)
ScheduledDowntime::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); ScheduledDowntime::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
if (childType == Notification::TypeInstance) if (childType == Notification::TypeInstance)
Notification::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); Notification::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
if (childType == Dependency::TypeInstance) if (childType == Dependency::TypeInstance)
Dependency::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); Dependency::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
if (childType == Service::TypeInstance) if (childType == Service::TypeInstance)
Service::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); Service::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
} }
void Host::Stop(bool runtimeRemoved) void Host::Stop(bool runtimeRemoved)

View File

@ -55,7 +55,7 @@ public:
protected: protected:
void Stop(bool runtimeRemoved) override; void Stop(bool runtimeRemoved) override;
void CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) override; void CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches) override;
Dictionary::Ptr MakeLocalsForApply() override; Dictionary::Ptr MakeLocalsForApply() override;

View File

@ -62,14 +62,14 @@ bool Notification::EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, co
} }
bool Notification::EvaluateApplyRule( bool Notification::EvaluateApplyRule(
const Checkable::Ptr& checkable, const ApplyRule& rule, const Checkable::Ptr& checkable, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter
) )
{ {
bool match = false; bool match = false;
BenchmarkApplyRuleEvaluation bare (totalTimeSpentOnApplyMismatches, match); BenchmarkApplyRuleEvaluation bare (timeSpentOnApplyMismatches, rule, match);
auto& di (rule.GetDebugInfo()); auto& di (rule->GetDebugInfo());
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
@ -77,11 +77,11 @@ bool Notification::EvaluateApplyRule(
ScriptFrame frame (false); ScriptFrame frame (false);
if (rule.GetScope() || rule.GetFTerm()) { if (rule->GetScope() || rule->GetFTerm()) {
frame.Locals = new Dictionary(); frame.Locals = new Dictionary();
if (rule.GetScope()) { if (rule->GetScope()) {
rule.GetScope()->CopyTo(frame.Locals); rule->GetScope()->CopyTo(frame.Locals);
} }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals); checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
@ -90,81 +90,81 @@ bool Notification::EvaluateApplyRule(
frame.Locals = checkable->GetFrozenLocalsForApply(); frame.Locals = checkable->GetFrozenLocalsForApply();
} }
if (rule.GetFTerm()) { if (rule->GetFTerm()) {
Value vinstances; Value vinstances;
try { try {
vinstances = rule.GetFTerm()->Evaluate(frame); vinstances = rule->GetFTerm()->Evaluate(frame);
} catch (const std::exception&) { } catch (const std::exception&) {
/* Silently ignore errors here and assume there are no instances. */ /* Silently ignore errors here and assume there are no instances. */
return false; return false;
} }
if (vinstances.IsObjectType<Array>()) { if (vinstances.IsObjectType<Array>()) {
if (!rule.GetFVVar().IsEmpty()) if (!rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
ObjectLock olock(arr); ObjectLock olock(arr);
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule->GetName();
frame.Locals->Set(rule.GetFKVar(), instance, true); frame.Locals->Set(rule->GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, *rule, skipFilter))
match = true; match = true;
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) if (rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
Dictionary::Ptr dict = vinstances; Dictionary::Ptr dict = vinstances;
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first, true); frame.Locals->Set(rule->GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second, true); frame.Locals->Set(rule->GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule->GetName() + kv.first, frame, *rule, skipFilter))
match = true; match = true;
} }
} }
} else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { } else if (EvaluateApplyRuleInstance(checkable, rule->GetName(), frame, *rule, skipFilter)) {
match = true; match = true;
} }
return match; return match;
} }
void Notification::EvaluateApplyRules(const Host::Ptr& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Notification::EvaluateApplyRules(const Host::Ptr& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(Notification::TypeInstance, Host::TypeInstance)) for (auto& rule : ApplyRule::GetRules(Notification::TypeInstance, Host::TypeInstance))
{ {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedHostRules(Notification::TypeInstance, host->GetName())) { for (auto& rule : ApplyRule::GetTargetedHostRules(Notification::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }
void Notification::EvaluateApplyRules(const Service::Ptr& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Notification::EvaluateApplyRules(const Service::Ptr& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(Notification::TypeInstance, Service::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(Notification::TypeInstance, Service::TypeInstance)) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedServiceRules(Notification::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) { for (auto& rule : ApplyRule::GetTargetedServiceRules(Notification::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }

View File

@ -3,6 +3,7 @@
#ifndef NOTIFICATION_H #ifndef NOTIFICATION_H
#define NOTIFICATION_H #define NOTIFICATION_H
#include "config/applyrule.hpp"
#include "icinga/i2-icinga.hpp" #include "icinga/i2-icinga.hpp"
#include "icinga/notification-ti.hpp" #include "icinga/notification-ti.hpp"
#include "icinga/checkable-ti.hpp" #include "icinga/checkable-ti.hpp"
@ -99,8 +100,8 @@ public:
void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
void ValidateTimes(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateTimes(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
static const std::map<String, int>& GetStateFilterMap(); static const std::map<String, int>& GetStateFilterMap();
static const std::map<String, int>& GetTypeFilterMap(); static const std::map<String, int>& GetTypeFilterMap();
@ -121,8 +122,8 @@ private:
static bool EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter); static bool EvaluateApplyRuleInstance(const intrusive_ptr<Checkable>& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter);
static bool EvaluateApplyRule( static bool EvaluateApplyRule(
const intrusive_ptr<Checkable>& checkable, const ApplyRule& rule, const intrusive_ptr<Checkable>& checkable, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter = false TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter = false
); );
static std::map<String, int> m_StateFilterMap; static std::map<String, int> m_StateFilterMap;

View File

@ -61,14 +61,14 @@ bool ScheduledDowntime::EvaluateApplyRuleInstance(const Checkable::Ptr& checkabl
} }
bool ScheduledDowntime::EvaluateApplyRule( bool ScheduledDowntime::EvaluateApplyRule(
const Checkable::Ptr& checkable, const ApplyRule& rule, const Checkable::Ptr& checkable, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter
) )
{ {
bool match = false; bool match = false;
BenchmarkApplyRuleEvaluation bare (totalTimeSpentOnApplyMismatches, match); BenchmarkApplyRuleEvaluation bare (timeSpentOnApplyMismatches, rule, match);
auto& di (rule.GetDebugInfo()); auto& di (rule->GetDebugInfo());
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
@ -76,11 +76,11 @@ bool ScheduledDowntime::EvaluateApplyRule(
ScriptFrame frame (false); ScriptFrame frame (false);
if (rule.GetScope() || rule.GetFTerm()) { if (rule->GetScope() || rule->GetFTerm()) {
frame.Locals = new Dictionary(); frame.Locals = new Dictionary();
if (rule.GetScope()) { if (rule->GetScope()) {
rule.GetScope()->CopyTo(frame.Locals); rule->GetScope()->CopyTo(frame.Locals);
} }
checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals); checkable->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
@ -89,80 +89,80 @@ bool ScheduledDowntime::EvaluateApplyRule(
frame.Locals = checkable->GetFrozenLocalsForApply(); frame.Locals = checkable->GetFrozenLocalsForApply();
} }
if (rule.GetFTerm()) { if (rule->GetFTerm()) {
Value vinstances; Value vinstances;
try { try {
vinstances = rule.GetFTerm()->Evaluate(frame); vinstances = rule->GetFTerm()->Evaluate(frame);
} catch (const std::exception&) { } catch (const std::exception&) {
/* Silently ignore errors here and assume there are no instances. */ /* Silently ignore errors here and assume there are no instances. */
return false; return false;
} }
if (vinstances.IsObjectType<Array>()) { if (vinstances.IsObjectType<Array>()) {
if (!rule.GetFVVar().IsEmpty()) if (!rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
ObjectLock olock(arr); ObjectLock olock(arr);
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule->GetName();
frame.Locals->Set(rule.GetFKVar(), instance, true); frame.Locals->Set(rule->GetFKVar(), instance, true);
name += instance; name += instance;
if (EvaluateApplyRuleInstance(checkable, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, name, frame, *rule, skipFilter))
match = true; match = true;
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) if (rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
Dictionary::Ptr dict = vinstances; Dictionary::Ptr dict = vinstances;
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first, true); frame.Locals->Set(rule->GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second, true); frame.Locals->Set(rule->GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(checkable, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(checkable, rule->GetName() + kv.first, frame, *rule, skipFilter))
match = true; match = true;
} }
} }
} else if (EvaluateApplyRuleInstance(checkable, rule.GetName(), frame, rule, skipFilter)) { } else if (EvaluateApplyRuleInstance(checkable, rule->GetName(), frame, *rule, skipFilter)) {
match = true; match = true;
} }
return match; return match;
} }
void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(ScheduledDowntime::TypeInstance, Host::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(ScheduledDowntime::TypeInstance, Host::TypeInstance)) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedHostRules(ScheduledDowntime::TypeInstance, host->GetName())) { for (auto& rule : ApplyRule::GetTargetedHostRules(ScheduledDowntime::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }
void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for service '" + service->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(ScheduledDowntime::TypeInstance, Service::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(ScheduledDowntime::TypeInstance, Service::TypeInstance)) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedServiceRules(ScheduledDowntime::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) { for (auto& rule : ApplyRule::GetTargetedServiceRules(ScheduledDowntime::TypeInstance, service->GetHost()->GetName(), service->GetShortName())) {
if (EvaluateApplyRule(service, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(service, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }

View File

@ -3,6 +3,7 @@
#ifndef SCHEDULEDDOWNTIME_H #ifndef SCHEDULEDDOWNTIME_H
#define SCHEDULEDDOWNTIME_H #define SCHEDULEDDOWNTIME_H
#include "config/applyrule.hpp"
#include "icinga/i2-icinga.hpp" #include "icinga/i2-icinga.hpp"
#include "icinga/scheduleddowntime-ti.hpp" #include "icinga/scheduleddowntime-ti.hpp"
#include "icinga/checkable.hpp" #include "icinga/checkable.hpp"
@ -29,8 +30,8 @@ public:
Checkable::Ptr GetCheckable() const; Checkable::Ptr GetCheckable() const;
static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Host>& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const intrusive_ptr<Service>& service, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
static bool AllConfigIsLoaded(); static bool AllConfigIsLoaded();
void ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
@ -54,8 +55,8 @@ private:
static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter); static bool EvaluateApplyRuleInstance(const Checkable::Ptr& checkable, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter);
static bool EvaluateApplyRule( static bool EvaluateApplyRule(
const Checkable::Ptr& checkable, const ApplyRule& rule, const Checkable::Ptr& checkable, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter = false TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter = false
); );
}; };

View File

@ -56,14 +56,14 @@ bool Service::EvaluateApplyRuleInstance(const Host::Ptr& host, const String& nam
} }
bool Service::EvaluateApplyRule( bool Service::EvaluateApplyRule(
const Host::Ptr& host, const ApplyRule& rule, const Host::Ptr& host, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter
) )
{ {
bool match = false; bool match = false;
BenchmarkApplyRuleEvaluation bare (totalTimeSpentOnApplyMismatches, match); BenchmarkApplyRuleEvaluation bare (timeSpentOnApplyMismatches, rule, match);
auto& di (rule.GetDebugInfo()); auto& di (rule->GetDebugInfo());
std::ostringstream msgbuf; std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")"; msgbuf << "Evaluating 'apply' rule (" << di << ")";
@ -71,11 +71,11 @@ bool Service::EvaluateApplyRule(
ScriptFrame frame (false); ScriptFrame frame (false);
if (rule.GetScope() || rule.GetFTerm()) { if (rule->GetScope() || rule->GetFTerm()) {
frame.Locals = new Dictionary(); frame.Locals = new Dictionary();
if (rule.GetScope()) { if (rule->GetScope()) {
rule.GetScope()->CopyTo(frame.Locals); rule->GetScope()->CopyTo(frame.Locals);
} }
host->GetFrozenLocalsForApply()->CopyTo(frame.Locals); host->GetFrozenLocalsForApply()->CopyTo(frame.Locals);
@ -84,67 +84,67 @@ bool Service::EvaluateApplyRule(
frame.Locals = host->GetFrozenLocalsForApply(); frame.Locals = host->GetFrozenLocalsForApply();
} }
if (rule.GetFTerm()) { if (rule->GetFTerm()) {
Value vinstances; Value vinstances;
try { try {
vinstances = rule.GetFTerm()->Evaluate(frame); vinstances = rule->GetFTerm()->Evaluate(frame);
} catch (const std::exception&) { } catch (const std::exception&) {
/* Silently ignore errors here and assume there are no instances. */ /* Silently ignore errors here and assume there are no instances. */
return false; return false;
} }
if (vinstances.IsObjectType<Array>()) { if (vinstances.IsObjectType<Array>()) {
if (!rule.GetFVVar().IsEmpty()) if (!rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di)); BOOST_THROW_EXCEPTION(ScriptError("Dictionary iterator requires value to be a dictionary.", di));
Array::Ptr arr = vinstances; Array::Ptr arr = vinstances;
ObjectLock olock(arr); ObjectLock olock(arr);
for (const Value& instance : arr) { for (const Value& instance : arr) {
String name = rule.GetName(); String name = rule->GetName();
if (!rule.GetFKVar().IsEmpty()) { if (!rule->GetFKVar().IsEmpty()) {
frame.Locals->Set(rule.GetFKVar(), instance, true); frame.Locals->Set(rule->GetFKVar(), instance, true);
name += instance; name += instance;
} }
if (EvaluateApplyRuleInstance(host, name, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(host, name, frame, *rule, skipFilter))
match = true; match = true;
} }
} else if (vinstances.IsObjectType<Dictionary>()) { } else if (vinstances.IsObjectType<Dictionary>()) {
if (rule.GetFVVar().IsEmpty()) if (rule->GetFVVar().IsEmpty())
BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di)); BOOST_THROW_EXCEPTION(ScriptError("Array iterator requires value to be an array.", di));
Dictionary::Ptr dict = vinstances; Dictionary::Ptr dict = vinstances;
ObjectLock olock (dict); ObjectLock olock (dict);
for (auto& kv : dict) { for (auto& kv : dict) {
frame.Locals->Set(rule.GetFKVar(), kv.first, true); frame.Locals->Set(rule->GetFKVar(), kv.first, true);
frame.Locals->Set(rule.GetFVVar(), kv.second, true); frame.Locals->Set(rule->GetFVVar(), kv.second, true);
if (EvaluateApplyRuleInstance(host, rule.GetName() + kv.first, frame, rule, skipFilter)) if (EvaluateApplyRuleInstance(host, rule->GetName() + kv.first, frame, *rule, skipFilter))
match = true; match = true;
} }
} }
} else if (EvaluateApplyRuleInstance(host, rule.GetName(), frame, rule, skipFilter)) { } else if (EvaluateApplyRuleInstance(host, rule->GetName(), frame, *rule, skipFilter)) {
match = true; match = true;
} }
return match; return match;
} }
void Service::EvaluateApplyRules(const Host::Ptr& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Service::EvaluateApplyRules(const Host::Ptr& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'"); CONTEXT("Evaluating 'apply' rules for host '" + host->GetName() + "'");
for (auto& rule : ApplyRule::GetRules(Service::TypeInstance, Host::TypeInstance)) { for (auto& rule : ApplyRule::GetRules(Service::TypeInstance, Host::TypeInstance)) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches))
rule->AddMatch(); rule->AddMatch();
} }
for (auto& rule : ApplyRule::GetTargetedHostRules(Service::TypeInstance, host->GetName())) { for (auto& rule : ApplyRule::GetTargetedHostRules(Service::TypeInstance, host->GetName())) {
if (EvaluateApplyRule(host, *rule, totalTimeSpentOnApplyMismatches, true)) if (EvaluateApplyRule(host, rule, timeSpentOnApplyMismatches, true))
rule->AddMatch(); rule->AddMatch();
} }
} }

View File

@ -74,16 +74,16 @@ void Service::OnAllConfigLoaded()
} }
} }
void Service::CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) void Service::CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches)
{ {
if (childType == ScheduledDowntime::TypeInstance) if (childType == ScheduledDowntime::TypeInstance)
ScheduledDowntime::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); ScheduledDowntime::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
if (childType == Notification::TypeInstance) if (childType == Notification::TypeInstance)
Notification::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); Notification::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
if (childType == Dependency::TypeInstance) if (childType == Dependency::TypeInstance)
Dependency::EvaluateApplyRules(this, totalTimeSpentOnApplyMismatches); Dependency::EvaluateApplyRules(this, timeSpentOnApplyMismatches);
} }
Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName) Service::Ptr Service::GetByNamePair(const String& hostName, const String& serviceName)

View File

@ -3,6 +3,7 @@
#ifndef SERVICE_H #ifndef SERVICE_H
#define SERVICE_H #define SERVICE_H
#include "config/applyrule.hpp"
#include "icinga/i2-icinga.hpp" #include "icinga/i2-icinga.hpp"
#include "icinga/service-ti.hpp" #include "icinga/service-ti.hpp"
#include "icinga/macroresolver.hpp" #include "icinga/macroresolver.hpp"
@ -42,14 +43,14 @@ public:
static StateType StateTypeFromString(const String& state); static StateType StateTypeFromString(const String& state);
static String StateTypeToString(StateType state); static String StateTypeToString(StateType state);
static void EvaluateApplyRules(const Host::Ptr& host, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches); static void EvaluateApplyRules(const Host::Ptr& host, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches);
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;
static boost::signals2::signal<void (const Service::Ptr&, const CheckResult::Ptr&, const MessageOrigin::Ptr&)> OnHostProblemChanged; static boost::signals2::signal<void (const Service::Ptr&, const CheckResult::Ptr&, const MessageOrigin::Ptr&)> OnHostProblemChanged;
protected: protected:
void CreateChildObjects(const Type::Ptr& childType, TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches) override; void CreateChildObjects(const Type::Ptr& childType, TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches) override;
Dictionary::Ptr MakeLocalsForApply() override; Dictionary::Ptr MakeLocalsForApply() override;
@ -59,8 +60,8 @@ private:
static bool EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter); static bool EvaluateApplyRuleInstance(const Host::Ptr& host, const String& name, ScriptFrame& frame, const ApplyRule& rule, bool skipFilter);
static bool EvaluateApplyRule( static bool EvaluateApplyRule(
const Host::Ptr& host, const ApplyRule& rule, const Host::Ptr& host, const ApplyRule::Ptr& rule,
TotalTimeSpentOnApplyMismatches& totalTimeSpentOnApplyMismatches, bool skipFilter = false TimeSpentOnApplyMismatches& timeSpentOnApplyMismatches, bool skipFilter = false
); );
}; };