diff --git a/lib/icingadb/icingadb-objects.cpp b/lib/icingadb/icingadb-objects.cpp index e7b0706a4..ff3994bc9 100644 --- a/lib/icingadb/icingadb-objects.cpp +++ b/lib/icingadb/icingadb-objects.cpp @@ -1539,10 +1539,11 @@ void IcingaDB::SendStateChange(const ConfigObject::Ptr& object, const CheckResul hard_state = service ? Convert::ToLong(service->GetLastHardState()) : Convert::ToLong(host->GetLastHardState()); } - auto eventTime (TimestampToMilliseconds(cr->GetExecutionEnd())); + auto eventTime (cr->GetExecutionEnd()); + auto eventTs (TimestampToMilliseconds(eventTime)); Array::Ptr rawId = new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(object))); - rawId->Add(eventTime); + rawId->Add(eventTs); std::vector xAdd ({ "XADD", "icinga:history:stream:state", "*", @@ -1556,8 +1557,8 @@ void IcingaDB::SendStateChange(const ConfigObject::Ptr& object, const CheckResul "previous_soft_state", Convert::ToString(GetPreviousState(checkable, service, StateTypeSoft)), "previous_hard_state", Convert::ToString(GetPreviousState(checkable, service, StateTypeHard)), "max_check_attempts", Convert::ToString(checkable->GetMaxCheckAttempts()), - "event_time", Convert::ToString(eventTime), - "event_id", Utility::NewUniqueID(), + "event_time", Convert::ToString(eventTs), + "event_id", CalcEventID("state_change", object, eventTime), "event_type", "state_change" }); @@ -1619,16 +1620,17 @@ void IcingaDB::SendSentNotification( } auto usersAmount (users.size()); - auto notificationHistoryId = Utility::NewUniqueID(); auto sendTs (TimestampToMilliseconds(sendTime)); Array::Ptr rawId = new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(notification))); rawId->Add(GetNotificationTypeByEnum(type)); rawId->Add(sendTs); + auto notificationHistoryId (HashValue(rawId)); + std::vector xAdd ({ "XADD", "icinga:history:stream:notification", "*", - "id", HashValue(rawId), + "id", notificationHistoryId, "environment_id", m_EnvironmentId, "notification_id", GetObjectIdentifier(notification), "host_id", GetObjectIdentifier(host), @@ -1639,7 +1641,7 @@ void IcingaDB::SendSentNotification( "text", Utility::ValidateUTF8(finalText), "users_notified", Convert::ToString(usersAmount), "send_time", Convert::ToString(sendTs), - "event_id", Utility::NewUniqueID(), + "event_id", CalcEventID("notification", notification, sendTime, type), "event_type", "notification" }); @@ -1700,7 +1702,7 @@ void IcingaDB::SendStartedDowntime(const Downtime::Ptr& downtime) "scheduled_end_time", Convert::ToString(TimestampToMilliseconds(downtime->GetEndTime())), "has_been_cancelled", Convert::ToString((unsigned short)downtime->GetWasCancelled()), "trigger_time", Convert::ToString(TimestampToMilliseconds(downtime->GetTriggerTime())), - "event_id", Utility::NewUniqueID(), + "event_id", CalcEventID("downtime_start", downtime), "event_type", "downtime_start" }); @@ -1780,7 +1782,7 @@ void IcingaDB::SendRemovedDowntime(const Downtime::Ptr& downtime) "has_been_cancelled", Convert::ToString((unsigned short)downtime->GetWasCancelled()), "trigger_time", Convert::ToString(TimestampToMilliseconds(downtime->GetTriggerTime())), "cancel_time", Convert::ToString(TimestampToMilliseconds(Utility::GetTime())), - "event_id", Utility::NewUniqueID(), + "event_id", CalcEventID("downtime_end", downtime), "event_type", "downtime_end" }); @@ -1850,7 +1852,7 @@ void IcingaDB::SendAddedComment(const Comment::Ptr& comment) "entry_type", Convert::ToString(comment->GetEntryType()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_sticky", Convert::ToString((unsigned short)(comment->GetEntryType() == CommentAcknowledgement && comment->GetCheckable()->GetAcknowledgement() == AcknowledgementSticky)), - "event_id", Utility::NewUniqueID(), + "event_id", CalcEventID("comment_add", comment), "event_type", "comment_add" }); @@ -1907,7 +1909,7 @@ void IcingaDB::SendRemovedComment(const Comment::Ptr& comment) "entry_type", Convert::ToString(comment->GetEntryType()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_sticky", Convert::ToString((unsigned short)(comment->GetEntryType() == CommentAcknowledgement && comment->GetCheckable()->GetAcknowledgement() == AcknowledgementSticky)), - "event_id", Utility::NewUniqueID(), + "event_id", CalcEventID("comment_remove", comment), "event_type", "comment_remove" }); @@ -1968,8 +1970,7 @@ void IcingaDB::SendFlappingChange(const Checkable::Ptr& checkable, double change "environment_id", m_EnvironmentId, "host_id", GetObjectIdentifier(host), "flapping_threshold_low", Convert::ToString(checkable->GetFlappingThresholdLow()), - "flapping_threshold_high", Convert::ToString(checkable->GetFlappingThresholdHigh()), - "event_id", Utility::NewUniqueID() + "flapping_threshold_high", Convert::ToString(checkable->GetFlappingThresholdHigh()) }); if (service) { @@ -2011,6 +2012,8 @@ void IcingaDB::SendFlappingChange(const Checkable::Ptr& checkable, double change xAdd.emplace_back("start_time"); xAdd.emplace_back(Convert::ToString(startTime)); + xAdd.emplace_back("event_id"); + xAdd.emplace_back(CalcEventID(checkable->IsFlapping() ? "flapping_start" : "flapping_end", checkable, startTime)); xAdd.emplace_back("id"); xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), startTime}))); @@ -2055,7 +2058,6 @@ void IcingaDB::SendAcknowledgementSet(const Checkable::Ptr& checkable, const Str std::vector xAdd ({ "XADD", "icinga:history:stream:acknowledgement", "*", - "event_id", Utility::NewUniqueID(), "environment_id", m_EnvironmentId, "host_id", GetObjectIdentifier(host), "event_type", "ack_set", @@ -2091,6 +2093,8 @@ void IcingaDB::SendAcknowledgementSet(const Checkable::Ptr& checkable, const Str xAdd.emplace_back("set_time"); xAdd.emplace_back(Convert::ToString(setTime)); + xAdd.emplace_back("event_id"); + xAdd.emplace_back(CalcEventID("ack_set", checkable, setTime)); xAdd.emplace_back("id"); xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), setTime}))); @@ -2108,7 +2112,6 @@ void IcingaDB::SendAcknowledgementCleared(const Checkable::Ptr& checkable, const std::vector xAdd ({ "XADD", "icinga:history:stream:acknowledgement", "*", - "event_id", Utility::NewUniqueID(), "environment_id", m_EnvironmentId, "host_id", GetObjectIdentifier(host), "clear_time", Convert::ToString(TimestampToMilliseconds(changeTime)), @@ -2136,6 +2139,8 @@ void IcingaDB::SendAcknowledgementCleared(const Checkable::Ptr& checkable, const xAdd.emplace_back("set_time"); xAdd.emplace_back(Convert::ToString(setTime)); + xAdd.emplace_back("event_id"); + xAdd.emplace_back(CalcEventID("ack_clear", checkable, setTime)); xAdd.emplace_back("id"); xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), setTime}))); diff --git a/lib/icingadb/icingadb-utility.cpp b/lib/icingadb/icingadb-utility.cpp index 74203ab9b..3b1713cde 100644 --- a/lib/icingadb/icingadb-utility.cpp +++ b/lib/icingadb/icingadb-utility.cpp @@ -80,6 +80,28 @@ String IcingaDB::GetObjectIdentifier(const ConfigObject::Ptr& object) return HashValue(new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(object)))); } +/** + * Calculates a deterministic history event ID like SHA1(env, eventType, x...[, nt][, eventTime]) + * + * Where SHA1(env, x...) = GetObjectIdentifier(object) + */ +String IcingaDB::CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime, NotificationType nt) +{ + Array::Ptr rawId = new Array(GetObjectIdentifiersWithoutEnv(object)); + rawId->Insert(0, GetEnvironment()); + rawId->Insert(1, eventType); + + if (nt) { + rawId->Add(GetNotificationTypeByEnum(nt)); + } + + if (eventTime) { + rawId->Add(TimestampToMilliseconds(eventTime)); + } + + return HashValue(std::move(rawId)); +} + static const std::set metadataWhitelist ({"package", "source_location", "templates"}); /** diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index 90c91a845..eef4267bf 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -107,6 +107,7 @@ private: static ArrayData GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& object); static String GetObjectIdentifier(const ConfigObject::Ptr& object); + static String CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime = 0, NotificationType nt = NotificationType(0)); static String GetEnvironment(); static Dictionary::Ptr SerializeVars(const CustomVarObject::Ptr& object); static const char* GetNotificationTypeByEnum(NotificationType type);