Merge pull request #9557 from Icinga/ctx

CONTEXT: lazily evaluate frames to only actually assemble when needed
This commit is contained in:
Julian Brost 2022-11-30 15:13:53 +01:00 committed by GitHub
commit adf5e6e86e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 71 additions and 67 deletions

View File

@ -352,7 +352,7 @@ void ConfigObject::Start(bool runtimeCreated)
void ConfigObject::PreActivate()
{
CONTEXT("Setting 'active' to true for object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'");
CONTEXT("Setting 'active' to true for object '" << GetName() << "' of type '" << GetReflectionType()->GetName() << "'");
ASSERT(!IsActive());
SetActive(true, true);
@ -360,7 +360,7 @@ void ConfigObject::PreActivate()
void ConfigObject::Activate(bool runtimeCreated, const Value& cookie)
{
CONTEXT("Activating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'");
CONTEXT("Activating object '" << GetName() << "' of type '" << GetReflectionType()->GetName() << "'");
{
ObjectLock olock(this);
@ -387,7 +387,7 @@ void ConfigObject::Stop(bool runtimeRemoved)
void ConfigObject::Deactivate(bool runtimeRemoved, const Value& cookie)
{
CONTEXT("Deactivating object '" + GetName() + "' of type '" + GetReflectionType()->GetName() + "'");
CONTEXT("Deactivating object '" << GetName() << "' of type '" << GetReflectionType()->GetName() << "'");
{
ObjectLock olock(this);

View File

@ -3,32 +3,40 @@
#include "base/context.hpp"
#include <boost/thread/tss.hpp>
#include <iostream>
#include <sstream>
#include <utility>
using namespace icinga;
static boost::thread_specific_ptr<std::list<String> > l_Frames;
static boost::thread_specific_ptr<std::vector<std::function<void(std::ostream&)>>> l_Frames;
ContextFrame::ContextFrame(const String& message)
ContextFrame::ContextFrame(std::function<void(std::ostream&)> message)
{
GetFrames().push_front(message);
GetFrames().emplace_back(std::move(message));
}
ContextFrame::~ContextFrame()
{
GetFrames().pop_front();
GetFrames().pop_back();
}
std::list<String>& ContextFrame::GetFrames()
std::vector<std::function<void(std::ostream&)>>& ContextFrame::GetFrames()
{
if (!l_Frames.get())
l_Frames.reset(new std::list<String>());
l_Frames.reset(new std::vector<std::function<void(std::ostream&)>>());
return *l_Frames;
}
ContextTrace::ContextTrace()
: m_Frames(ContextFrame::GetFrames())
{ }
{
for (auto frame (ContextFrame::GetFrames().rbegin()); frame != ContextFrame::GetFrames().rend(); ++frame) {
std::ostringstream oss;
(*frame)(oss);
m_Frames.emplace_back(oss.str());
}
}
void ContextTrace::Print(std::ostream& fp) const
{

View File

@ -5,7 +5,8 @@
#include "base/i2-base.hpp"
#include "base/string.hpp"
#include <list>
#include <functional>
#include <vector>
namespace icinga
{
@ -20,7 +21,7 @@ public:
size_t GetLength() const;
private:
std::list<String> m_Frames;
std::vector<String> m_Frames;
};
std::ostream& operator<<(std::ostream& stream, const ContextTrace& trace);
@ -33,18 +34,21 @@ std::ostream& operator<<(std::ostream& stream, const ContextTrace& trace);
class ContextFrame
{
public:
ContextFrame(const String& message);
ContextFrame(std::function<void(std::ostream&)> message);
~ContextFrame();
private:
static std::list<String>& GetFrames();
static std::vector<std::function<void(std::ostream&)>>& GetFrames();
friend class ContextTrace;
};
/* The currentContextFrame variable has to be volatile in order to prevent
* the compiler from optimizing it away. */
#define CONTEXT(message) volatile icinga::ContextFrame currentContextFrame(message)
#define CONTEXT(message) volatile icinga::ContextFrame currentContextFrame ([&](std::ostream& _CONTEXT_stream) { \
_CONTEXT_stream << message; \
})
}
#endif /* CONTEXT_H */

View File

@ -71,14 +71,14 @@ void CheckResultReader::Stop(bool runtimeRemoved)
*/
void CheckResultReader::ReadTimerHandler() const
{
CONTEXT("Processing check result files in '" + GetSpoolDir() + "'");
CONTEXT("Processing check result files in '" << GetSpoolDir() << "'");
Utility::Glob(GetSpoolDir() + "/c??????.ok", [this](const String& path) { ProcessCheckResultFile(path); }, GlobFile);
}
void CheckResultReader::ProcessCheckResultFile(const String& path) const
{
CONTEXT("Processing check result file '" + path + "'");
CONTEXT("Processing check result file '" << path << "'");
String crfile = String(path.Begin(), path.End() - 3); /* Remove the ".ok" extension. */

View File

@ -235,7 +235,7 @@ std::unique_ptr<Expression> ConfigCompiler::HandleIncludeZones(const String& rel
std::unique_ptr<Expression> ConfigCompiler::CompileStream(const String& path,
std::istream *stream, const String& zone, const String& package)
{
CONTEXT("Compiling configuration stream with name '" + path + "'");
CONTEXT("Compiling configuration stream with name '" << path << "'");
stream->exceptions(std::istream::badbit);
@ -259,7 +259,7 @@ std::unique_ptr<Expression> ConfigCompiler::CompileStream(const String& path,
std::unique_ptr<Expression> ConfigCompiler::CompileFile(const String& path, const String& zone,
const String& package)
{
CONTEXT("Compiling configuration file '" + path + "'");
CONTEXT("Compiling configuration file '" << path << "'");
std::ifstream stream(path.CStr(), std::ifstream::in);

View File

@ -201,7 +201,7 @@ void IdoMysqlConnection::Reconnect()
if (!IsActive())
return;
CONTEXT("Reconnecting to MySQL IDO database '" + GetName() + "'");
CONTEXT("Reconnecting to MySQL IDO database '" << GetName() << "'");
double startTime = Utility::GetTime();

View File

@ -183,7 +183,7 @@ void IdoPgsqlConnection::Reconnect()
{
AssertOnWorkQueue();
CONTEXT("Reconnecting to PostgreSQL IDO database '" + GetName() + "'");
CONTEXT("Reconnecting to PostgreSQL IDO database '" << GetName() << "'");
double startTime = Utility::GetTime();

View File

@ -534,7 +534,7 @@ Checkable::ProcessingResult Checkable::ProcessCheckResult(const CheckResult::Ptr
void Checkable::ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros)
{
CONTEXT("Executing remote check for object '" + GetName() + "'");
CONTEXT("Executing remote check for object '" << GetName() << "'");
double scheduled_start = GetNextCheck();
double before_check = Utility::GetTime();
@ -548,7 +548,7 @@ void Checkable::ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros)
void Checkable::ExecuteCheck()
{
CONTEXT("Executing check for object '" + GetName() + "'");
CONTEXT("Executing check for object '" << GetName() << "'");
/* keep track of scheduling info in case the check type doesn't provide its own information */
double scheduled_start = GetNextCheck();

View File

@ -19,7 +19,7 @@ EventCommand::Ptr Checkable::GetEventCommand() const
void Checkable::ExecuteEventHandler(const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{
CONTEXT("Executing event handler for object '" + GetName() + "'");
CONTEXT("Executing event handler for object '" << GetName() << "'");
if (!IcingaApplication::GetInstance()->GetEnableEventHandlers() || !GetEnableEventHandler())
return;

View File

@ -34,7 +34,7 @@ void Checkable::SendNotifications(NotificationType type, const CheckResult::Ptr&
{
String checkableName = GetName();
CONTEXT("Sending notifications for object '" + checkableName + "'");
CONTEXT("Sending notifications for object '" << checkableName << "'");
bool force = GetForceNextNotification();

View File

@ -66,9 +66,7 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
{
auto& di (rule.GetDebugInfo());
std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str());
CONTEXT("Evaluating 'apply' rule (" << di << ")");
Host::Ptr host;
Service::Ptr service;
@ -134,7 +132,7 @@ bool Dependency::EvaluateApplyRule(const Checkable::Ptr& checkable, const ApplyR
void Dependency::EvaluateApplyRules(const Host::Ptr& host)
{
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)) {
if (EvaluateApplyRule(host, *rule))
@ -149,7 +147,7 @@ void Dependency::EvaluateApplyRules(const Host::Ptr& host)
void Dependency::EvaluateApplyRules(const Service::Ptr& service)
{
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)) {
if (EvaluateApplyRule(service, *rule))

View File

@ -22,7 +22,7 @@ bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr&
{
String groupName = group->GetName();
CONTEXT("Evaluating rule for group '" + groupName + "'");
CONTEXT("Evaluating rule for group '" << groupName << "'");
ScriptFrame frame(true);
if (group->GetScope())
@ -45,7 +45,7 @@ bool HostGroup::EvaluateObjectRule(const Host::Ptr& host, const ConfigItem::Ptr&
void HostGroup::EvaluateObjectRules(const Host::Ptr& host)
{
CONTEXT("Evaluating group memberships for host '" + host->GetName() + "'");
CONTEXT("Evaluating group memberships for host '" << host->GetName() << "'");
for (const ConfigItem::Ptr& group : ConfigItem::GetItems(HostGroup::TypeInstance))
{

View File

@ -76,7 +76,7 @@ Value MacroProcessor::ResolveMacros(const Value& str, const ResolverList& resolv
bool MacroProcessor::ResolveMacro(const String& macro, const ResolverList& resolvers,
const CheckResult::Ptr& cr, Value *result, bool *recursive_macro)
{
CONTEXT("Resolving macro '" + macro + "'");
CONTEXT("Resolving macro '" << macro << "'");
*recursive_macro = false;
@ -205,7 +205,7 @@ Value MacroProcessor::InternalResolveMacros(const String& str, const ResolverLis
const MacroProcessor::EscapeCallback& escapeFn, const Dictionary::Ptr& resolvedMacros,
bool useResolvedMacros, int recursionLevel)
{
CONTEXT("Resolving macros for string '" + str + "'");
CONTEXT("Resolving macros for string '" << str << "'");
if (recursionLevel > 15)
BOOST_THROW_EXCEPTION(std::runtime_error("Infinite recursion detected while resolving macros"));

View File

@ -65,9 +65,7 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
{
auto& di (rule.GetDebugInfo());
std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str());
CONTEXT("Evaluating 'apply' rule (" << di << ")");
Host::Ptr host;
Service::Ptr service;
@ -133,7 +131,7 @@ bool Notification::EvaluateApplyRule(const Checkable::Ptr& checkable, const Appl
void Notification::EvaluateApplyRules(const Host::Ptr& host)
{
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))
{
@ -149,7 +147,7 @@ void Notification::EvaluateApplyRules(const Host::Ptr& host)
void Notification::EvaluateApplyRules(const Service::Ptr& service)
{
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)) {
if (EvaluateApplyRule(service, *rule))

View File

@ -64,9 +64,7 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
{
auto& di (rule.GetDebugInfo());
std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str());
CONTEXT("Evaluating 'apply' rule (" << di << ")");
Host::Ptr host;
Service::Ptr service;
@ -132,7 +130,7 @@ bool ScheduledDowntime::EvaluateApplyRule(const Checkable::Ptr& checkable, const
void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
{
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)) {
if (EvaluateApplyRule(host, *rule))
@ -147,7 +145,7 @@ void ScheduledDowntime::EvaluateApplyRules(const Host::Ptr& host)
void ScheduledDowntime::EvaluateApplyRules(const Service::Ptr& service)
{
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)) {
if (EvaluateApplyRule(service, *rule))

View File

@ -59,9 +59,7 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo
{
auto& di (rule.GetDebugInfo());
std::ostringstream msgbuf;
msgbuf << "Evaluating 'apply' rule (" << di << ")";
CONTEXT(msgbuf.str());
CONTEXT("Evaluating 'apply' rule (" << di << ")");
ScriptFrame frame(true);
if (rule.GetScope())
@ -121,7 +119,7 @@ bool Service::EvaluateApplyRule(const Host::Ptr& host, const ApplyRule& rule, bo
void Service::EvaluateApplyRules(const Host::Ptr& host)
{
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)) {
if (EvaluateApplyRule(host, *rule))

View File

@ -22,7 +22,7 @@ bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigI
{
String groupName = group->GetName();
CONTEXT("Evaluating rule for group '" + groupName + "'");
CONTEXT("Evaluating rule for group '" << groupName << "'");
Host::Ptr host = service->GetHost();
@ -48,7 +48,7 @@ bool ServiceGroup::EvaluateObjectRule(const Service::Ptr& service, const ConfigI
void ServiceGroup::EvaluateObjectRules(const Service::Ptr& service)
{
CONTEXT("Evaluating group membership for service '" + service->GetName() + "'");
CONTEXT("Evaluating group membership for service '" << service->GetName() << "'");
for (const ConfigItem::Ptr& group : ConfigItem::GetItems(ServiceGroup::TypeInstance))
{

View File

@ -23,7 +23,7 @@ bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr&
{
String groupName = group->GetName();
CONTEXT("Evaluating rule for group '" + groupName + "'");
CONTEXT("Evaluating rule for group '" << groupName << "'");
ScriptFrame frame(true);
if (group->GetScope())
@ -46,7 +46,7 @@ bool UserGroup::EvaluateObjectRule(const User::Ptr& user, const ConfigItem::Ptr&
void UserGroup::EvaluateObjectRules(const User::Ptr& user)
{
CONTEXT("Evaluating group membership for user '" + user->GetName() + "'");
CONTEXT("Evaluating group membership for user '" << user->GetName() << "'");
for (const ConfigItem::Ptr& group : ConfigItem::GetItems(UserGroup::TypeInstance))
{

View File

@ -211,7 +211,7 @@ void ElasticsearchWriter::InternalCheckResultHandler(const Checkable::Ptr& check
{
AssertOnWorkQueue();
CONTEXT("Elasticwriter processing check result for '" + checkable->GetName() + "'");
CONTEXT("Elasticwriter processing check result for '" << checkable->GetName() << "'");
if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !checkable->GetEnablePerfdata())
return;
@ -268,7 +268,7 @@ void ElasticsearchWriter::StateChangeHandlerInternal(const Checkable::Ptr& check
{
AssertOnWorkQueue();
CONTEXT("Elasticwriter processing state change '" + checkable->GetName() + "'");
CONTEXT("Elasticwriter processing state change '" << checkable->GetName() << "'");
Host::Ptr host;
Service::Ptr service;
@ -324,7 +324,7 @@ void ElasticsearchWriter::NotificationSentToAllUsersHandlerInternal(const Notifi
{
AssertOnWorkQueue();
CONTEXT("Elasticwriter processing notification to all users '" + checkable->GetName() + "'");
CONTEXT("Elasticwriter processing notification to all users '" << checkable->GetName() << "'");
Log(LogDebug, "ElasticsearchWriter")
<< "Processing notification for '" << checkable->GetName() << "'";

View File

@ -162,7 +162,7 @@ void GelfWriter::ReconnectInternal()
{
double startTime = Utility::GetTime();
CONTEXT("Reconnecting to Graylog Gelf '" + GetName() + "'");
CONTEXT("Reconnecting to Graylog Gelf '" << GetName() << "'");
SetShouldConnect(true);
@ -276,7 +276,7 @@ void GelfWriter::CheckResultHandlerInternal(const Checkable::Ptr& checkable, con
{
AssertOnWorkQueue();
CONTEXT("GELF Processing check result for '" + checkable->GetName() + "'");
CONTEXT("GELF Processing check result for '" << checkable->GetName() << "'");
Log(LogDebug, "GelfWriter")
<< "Processing check result for '" << checkable->GetName() << "'";
@ -388,7 +388,7 @@ void GelfWriter::NotificationToUserHandlerInternal(const Notification::Ptr& noti
{
AssertOnWorkQueue();
CONTEXT("GELF Processing notification to all users '" + checkable->GetName() + "'");
CONTEXT("GELF Processing notification to all users '" << checkable->GetName() << "'");
Log(LogDebug, "GelfWriter")
<< "Processing notification for '" << checkable->GetName() << "'";
@ -452,7 +452,7 @@ void GelfWriter::StateChangeHandlerInternal(const Checkable::Ptr& checkable, con
{
AssertOnWorkQueue();
CONTEXT("GELF Processing state change '" + checkable->GetName() + "'");
CONTEXT("GELF Processing state change '" << checkable->GetName() << "'");
Log(LogDebug, "GelfWriter")
<< "Processing state change for '" << checkable->GetName() << "'";

View File

@ -181,7 +181,7 @@ void GraphiteWriter::ReconnectInternal()
{
double startTime = Utility::GetTime();
CONTEXT("Reconnecting to Graphite '" + GetName() + "'");
CONTEXT("Reconnecting to Graphite '" << GetName() << "'");
SetShouldConnect(true);
@ -276,7 +276,7 @@ void GraphiteWriter::CheckResultHandlerInternal(const Checkable::Ptr& checkable,
{
AssertOnWorkQueue();
CONTEXT("Processing check result for '" + checkable->GetName() + "'");
CONTEXT("Processing check result for '" << checkable->GetName() << "'");
/* TODO: Deal with missing connection here. Needs refactoring
* into parsing the actual performance data and then putting it

View File

@ -210,7 +210,7 @@ void InfluxdbCommonWriter::CheckResultHandlerWQ(const Checkable::Ptr& checkable,
{
AssertOnWorkQueue();
CONTEXT("Processing check result for '" + checkable->GetName() + "'");
CONTEXT("Processing check result for '" << checkable->GetName() << "'");
if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !checkable->GetEnablePerfdata())
return;

View File

@ -158,7 +158,7 @@ void OpenTsdbWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
if (IsPaused())
return;
CONTEXT("Processing check result for '" + checkable->GetName() + "'");
CONTEXT("Processing check result for '" << checkable->GetName() << "'");
if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !checkable->GetEnablePerfdata())
return;

View File

@ -99,7 +99,7 @@ void PerfdataWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
if (IsPaused())
return;
CONTEXT("Writing performance data for object '" + checkable->GetName() + "'");
CONTEXT("Writing performance data for object '" << checkable->GetName() << "'");
if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !checkable->GetEnablePerfdata())
return;

View File

@ -817,7 +817,7 @@ void ApiListener::ConfigGlobHandler(ConfigDirInformation& config, const String&
if (Utility::BaseName(file) == ".authoritative")
return;
CONTEXT("Creating config update for file '" + file + "'");
CONTEXT("Creating config update for file '" << file << "'");
Log(LogNotice, "ApiListener")
<< "Creating config update for file '" << file << "'.";

View File

@ -1400,7 +1400,7 @@ void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client)
return;
}
CONTEXT("Replaying log for Endpoint '" + endpoint->GetName() + "'");
CONTEXT("Replaying log for Endpoint '" << endpoint->GetName() << "'");
int count = -1;
double peer_ts = endpoint->GetLocalLogPosition();