Add tags functionality to ElasticSearchWriter

This commit is contained in:
Sebastian Grund 2024-09-23 10:50:08 +02:00 committed by Yonas Habteab
parent d55c3644a2
commit 7d12c1a524
3 changed files with 102 additions and 0 deletions

View File

@ -5,6 +5,7 @@
#include "remote/url.hpp"
#include "icinga/compatutility.hpp"
#include "icinga/service.hpp"
#include "icinga/macroprocessor.hpp"
#include "icinga/checkcommand.hpp"
#include "base/application.hpp"
#include "base/defer.hpp"
@ -131,6 +132,33 @@ void ElasticsearchWriter::Pause()
ObjectImpl<ElasticsearchWriter>::Pause();
}
void ElasticsearchWriter::AddTemplateTags(const Dictionary::Ptr& fields, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
{
Host::Ptr host;
Service::Ptr service;
tie(host, service) = GetHostService(checkable);
Dictionary::Ptr tmpl = service ? GetServiceTagsTemplate() : GetHostTagsTemplate();
if (tmpl) {
MacroProcessor::ResolverList resolvers;
resolvers.emplace_back("host", host);
if (service) {
resolvers.emplace_back("service", service);
}
ObjectLock olock(tmpl);
for (const Dictionary::Pair& pair : tmpl) {
String missingMacro;
Value value = MacroProcessor::ResolveMacros(pair.second, resolvers, cr, &missingMacro);
if (missingMacro.IsEmpty()) {
fields->Set(pair.first, value);
}
}
}
}
void ElasticsearchWriter::AddCheckResult(const Dictionary::Ptr& fields, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
{
String prefix = "check_result.";
@ -257,6 +285,8 @@ void ElasticsearchWriter::InternalCheckResultHandler(const Checkable::Ptr& check
ts = cr->GetExecutionEnd();
}
AddTemplateTags(fields, checkable, cr);
Enqueue(checkable, "checkresult", fields, ts);
}
@ -307,6 +337,8 @@ void ElasticsearchWriter::StateChangeHandlerInternal(const Checkable::Ptr& check
ts = cr->GetExecutionEnd();
}
AddTemplateTags(fields, checkable, cr);
Enqueue(checkable, "statechange", fields, ts);
}
@ -377,6 +409,8 @@ void ElasticsearchWriter::NotificationSentToAllUsersHandlerInternal(const Notifi
ts = cr->GetExecutionEnd();
}
AddTemplateTags(fields, checkable, cr);
Enqueue(checkable, "notification", fields, ts);
}
@ -683,3 +717,49 @@ String ElasticsearchWriter::FormatTimestamp(double ts)
return Utility::FormatDateTime("%Y-%m-%dT%H:%M:%S", ts) + "." + Convert::ToString(milliSeconds) + Utility::FormatDateTime("%z", ts);
}
void ElasticsearchWriter::ValidateHostTagsTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
{
ObjectImpl<ElasticsearchWriter>::ValidateHostTagsTemplate(lvalue, utils);
Dictionary::Ptr tags = lvalue();
if (tags) {
ObjectLock olock(tags);
for (const Dictionary::Pair& pair : tags) {
if (pair.second.IsObjectType<Array>()) {
Array::Ptr arrObject = pair.second;
ObjectLock arrLock(arrObject);
for (const Value& arrValue : arrObject) {
if (!MacroProcessor::ValidateMacroString(arrValue)) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "host_tags_template", pair.first }, "Closing $ not found in macro format string '" + arrValue + "'."));
}
}
} else if (!MacroProcessor::ValidateMacroString(pair.second)) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "host_tags_template", pair.first }, "Closing $ not found in macro format string '" + pair.second + "'."));
}
}
}
}
void ElasticsearchWriter::ValidateServiceTagsTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
{
ObjectImpl<ElasticsearchWriter>::ValidateServiceTagsTemplate(lvalue, utils);
Dictionary::Ptr tags = lvalue();
if (tags) {
ObjectLock olock(tags);
for (const Dictionary::Pair& pair : tags) {
if (pair.second.IsObjectType<Array>()) {
Array::Ptr arrObject = pair.second;
ObjectLock arrLock(arrObject);
for (const Value& arrValue : arrObject) {
if (!MacroProcessor::ValidateMacroString(arrValue)) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "service_tags_template", pair.first }, "Closing $ not found in macro format string '" + arrValue + "'."));
}
}
} else if (!MacroProcessor::ValidateMacroString(pair.second)) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "service_tags_template", pair.first }, "Closing $ not found in macro format string '" + pair.second + "'."));
}
}
}
}

View File

@ -23,6 +23,9 @@ public:
static String FormatTimestamp(double ts);
void ValidateHostTagsTemplate(const Lazy<Dictionary::Ptr> &lvalue, const ValidationUtils &utils) override;
void ValidateServiceTagsTemplate(const Lazy<Dictionary::Ptr> &lvalue, const ValidationUtils &utils) override;
protected:
void OnConfigLoaded() override;
void Resume() override;
@ -37,6 +40,7 @@ private:
std::mutex m_DataBufferMutex;
void AddCheckResult(const Dictionary::Ptr& fields, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
void AddTemplateTags(const Dictionary::Ptr& fields, const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
void StateChangeHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, StateType type);
void StateChangeHandlerInternal(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr, StateType type);

View File

@ -29,6 +29,9 @@ class ElasticsearchWriter : ConfigObject
[config] bool enable_tls {
default {{{ return false; }}}
};
[config] Dictionary::Ptr host_tags_template;
[config] Dictionary::Ptr service_tags_template;
[config] bool insecure_noverify {
default {{{ return false; }}}
};
@ -47,4 +50,19 @@ class ElasticsearchWriter : ConfigObject
};
};
validator ElasticsearchWriter {
Dictionary host_tags_template {
String "*";
Array "*" {
String "*";
};
};
Dictionary service_tags_template {
String "*";
Array "*" {
String "*";
};
};
};
}