diff --git a/lib/icingadb/icingadb-objects.cpp b/lib/icingadb/icingadb-objects.cpp index e30caedae..3ac8dddf1 100644 --- a/lib/icingadb/icingadb-objects.cpp +++ b/lib/icingadb/icingadb-objects.cpp @@ -60,6 +60,13 @@ void IcingaDB::ConfigStaticInitialize() IcingaDB::StateChangeHandler(checkable, cr, type); }); + Checkable::OnAcknowledgementSet.connect([](const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool, bool persistent, double expiry, const MessageOrigin::Ptr&) { + AcknowledgementSetHandler(checkable, author, comment, type, persistent, expiry); + }); + Checkable::OnAcknowledgementCleared.connect([](const Checkable::Ptr& checkable, const String& removedBy, const MessageOrigin::Ptr&) { + AcknowledgementClearedHandler(checkable, removedBy); + }); + /* triggered when acknowledged host/service goes back to ok and when the acknowledgement gets deleted */ Checkable::OnAcknowledgementCleared.connect([](const Checkable::Ptr& checkable, const String&, const MessageOrigin::Ptr&) { IcingaDB::StateChangeHandler(checkable); @@ -1634,6 +1641,92 @@ void IcingaDB::SendNextUpdate(const Checkable::Ptr& checkable) ); } +void IcingaDB::SendAcknowledgementSet(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool persistent, double expiry) +{ + if (!m_Rcon || !m_Rcon->IsConnected()) + return; + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + std::vector xAdd ({ + "XADD", "icinga:history:stream:acknowledgement", "*", + "id", Utility::NewUniqueID(), + "environment_id", SHA1(GetEnvironment()), + "host_id", GetObjectIdentifier(host), + "event_time", Convert::ToString(TimestampToMilliseconds(Utility::GetTime())), + "event_type", "ack_set", + "author", author, + "comment", comment, + "is_sticky", Convert::ToString((unsigned short)(type == AcknowledgementSticky)), + "is_persistent", Convert::ToString((unsigned short)persistent) + }); + + if (service) { + xAdd.emplace_back("object_type"); + xAdd.emplace_back("service"); + xAdd.emplace_back("service_id"); + xAdd.emplace_back(GetObjectIdentifier(checkable)); + } else { + xAdd.emplace_back("object_type"); + xAdd.emplace_back("host"); + } + + auto endpoint (Endpoint::GetLocalEndpoint()); + + if (endpoint) { + xAdd.emplace_back("endpoint_id"); + xAdd.emplace_back(GetObjectIdentifier(endpoint)); + } + + if (expiry > 0) { + xAdd.emplace_back("expire_time"); + xAdd.emplace_back(Convert::ToString(TimestampToMilliseconds(expiry))); + } + + m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); +} + +void IcingaDB::SendAcknowledgementCleared(const Checkable::Ptr& checkable, const String& removedBy) +{ + if (!m_Rcon || !m_Rcon->IsConnected()) + return; + + Host::Ptr host; + Service::Ptr service; + tie(host, service) = GetHostService(checkable); + + std::vector xAdd ({ + "XADD", "icinga:history:stream:acknowledgement", "*", + "id", Utility::NewUniqueID(), + "environment_id", SHA1(GetEnvironment()), + "host_id", GetObjectIdentifier(host), + "event_time", Convert::ToString(TimestampToMilliseconds(Utility::GetTime())), + "event_type", "ack_clear", + "author", removedBy + }); + + if (service) { + xAdd.emplace_back("object_type"); + xAdd.emplace_back("service"); + xAdd.emplace_back("service_id"); + xAdd.emplace_back(GetObjectIdentifier(checkable)); + } else { + xAdd.emplace_back("object_type"); + xAdd.emplace_back("host"); + } + + auto endpoint (Endpoint::GetLocalEndpoint()); + + if (endpoint) { + xAdd.emplace_back("endpoint_id"); + xAdd.emplace_back(GetObjectIdentifier(endpoint)); + } + + m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); +} + Dictionary::Ptr IcingaDB::SerializeState(const Checkable::Ptr& checkable) { Dictionary::Ptr attrs = new Dictionary(); @@ -1880,3 +1973,35 @@ void IcingaDB::NewCheckResultHandler(const Checkable::Ptr& checkable) rw->m_WorkQueue.Enqueue([rw, checkable]() { rw->SendNextUpdate(checkable); }); } } + +struct AuthorComment +{ + String Author; + String Comment; +}; + +void IcingaDB::AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool persistent, double expiry) +{ + auto rws (ConfigType::GetObjectsByType()); + + if (!rws.empty()) { + auto ac (Shared::Make(AuthorComment{author, comment})); + + for (auto& rw : rws) { + rw->m_WorkQueue.Enqueue([rw, checkable, ac, type, persistent, expiry]() { rw->SendAcknowledgementSet(checkable, ac->Author, ac->Comment, type, persistent, expiry); }); + } + } +} + +void IcingaDB::AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const String& removedBy) +{ + auto rws (ConfigType::GetObjectsByType()); + + if (!rws.empty()) { + auto rb (Shared::Make(removedBy)); + + for (auto& rw : rws) { + rw->m_WorkQueue.Enqueue([rw, checkable, rb]() { rw->SendAcknowledgementCleared(checkable, *rb); }); + } + } +} diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index a1ae85c80..2ac8ab6bf 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -67,6 +67,8 @@ private: void SendRemovedComment(const Comment::Ptr& comment); void SendFlappingChanged(const Checkable::Ptr& checkable, const Value& value); void SendNextUpdate(const Checkable::Ptr& checkable); + void SendAcknowledgementSet(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool persistent, double expiry); + void SendAcknowledgementCleared(const Checkable::Ptr& checkable, const String& removedBy); std::vector UpdateObjectAttrs(const ConfigObject::Ptr& object, int fieldType, const String& typeNameOverride); Dictionary::Ptr SerializeState(const Checkable::Ptr& checkable); @@ -109,6 +111,8 @@ private: static void CommentRemovedHandler(const Comment::Ptr& comment); static void FlappingChangedHandler(const Checkable::Ptr& checkable, const Value& value); static void NewCheckResultHandler(const Checkable::Ptr& checkable); + static void AcknowledgementSetHandler(const Checkable::Ptr& checkable, const String& author, const String& comment, AcknowledgementType type, bool persistent, double expiry); + static void AcknowledgementClearedHandler(const Checkable::Ptr& checkable, const String& removedBy); void AssertOnWorkQueue();