mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-25 22:54:57 +02:00
Only notify users on recovery who have been notified on not-OK before
Also ensure that type NotificationRecovery always passes the state filter (missing `OK` is totally fine). Also fix that notification delays set the correct next notification time to the begin time window. fixes #7579 fixes #7623 fixes #6547
This commit is contained in:
parent
478f03b49a
commit
885e7704a2
@ -610,8 +610,6 @@ to the defined notifications. That way you'll save duplicated attributes in each
|
|||||||
|
|
||||||
The time period `24x7` is shipped as example configuration with Icinga 2.
|
The time period `24x7` is shipped as example configuration with Icinga 2.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Use the `apply` keyword to create `Notification` objects for your services:
|
Use the `apply` keyword to create `Notification` objects for your services:
|
||||||
|
|
||||||
apply Notification "notify-cust-xy-mysql" to Service {
|
apply Notification "notify-cust-xy-mysql" to Service {
|
||||||
@ -628,6 +626,11 @@ Instead of assigning users to notifications, you can also add the `user_groups`
|
|||||||
attribute with a list of user groups to the `Notification` object. Icinga 2 will
|
attribute with a list of user groups to the `Notification` object. Icinga 2 will
|
||||||
send notifications to all group members.
|
send notifications to all group members.
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Only users who have been notified of a problem before (`Warning`, `Critical`, `Unknown`
|
||||||
|
> states for services, `Down` for hosts) will receive `Recovery` notifications.
|
||||||
|
|
||||||
### <a id="notification-escalations"></a> Notification Escalations
|
### <a id="notification-escalations"></a> Notification Escalations
|
||||||
|
|
||||||
When a problem notification is sent and a problem still exists at the time of re-notification
|
When a problem notification is sent and a problem still exists at the time of re-notification
|
||||||
|
@ -245,6 +245,14 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
|
|||||||
if (times && times->Contains("begin") && now < checkable->GetLastHardStateChange() + times->Get("begin")) {
|
if (times && times->Contains("begin") && now < checkable->GetLastHardStateChange() + times->Get("begin")) {
|
||||||
Log(LogNotice, "Notification")
|
Log(LogNotice, "Notification")
|
||||||
<< "Not sending notifications for notification object '" << GetName() << "': before escalation range";
|
<< "Not sending notifications for notification object '" << GetName() << "': before escalation range";
|
||||||
|
|
||||||
|
/* we need to adjust the next notification time
|
||||||
|
* to now + begin delaying the first notification
|
||||||
|
*/
|
||||||
|
double nextProposedNotification = now + times->Get("begin") + 1.0;
|
||||||
|
if (GetNextNotification() > nextProposedNotification)
|
||||||
|
SetNextNotification(nextProposedNotification);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +270,13 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
|
|||||||
|
|
||||||
if (!(ftype & GetTypeFilter())) {
|
if (!(ftype & GetTypeFilter())) {
|
||||||
Log(LogNotice, "Notification")
|
Log(LogNotice, "Notification")
|
||||||
<< "Not sending notifications for notification object '" << GetName() << "': type filter does not match";
|
<< "Not sending notifications for notification object '" << GetName() << "': type filter does not match '"
|
||||||
|
<< NotificationTypeToString(type) << "'";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ensure that recovery notifications are always sent, no state filter checks necessary */
|
||||||
|
if (type != NotificationRecovery) {
|
||||||
Host::Ptr host;
|
Host::Ptr host;
|
||||||
Service::Ptr service;
|
Service::Ptr service;
|
||||||
tie(host, service) = GetHostService(checkable);
|
tie(host, service) = GetHostService(checkable);
|
||||||
@ -283,6 +294,7 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
@ -307,19 +319,47 @@ void Notification::BeginExecuteNotification(NotificationType type, const CheckRe
|
|||||||
Service::OnNotificationSendStart(this, checkable, allUsers, type, cr, author, text);
|
Service::OnNotificationSendStart(this, checkable, allUsers, type, cr, author, text);
|
||||||
|
|
||||||
std::set<User::Ptr> allNotifiedUsers;
|
std::set<User::Ptr> allNotifiedUsers;
|
||||||
|
|
||||||
BOOST_FOREACH(const User::Ptr& user, allUsers) {
|
BOOST_FOREACH(const User::Ptr& user, allUsers) {
|
||||||
if (!user->GetEnableNotifications() || !CheckNotificationUserFilters(type, user, force))
|
String userName = user->GetName();
|
||||||
|
|
||||||
|
if (!user->GetEnableNotifications()) {
|
||||||
|
Log(LogNotice, "Notification")
|
||||||
|
<< "Disabled notifications for user '" << userName << "'. Not sending notification.";
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CheckNotificationUserFilters(type, user, force)) {
|
||||||
|
Log(LogNotice, "Notification")
|
||||||
|
<< "Notification filters for user '" << userName << "' not matched. Not sending notification.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* on recovery, check if user was notified before */
|
||||||
|
if (type == NotificationRecovery) {
|
||||||
|
if (m_NotifiedUsers.find(userName) == m_NotifiedUsers.end()) {
|
||||||
|
Log(LogNotice, "Notification")
|
||||||
|
<< "We did not notify user '" << userName << "' before. Not sending recovery notification.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log(LogInformation, "Notification")
|
Log(LogInformation, "Notification")
|
||||||
<< "Sending notification for user '" << user->GetName() << "'";
|
<< "Sending notification for user '" << userName << "'";
|
||||||
|
|
||||||
Utility::QueueAsyncCallback(boost::bind(&Notification::ExecuteNotificationHelper, this, type, user, cr, force, author, text));
|
Utility::QueueAsyncCallback(boost::bind(&Notification::ExecuteNotificationHelper, this, type, user, cr, force, author, text));
|
||||||
|
|
||||||
/* collect all notified users */
|
/* collect all notified users */
|
||||||
allNotifiedUsers.insert(user);
|
allNotifiedUsers.insert(user);
|
||||||
|
|
||||||
|
/* store all notified users for later recovery checks */
|
||||||
|
m_NotifiedUsers.insert(userName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if this was a recovery notification, reset all notified users */
|
||||||
|
if (type == NotificationRecovery)
|
||||||
|
ResetNotifiedUsers();
|
||||||
|
|
||||||
/* used in db_ido for notification history */
|
/* used in db_ido for notification history */
|
||||||
Service::OnNotificationSentToAllUsers(this, checkable, allNotifiedUsers, type, cr, author, text);
|
Service::OnNotificationSentToAllUsers(this, checkable, allNotifiedUsers, type, cr, author, text);
|
||||||
}
|
}
|
||||||
@ -347,6 +387,8 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check state filters it this is not a recovery notification */
|
||||||
|
if (type != NotificationRecovery) {
|
||||||
Checkable::Ptr checkable = GetCheckable();
|
Checkable::Ptr checkable = GetCheckable();
|
||||||
Host::Ptr host;
|
Host::Ptr host;
|
||||||
Service::Ptr service;
|
Service::Ptr service;
|
||||||
@ -366,6 +408,7 @@ bool Notification::CheckNotificationUserFilters(NotificationType type, const Use
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -403,6 +446,11 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Notification::ResetNotifiedUsers(void)
|
||||||
|
{
|
||||||
|
m_NotifiedUsers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
int icinga::ServiceStateToFilter(ServiceState state)
|
int icinga::ServiceStateToFilter(ServiceState state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -471,4 +519,3 @@ void Notification::ValidateFilters(const String& location, const Dictionary::Ptr
|
|||||||
location + ": Type filter is invalid.");
|
location + ": Type filter is invalid.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ public:
|
|||||||
|
|
||||||
bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force);
|
bool CheckNotificationUserFilters(NotificationType type, const User::Ptr& user, bool force);
|
||||||
|
|
||||||
|
void ResetNotifiedUsers(void);
|
||||||
|
|
||||||
static String NotificationTypeToString(NotificationType type);
|
static String NotificationTypeToString(NotificationType type);
|
||||||
|
|
||||||
static boost::signals2::signal<void (const Notification::Ptr&, double, const MessageOrigin&)> OnNextNotificationChanged;
|
static boost::signals2::signal<void (const Notification::Ptr&, double, const MessageOrigin&)> OnNextNotificationChanged;
|
||||||
@ -111,6 +113,8 @@ protected:
|
|||||||
virtual void Stop(void);
|
virtual void Stop(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::set<String> m_NotifiedUsers;
|
||||||
|
|
||||||
void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
|
void ExecuteNotificationHelper(NotificationType type, const User::Ptr& user, const CheckResult::Ptr& cr, bool force, const String& author = "", const String& text = "");
|
||||||
|
|
||||||
static void EvaluateApplyRuleOneInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
|
static void EvaluateApplyRuleOneInstance(const intrusive_ptr<Checkable>& checkable, const String& name, const Dictionary::Ptr& locals, const ApplyRule& rule);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user