Merge pull request #10452 from Icinga/streamline-redis-and-db-values

IcingaDB: Make Redis & DB values consistent
This commit is contained in:
Julian Brost 2025-06-10 11:30:07 +02:00 committed by GitHub
commit c41fe682c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 211 additions and 77 deletions

View File

@ -130,7 +130,7 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che
<< host->GetName() << ";" << host->GetName() << ";"
<< service->GetShortName() << ";" << service->GetShortName() << ";"
<< Service::StateToString(service->GetState()) << ";" << Service::StateToString(service->GetState()) << ";"
<< Service::StateTypeToString(service->GetStateType()) << ";" << Checkable::StateTypeToString(service->GetStateType()) << ";"
<< attempt_after << ";" << attempt_after << ";"
<< output << "" << output << ""
<< ""; << "";
@ -140,7 +140,7 @@ void CompatLogger::CheckResultHandler(const Checkable::Ptr& checkable, const Che
msgbuf << "HOST ALERT: " msgbuf << "HOST ALERT: "
<< host->GetName() << ";" << host->GetName() << ";"
<< GetHostStateString(host) << ";" << GetHostStateString(host) << ";"
<< Host::StateTypeToString(host->GetStateType()) << ";" << Checkable::StateTypeToString(host->GetStateType()) << ";"
<< attempt_after << ";" << attempt_after << ";"
<< output << "" << output << ""
<< ""; << "";
@ -413,14 +413,14 @@ void CompatLogger::EventCommandHandler(const Checkable::Ptr& checkable)
<< host->GetName() << ";" << host->GetName() << ";"
<< service->GetShortName() << ";" << service->GetShortName() << ";"
<< Service::StateToString(service->GetState()) << ";" << Service::StateToString(service->GetState()) << ";"
<< Service::StateTypeToString(service->GetStateType()) << ";" << Checkable::StateTypeToString(service->GetStateType()) << ";"
<< current_attempt << ";" << current_attempt << ";"
<< event_command_name; << event_command_name;
} else { } else {
msgbuf << "HOST EVENT HANDLER: " msgbuf << "HOST EVENT HANDLER: "
<< host->GetName() << ";" << host->GetName() << ";"
<< GetHostStateString(host) << ";" << GetHostStateString(host) << ";"
<< Host::StateTypeToString(host->GetStateType()) << ";" << Checkable::StateTypeToString(host->GetStateType()) << ";"
<< current_attempt << ";" << current_attempt << ";"
<< event_command_name; << event_command_name;
} }
@ -505,7 +505,7 @@ void CompatLogger::ReopenFile(bool rotate)
msgbuf << "CURRENT HOST STATE: " msgbuf << "CURRENT HOST STATE: "
<< host->GetName() << ";" << host->GetName() << ";"
<< GetHostStateString(host) << ";" << GetHostStateString(host) << ";"
<< Host::StateTypeToString(host->GetStateType()) << ";" << Checkable::StateTypeToString(host->GetStateType()) << ";"
<< host->GetCheckAttempt() << ";" << host->GetCheckAttempt() << ";"
<< output << ""; << output << "";
@ -526,7 +526,7 @@ void CompatLogger::ReopenFile(bool rotate)
<< host->GetName() << ";" << host->GetName() << ";"
<< service->GetShortName() << ";" << service->GetShortName() << ";"
<< Service::StateToString(service->GetState()) << ";" << Service::StateToString(service->GetState()) << ";"
<< Service::StateTypeToString(service->GetStateType()) << ";" << Checkable::StateTypeToString(service->GetStateType()) << ";"
<< service->GetCheckAttempt() << ";" << service->GetCheckAttempt() << ";"
<< output << ""; << output << "";

View File

@ -994,7 +994,7 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C
<< host->GetName() << ";" << host->GetName() << ";"
<< service->GetShortName() << ";" << service->GetShortName() << ";"
<< Service::StateToString(service->GetState()) << ";" << Service::StateToString(service->GetState()) << ";"
<< Service::StateTypeToString(service->GetStateType()) << ";" << Checkable::StateTypeToString(service->GetStateType()) << ";"
<< service->GetCheckAttempt() << ";" << service->GetCheckAttempt() << ";"
<< output << "" << output << ""
<< ""; << "";
@ -1021,7 +1021,7 @@ void DbEvents::AddCheckResultLogHistory(const Checkable::Ptr& checkable, const C
msgbuf << "HOST ALERT: " msgbuf << "HOST ALERT: "
<< host->GetName() << ";" << host->GetName() << ";"
<< GetHostStateString(host) << ";" << GetHostStateString(host) << ";"
<< Host::StateTypeToString(host->GetStateType()) << ";" << Checkable::StateTypeToString(host->GetStateType()) << ";"
<< host->GetCheckAttempt() << ";" << host->GetCheckAttempt() << ";"
<< output << "" << output << ""
<< ""; << "";

View File

@ -322,3 +322,9 @@ void Checkable::CleanDeadlinedExecutions(const Timer * const&)
} }
} }
} }
String Checkable::StateTypeToString(StateType type)
{
return type == StateTypeSoft ? "SOFT" : "HARD";
}

View File

@ -106,6 +106,8 @@ public:
void UpdateNextCheck(const MessageOrigin::Ptr& origin = nullptr); void UpdateNextCheck(const MessageOrigin::Ptr& origin = nullptr);
static String StateTypeToString(StateType type);
bool HasBeenChecked() const; bool HasBeenChecked() const;
virtual bool IsStateOK(ServiceState state) const = 0; virtual bool IsStateOK(ServiceState state) const = 0;

View File

@ -227,22 +227,6 @@ String Host::StateToString(HostState state)
} }
} }
StateType Host::StateTypeFromString(const String& type)
{
if (type == "SOFT")
return StateTypeSoft;
else
return StateTypeHard;
}
String Host::StateTypeToString(StateType type)
{
if (type == StateTypeSoft)
return "SOFT";
else
return "HARD";
}
bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, Value *result) const
{ {
if (macro == "state") { if (macro == "state") {

View File

@ -45,9 +45,6 @@ public:
static HostState StateFromString(const String& state); static HostState StateFromString(const String& state);
static String StateToString(HostState state); static String StateToString(HostState state);
static StateType StateTypeFromString(const String& state);
static String StateTypeToString(StateType state);
bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override; bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override;
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;

View File

@ -100,12 +100,13 @@ void Notification::StaticInitialize()
m_TypeFilterMap["FlappingEnd"] = NotificationFlappingEnd; m_TypeFilterMap["FlappingEnd"] = NotificationFlappingEnd;
} }
void Notification::OnConfigLoaded() Notification::Notification()
{ {
ObjectImpl<Notification>::OnConfigLoaded(); // If a notification is created without specifying the "types/states" attribute, the Set* methods won't be called,
// consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are
SetTypeFilter(FilterArrayToInt(GetTypes(), GetTypeFilterMap(), ~0)); // initialized to the default values, which are all types and states enabled.
SetStateFilter(FilterArrayToInt(GetStates(), GetStateFilterMap(), ~0)); SetTypes(nullptr, false, Empty);
SetStates(nullptr, false, Empty);
} }
void Notification::OnAllConfigLoaded() void Notification::OnAllConfigLoaded()
@ -751,6 +752,36 @@ String Notification::NotificationHostStateToString(HostState state)
} }
} }
Array::Ptr Notification::GetTypes() const
{
return m_Types.load();
}
void Notification::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
m_Types.store(value);
// Ensure that the type filter is updated when the types attribute changes.
SetTypeFilter(FilterArrayToInt(value, GetTypeFilterMap(), ~0));
if (!suppress_events) {
NotifyTypes(cookie);
}
}
Array::Ptr Notification::GetStates() const
{
return m_States.load();
}
void Notification::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
m_States.store(value);
// Ensure that the state filter is updated when the states attribute changes.
SetStateFilter(FilterArrayToInt(value, GetStateFilterMap(), ~0));
if (!suppress_events) {
NotifyStates(cookie);
}
}
void Notification::Validate(int types, const ValidationUtils& utils) void Notification::Validate(int types, const ValidationUtils& utils)
{ {
ObjectImpl<Notification>::Validate(types, utils); ObjectImpl<Notification>::Validate(types, utils);

View File

@ -29,7 +29,9 @@ enum NotificationFilter
StateFilterUnknown = 8, StateFilterUnknown = 8,
StateFilterUp = 16, StateFilterUp = 16,
StateFilterDown = 32 StateFilterDown = 32,
StateFilterAll = StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown | StateFilterUp | StateFilterDown,
}; };
/** /**
@ -47,7 +49,11 @@ enum NotificationType
NotificationProblem = 32, NotificationProblem = 32,
NotificationRecovery = 64, NotificationRecovery = 64,
NotificationFlappingStart = 128, NotificationFlappingStart = 128,
NotificationFlappingEnd = 256 NotificationFlappingEnd = 256,
NotificationTypeAll = NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved |
NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery |
NotificationFlappingStart | NotificationFlappingEnd,
}; };
class NotificationCommand; class NotificationCommand;
@ -68,6 +74,8 @@ public:
DECLARE_OBJECT(Notification); DECLARE_OBJECT(Notification);
DECLARE_OBJECTNAME(Notification); DECLARE_OBJECTNAME(Notification);
Notification();
static void StaticInitialize(); static void StaticInitialize();
intrusive_ptr<Checkable> GetCheckable() const; intrusive_ptr<Checkable> GetCheckable() const;
@ -109,13 +117,28 @@ public:
static const std::map<String, int>& GetStateFilterMap(); static const std::map<String, int>& GetStateFilterMap();
static const std::map<String, int>& GetTypeFilterMap(); static const std::map<String, int>& GetTypeFilterMap();
void OnConfigLoaded() override;
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;
void Start(bool runtimeCreated) override; void Start(bool runtimeCreated) override;
void Stop(bool runtimeRemoved) override; void Stop(bool runtimeRemoved) override;
Array::Ptr GetTypes() const override;
void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
Array::Ptr GetStates() const override;
void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
private: private:
ObjectImpl<Checkable>::Ptr m_Checkable; ObjectImpl<Checkable>::Ptr m_Checkable;
// These attributes represent the actual notification "types" and "states" attributes from the "notification.ti".
// However, since we want to ensure that the type and state bitsets are always in sync with those attributes,
// we need to override their setters, and this on the hand introduces another problem: The virtual setters are
// called from within the ObjectImpl<Notification> constructor, which obviously violates the C++ standard [^1].
// So, in order to avoid all this kind of mess, these two attributes have the "no_storage" flag set, and
// their getters/setters are pure virtual, which means this class has to provide the implementation of them.
//
// [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors
AtomicOrLocked<Array::Ptr> m_Types;
AtomicOrLocked<Array::Ptr> m_States;
bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force, bool reminder); bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force, bool reminder);

View File

@ -41,9 +41,15 @@ class Notification : CustomVarObject < NotificationNameComposer
[config, signal_with_old_value] array(name(User)) users (UsersRaw); [config, signal_with_old_value] array(name(User)) users (UsersRaw);
[config, signal_with_old_value] array(name(UserGroup)) user_groups (UserGroupsRaw); [config, signal_with_old_value] array(name(UserGroup)) user_groups (UserGroupsRaw);
[config] Dictionary::Ptr times; [config] Dictionary::Ptr times;
[config] array(Value) types; [config, no_storage] array(Value) types {
get;
set;
};
[no_user_view, no_user_modify] int type_filter_real (TypeFilter); [no_user_view, no_user_modify] int type_filter_real (TypeFilter);
[config] array(Value) states; [config, no_storage] array(Value) states {
get;
set;
};
[no_user_view, no_user_modify] int state_filter_real (StateFilter); [no_user_view, no_user_modify] int state_filter_real (StateFilter);
[config, no_user_modify, protected, required, navigation(host)] name(Host) host_name { [config, no_user_modify, protected, required, navigation(host)] name(Host) host_name {
navigate {{{ navigate {{{

View File

@ -195,22 +195,6 @@ String Service::StateToString(ServiceState state)
} }
} }
StateType Service::StateTypeFromString(const String& type)
{
if (type == "SOFT")
return StateTypeSoft;
else
return StateTypeHard;
}
String Service::StateTypeToString(StateType type)
{
if (type == StateTypeSoft)
return "SOFT";
else
return "HARD";
}
bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const bool Service::ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const
{ {
if (macro == "state") { if (macro == "state") {

View File

@ -39,9 +39,6 @@ public:
static ServiceState StateFromString(const String& state); static ServiceState StateFromString(const String& state);
static String StateToString(ServiceState state); static String StateToString(ServiceState state);
static StateType StateTypeFromString(const String& state);
static String StateTypeToString(StateType state);
static void EvaluateApplyRules(const Host::Ptr& host); static void EvaluateApplyRules(const Host::Ptr& host);
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;

View File

@ -12,12 +12,13 @@ using namespace icinga;
REGISTER_TYPE(User); REGISTER_TYPE(User);
void User::OnConfigLoaded() User::User()
{ {
ObjectImpl<User>::OnConfigLoaded(); // If a User is created without specifying the "types/states" attribute, the Set* methods won't be called,
// consequently the filter bitset will also be 0. Thus, we need to ensure that the type/state filter are
SetTypeFilter(FilterArrayToInt(GetTypes(), Notification::GetTypeFilterMap(), ~0)); // initialized to the default values, which are all types and states enabled.
SetStateFilter(FilterArrayToInt(GetStates(), Notification::GetStateFilterMap(), ~0)); SetTypes(nullptr, false, Empty);
SetStates(nullptr, false, Empty);
} }
void User::OnAllConfigLoaded() void User::OnAllConfigLoaded()
@ -80,6 +81,36 @@ TimePeriod::Ptr User::GetPeriod() const
return TimePeriod::GetByName(GetPeriodRaw()); return TimePeriod::GetByName(GetPeriodRaw());
} }
Array::Ptr User::GetTypes() const
{
return m_Types.load();
}
void User::SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
m_Types.store(value);
// Ensure that the type filter is updated when the types attribute changes.
SetTypeFilter(FilterArrayToInt(value, Notification::GetTypeFilterMap(), ~0));
if (!suppress_events) {
NotifyTypes(cookie);
}
}
Array::Ptr User::GetStates() const
{
return m_States.load();
}
void User::SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
m_States.store(value);
// Ensure that the state filter is updated when the states attribute changes.
SetStateFilter(FilterArrayToInt(value, Notification::GetStateFilterMap(), ~0));
if (!suppress_events) {
NotifyStates(cookie);
}
}
void User::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) void User::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
{ {
ObjectImpl<User>::ValidateStates(lvalue, utils); ObjectImpl<User>::ValidateStates(lvalue, utils);

View File

@ -22,21 +22,38 @@ public:
DECLARE_OBJECT(User); DECLARE_OBJECT(User);
DECLARE_OBJECTNAME(User); DECLARE_OBJECTNAME(User);
User();
void AddGroup(const String& name); void AddGroup(const String& name);
/* Notifications */ /* Notifications */
TimePeriod::Ptr GetPeriod() const; TimePeriod::Ptr GetPeriod() const;
Array::Ptr GetTypes() const override;
void SetTypes(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
Array::Ptr GetStates() const override;
void SetStates(const Array::Ptr& value, bool suppress_events, const Value& cookie) override;
void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override; void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
protected: protected:
void Stop(bool runtimeRemoved) override; void Stop(bool runtimeRemoved) override;
void OnConfigLoaded() override;
void OnAllConfigLoaded() override; void OnAllConfigLoaded() override;
private: private:
mutable std::mutex m_UserMutex; mutable std::mutex m_UserMutex;
// These attributes represent the actual User "types" and "states" attributes from the "user.ti".
// However, since we want to ensure that the type and state bitsets are always in sync with those attributes,
// we need to override their setters, and this on the hand introduces another problem: The virtual setters are
// called from within the ObjectImpl<User> constructor, which obviously violates the C++ standard [^1].
// So, in order to avoid al this kind of mess, these two attributes have the "no_storage" flag set, and
// their getters/setters are pure virtual, which means this class has to provide the implementation of them.
//
// [^1]: https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctors
AtomicOrLocked<Array::Ptr> m_Types;
AtomicOrLocked<Array::Ptr> m_States;
}; };
} }

View File

@ -29,9 +29,15 @@ class User : CustomVarObject
}}} }}}
}; };
[config] array(Value) types; [config, no_storage] array(Value) types {
get;
set;
};
[no_user_view, no_user_modify] int type_filter_real (TypeFilter); [no_user_view, no_user_modify] int type_filter_real (TypeFilter);
[config] array(Value) states; [config, no_storage] array(Value) states {
get;
set;
};
[no_user_view, no_user_modify] int state_filter_real (StateFilter); [no_user_view, no_user_modify] int state_filter_real (StateFilter);
[config] String email; [config] String email;

View File

@ -1624,8 +1624,8 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
attributes->Set("email", user->GetEmail()); attributes->Set("email", user->GetEmail());
attributes->Set("pager", user->GetPager()); attributes->Set("pager", user->GetPager());
attributes->Set("notifications_enabled", user->GetEnableNotifications()); attributes->Set("notifications_enabled", user->GetEnableNotifications());
attributes->Set("states", user->GetStates()); attributes->Set("states", StateFilterToRedisValue(user->GetStateFilter()));
attributes->Set("types", user->GetTypes()); attributes->Set("types", TypeFilterToRedisValue(user->GetTypeFilter()));
if (user->GetPeriod()) if (user->GetPeriod())
attributes->Set("timeperiod_id", GetObjectIdentifier(user->GetPeriod())); attributes->Set("timeperiod_id", GetObjectIdentifier(user->GetPeriod()));
@ -1673,8 +1673,8 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
} }
attributes->Set("notification_interval", std::max(0.0, std::round(notification->GetInterval()))); attributes->Set("notification_interval", std::max(0.0, std::round(notification->GetInterval())));
attributes->Set("states", notification->GetStates()); attributes->Set("states", StateFilterToRedisValue(notification->GetStateFilter()));
attributes->Set("types", notification->GetTypes()); attributes->Set("types", TypeFilterToRedisValue(notification->GetTypeFilter()));
return true; return true;
} }
@ -1684,7 +1684,7 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
attributes->Set("author", comment->GetAuthor()); attributes->Set("author", comment->GetAuthor());
attributes->Set("text", comment->GetText()); attributes->Set("text", comment->GetText());
attributes->Set("entry_type", comment->GetEntryType()); attributes->Set("entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType()));
attributes->Set("entry_time", TimestampToMilliseconds(comment->GetEntryTime())); attributes->Set("entry_time", TimestampToMilliseconds(comment->GetEntryTime()));
attributes->Set("is_persistent", comment->GetPersistent()); attributes->Set("is_persistent", comment->GetPersistent());
attributes->Set("is_sticky", comment->GetSticky()); attributes->Set("is_sticky", comment->GetSticky());
@ -1974,7 +1974,7 @@ void IcingaDB::SendStateChange(const ConfigObject::Ptr& object, const CheckResul
"id", HashValue(rawId), "id", HashValue(rawId),
"environment_id", m_EnvironmentId, "environment_id", m_EnvironmentId,
"host_id", GetObjectIdentifier(host), "host_id", GetObjectIdentifier(host),
"state_type", Convert::ToString(type), "state_type", Checkable::StateTypeToString(type).ToLower(),
"soft_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99), "soft_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99),
"hard_state", Convert::ToString(hard_state), "hard_state", Convert::ToString(hard_state),
"check_attempt", Convert::ToString(checkable->GetCheckAttempt()), "check_attempt", Convert::ToString(checkable->GetCheckAttempt()),
@ -2047,8 +2047,9 @@ void IcingaDB::SendSentNotification(
auto usersAmount (users.size()); auto usersAmount (users.size());
auto sendTs (TimestampToMilliseconds(sendTime)); auto sendTs (TimestampToMilliseconds(sendTime));
auto notificationTypeStr(GetNotificationTypeByEnum(type));
Array::Ptr rawId = new Array({m_EnvironmentId, notification->GetName()}); Array::Ptr rawId = new Array({m_EnvironmentId, notification->GetName()});
rawId->Add(GetNotificationTypeByEnum(type)); rawId->Add(notificationTypeStr);
rawId->Add(sendTs); rawId->Add(sendTs);
auto notificationHistoryId (HashValue(rawId)); auto notificationHistoryId (HashValue(rawId));
@ -2059,7 +2060,7 @@ void IcingaDB::SendSentNotification(
"environment_id", m_EnvironmentId, "environment_id", m_EnvironmentId,
"notification_id", GetObjectIdentifier(notification), "notification_id", GetObjectIdentifier(notification),
"host_id", GetObjectIdentifier(host), "host_id", GetObjectIdentifier(host),
"type", Convert::ToString(type), "type", notificationTypeStr,
"state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99), "state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetState()) : Convert::ToLong(Host::CalculateState(cr->GetState())) : 99),
"previous_hard_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetPreviousHardState()) : Convert::ToLong(Host::CalculateState(cr->GetPreviousHardState())) : 99), "previous_hard_state", Convert::ToString(cr ? service ? Convert::ToLong(cr->GetPreviousHardState()) : Convert::ToLong(Host::CalculateState(cr->GetPreviousHardState())) : 99),
"author", Utility::ValidateUTF8(author), "author", Utility::ValidateUTF8(author),
@ -2300,7 +2301,7 @@ void IcingaDB::SendAddedComment(const Comment::Ptr& comment)
"entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())), "entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())),
"author", Utility::ValidateUTF8(comment->GetAuthor()), "author", Utility::ValidateUTF8(comment->GetAuthor()),
"comment", Utility::ValidateUTF8(comment->GetText()), "comment", Utility::ValidateUTF8(comment->GetText()),
"entry_type", Convert::ToString(comment->GetEntryType()), "entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType()),
"is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()),
"is_sticky", Convert::ToString((unsigned short)comment->GetSticky()), "is_sticky", Convert::ToString((unsigned short)comment->GetSticky()),
"event_id", CalcEventID("comment_add", comment), "event_id", CalcEventID("comment_add", comment),
@ -2372,7 +2373,7 @@ void IcingaDB::SendRemovedComment(const Comment::Ptr& comment)
"entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())), "entry_time", Convert::ToString(TimestampToMilliseconds(comment->GetEntryTime())),
"author", Utility::ValidateUTF8(comment->GetAuthor()), "author", Utility::ValidateUTF8(comment->GetAuthor()),
"comment", Utility::ValidateUTF8(comment->GetText()), "comment", Utility::ValidateUTF8(comment->GetText()),
"entry_type", Convert::ToString(comment->GetEntryType()), "entry_type", IcingaDB::CommentTypeToString(comment->GetEntryType()),
"is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()), "is_persistent", Convert::ToString((unsigned short)comment->GetPersistent()),
"is_sticky", Convert::ToString((unsigned short)comment->GetSticky()), "is_sticky", Convert::ToString((unsigned short)comment->GetSticky()),
"event_id", CalcEventID("comment_remove", comment), "event_id", CalcEventID("comment_remove", comment),
@ -2954,7 +2955,7 @@ Dictionary::Ptr IcingaDB::SerializeState(const Checkable::Ptr& checkable)
*/ */
attrs->Set("id", id); attrs->Set("id", id);
attrs->Set("environment_id", m_EnvironmentId); attrs->Set("environment_id", m_EnvironmentId);
attrs->Set("state_type", checkable->HasBeenChecked() ? checkable->GetStateType() : StateTypeHard); attrs->Set("state_type", Checkable::StateTypeToString(checkable->HasBeenChecked() ? checkable->GetStateType() : StateTypeHard).ToLower());
// TODO: last_hard/soft_state should be "previous". // TODO: last_hard/soft_state should be "previous".
if (service) { if (service) {
@ -3017,7 +3018,9 @@ Dictionary::Ptr IcingaDB::SerializeState(const Checkable::Ptr& checkable)
attrs->Set("is_reachable", checkable->IsReachable()); attrs->Set("is_reachable", checkable->IsReachable());
attrs->Set("is_flapping", checkable->IsFlapping()); attrs->Set("is_flapping", checkable->IsFlapping());
attrs->Set("is_acknowledged", checkable->GetAcknowledgement()); attrs->Set("is_acknowledged", checkable->IsAcknowledged());
attrs->Set("is_sticky_acknowledgement", checkable->GetAcknowledgement() == AcknowledgementSticky);
if (checkable->IsAcknowledged()) { if (checkable->IsAcknowledged()) {
Timestamp entry = 0; Timestamp entry = 0;
Comment::Ptr AckComment; Comment::Ptr AckComment;

View File

@ -219,6 +219,35 @@ Dictionary::Ptr IcingaDB::SerializeRedundancyGroupState(const Checkable::Ptr& ch
}; };
} }
/**
* Converts the given filter to its Redis value representation.
*
* Within the Icinga 2 code base, if the states filter bitsets are set to -1, the filter will match on all states.
* However, since sending -1 to Redis would crash the Icinga DB daemon, as the "states" field is of type uint8, so
* the primary purpose of this function is to make sure that no values outside the valid range of 0-255 are sent to Redis.
*
* @param filter The filter to convert.
*/
int IcingaDB::StateFilterToRedisValue(int filter)
{
return filter & StateFilterAll;
}
/**
* Converts the given filter to its Redis value representation.
*
* Within the Icinga 2 code base, if the types filter bitsets are set to -1, the filter will match on all types.
* However, since sending -1 to Redis would crash the Icinga DB daemon, as the "types" field is of type uint16, so
* the primary purpose of this function is to make sure that no values outside the "types" field's valid range are
* sent to Redis.
*
* @param filter The filter to convert.
*/
int IcingaDB::TypeFilterToRedisValue(int filter)
{
return filter & NotificationTypeAll;
}
const char* IcingaDB::GetNotificationTypeByEnum(NotificationType type) const char* IcingaDB::GetNotificationTypeByEnum(NotificationType type)
{ {
switch (type) { switch (type) {
@ -240,9 +269,24 @@ const char* IcingaDB::GetNotificationTypeByEnum(NotificationType type)
return "flapping_start"; return "flapping_start";
case NotificationFlappingEnd: case NotificationFlappingEnd:
return "flapping_end"; return "flapping_end";
} default:
VERIFY(!"Invalid notification type."); VERIFY(!"Invalid notification type.");
}
}
/**
* Converts the given comment type to its string representation.
*
* @ingroup icinga
*/
String IcingaDB::CommentTypeToString(CommentType type)
{
switch (type) {
case CommentUser: return "comment";
case CommentAcknowledgement: return "ack";
default:
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid comment type specified"));
}
} }
static const std::set<String> propertiesBlacklistEmpty; static const std::set<String> propertiesBlacklistEmpty;

View File

@ -173,7 +173,10 @@ private:
static String GetObjectIdentifier(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 CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime = 0, NotificationType nt = NotificationType(0));
static int StateFilterToRedisValue(int filter);
static int TypeFilterToRedisValue(int filter);
static const char* GetNotificationTypeByEnum(NotificationType type); static const char* GetNotificationTypeByEnum(NotificationType type);
static String CommentTypeToString(CommentType type);
static Dictionary::Ptr SerializeVars(const Dictionary::Ptr& vars); static Dictionary::Ptr SerializeVars(const Dictionary::Ptr& vars);
static Dictionary::Ptr SerializeDependencyEdgeState(const DependencyGroup::Ptr& dependencyGroup, const Dependency::Ptr& dep); static Dictionary::Ptr SerializeDependencyEdgeState(const DependencyGroup::Ptr& dependencyGroup, const Dependency::Ptr& dep);
static Dictionary::Ptr SerializeRedundancyGroupState(const Checkable::Ptr& child, const DependencyGroup::Ptr& redundancyGroup); static Dictionary::Ptr SerializeRedundancyGroupState(const Checkable::Ptr& child, const DependencyGroup::Ptr& redundancyGroup);