CONTEXT: lazily evaluate frames to only actually assemble when needed

This commit is contained in:
Alexander A. Klimov 2022-10-28 17:19:50 +02:00
parent 0b46e0aeab
commit b82814fb29
6 changed files with 26 additions and 22 deletions

View File

@ -3,14 +3,16 @@
#include "base/context.hpp"
#include <boost/thread/tss.hpp>
#include <iostream>
#include <sstream>
#include <utility>
using namespace icinga;
static boost::thread_specific_ptr<std::vector<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().emplace_back(message);
GetFrames().emplace_back(std::move(message));
}
ContextFrame::~ContextFrame()
@ -18,17 +20,23 @@ ContextFrame::~ContextFrame()
GetFrames().pop_back();
}
std::vector<String>& ContextFrame::GetFrames()
std::vector<std::function<void(std::ostream&)>>& ContextFrame::GetFrames()
{
if (!l_Frames.get())
l_Frames.reset(new std::vector<String>());
l_Frames.reset(new std::vector<std::function<void(std::ostream&)>>());
return *l_Frames;
}
ContextTrace::ContextTrace()
: m_Frames(ContextFrame::GetFrames().rbegin(), ContextFrame::GetFrames().rend())
{ }
{
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,6 +5,7 @@
#include "base/i2-base.hpp"
#include "base/string.hpp"
#include <functional>
#include <vector>
namespace icinga
@ -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::vector<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

@ -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;

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;

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;

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())