<< "\t" << "passive_checks_enabled" << "\t" << (hc->GetEnablePassiveChecks() ? 1 : 0) << "\n"
<< "\t" << "notifications_enabled" << "\t" << (hc->GetEnableNotifications() ? 1 : 0) << "\n"
<< "\t" << "notification_options" << "\t" << "d,u,r" << "\n"
- << "\t" << "notification_interval" << "\t" << hc->GetNotificationInterval() << "\n";
+ << "\t" << "notification_interval" << "\t" << 1 << "\n";
} else {
fp << "\t" << "check_interval" << "\t" << 60 << "\n"
<< "\t" << "retry_interval" << "\t" << 60 << "\n"
state = 2; /* UNREACHABLE */
}
+ double last_notification = 0;
+ BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+ if (notification->GetLastNotification() > last_notification)
+ last_notification = notification->GetLastNotification();
+ }
+
fp << "\t" << "check_interval=" << service->GetCheckInterval() / 60.0 << "\n"
<< "\t" << "retry_interval=" << service->GetRetryInterval() / 60.0 << "\n"
<< "\t" << "has_been_checked=" << (service->GetLastCheckResult() ? 1 : 0) << "\n"
<< "\t" << "acknowledgement_type=" << static_cast<int>(service->GetAcknowledgement()) << "\n"
<< "\t" << "acknowledgement_end_time=" << service->GetAcknowledgementExpiry() << "\n"
<< "\t" << "scheduled_downtime_depth=" << (service->IsInDowntime() ? 1 : 0) << "\n"
- << "\t" << "last_notification=" << service->GetLastNotification() << "\n";
+ << "\t" << "last_notification=" << last_notification << "\n";
}
void CompatComponent::DumpServiceStatus(std::ostream& fp, const Service::Ptr& service)
if (!host)
return;
+ double notification_interval = -1;
+ BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+ if (notification_interval == -1 || notification->GetNotificationInterval() < notification_interval)
+ notification_interval = notification->GetNotificationInterval();
+ }
+
{
ObjectLock olock(service);
<< "\t" << "passive_checks_enabled" << "\t" << (service->GetEnablePassiveChecks() ? 1 : 0) << "\n"
<< "\t" << "notifications_enabled" << "\t" << (service->GetEnableNotifications() ? 1 : 0) << "\n"
<< "\t" << "notification_options" << "\t" << "u,w,c,r" << "\n"
- << "\t" << "notification_interval" << "\t" << service->GetNotificationInterval() << "\n"
+ << "\t" << "notification_interval" << "\t" << notification_interval << "\n"
<< "\t" << "}" << "\n"
<< "\n";
}
#include "icinga/service.h"
#include "base/dynamictype.h"
#include "base/objectlock.h"
+#include "base/logger_fwd.h"
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/foreach.hpp>
}
/**
- * Periodically sends a notification::HelloWorld message.
+ * Periodically sends notifications.
*
* @param - Event arguments for the timer.
*/
{
double now = Utility::GetTime();
- BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Service")) {
- Service::Ptr service = dynamic_pointer_cast<Service>(object);
+ BOOST_FOREACH(const DynamicObject::Ptr& object, DynamicType::GetObjects("Notification")) {
+ Notification::Ptr notification = dynamic_pointer_cast<Notification>(object);
+
+ if (notification->GetNotificationInterval() <= 0)
+ continue;
+
+ if (notification->GetNextNotification() > now)
+ continue;
+
+ Service::Ptr service = notification->GetService();
bool reachable = service->IsReachable();
bool send_notification;
if (service->GetState() == StateOK)
continue;
- if (service->GetNotificationInterval() <= 0)
- continue;
+ send_notification = reachable && !service->IsInDowntime() && !service->IsAcknowledged();
+ }
- if (service->GetLastNotification() > now - service->GetNotificationInterval())
- continue;
+ if (!send_notification)
+ continue;
- send_notification = reachable && !service->IsInDowntime() && !service->IsAcknowledged();
+ try {
+ Log(LogInformation, "notification", "Sending reminder notification for service '" + service->GetName() + "'");
+ notification->BeginExecuteNotification(NotificationProblem, service->GetLastCheckResult());
+ } catch (const std::exception& ex) {
+ std::ostringstream msgbuf;
+ msgbuf << "Exception occured during notification for service '"
+ << GetName() << "': " << boost::diagnostic_information(ex);
+ String message = msgbuf.str();
+
+ Log(LogWarning, "icinga", message);
}
- if (send_notification)
- service->RequestNotifications(NotificationProblem, service->GetLastCheckResult());
+ notification->SetNextNotification(Utility::GetTime() + notification->GetNotificationInterval());
}
}
if (!hc)
return;
- {
- ObjectLock olock(hc);
+ BOOST_FOREACH(const Notification::Ptr& notification, hc->GetNotifications()) {
+ ObjectLock olock(notification);
- hc->SetLastNotification(Convert::ToDouble(arguments[1]));
+ notification->SetNextNotification(Convert::ToDouble(arguments[1]));
}
}
Log(LogInformation, "icinga", "Delaying notifications for service " + service->GetName());
- {
- ObjectLock olock(service);
+ BOOST_FOREACH(const Notification::Ptr& notification, service->GetNotifications()) {
+ ObjectLock olock(notification);
- service->SetLastNotification(Convert::ToDouble(arguments[2]));
+ notification->SetNextNotification(Convert::ToDouble(arguments[2]));
}
}
%attribute array "notification_command" {
%attribute string "*"
},
- %attribute string "notification_command"
+ %attribute string "notification_command",
+
+ %attribute number "notification_interval"
}
type User {
: DynamicObject(serializedUpdate)
{
RegisterAttribute("notification_command", Attribute_Config, &m_NotificationCommand);
+ RegisterAttribute("notification_interval", Attribute_Config, &m_NotificationInterval);
+ RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
+ RegisterAttribute("next_notification", Attribute_Replicated, &m_NextNotification);
RegisterAttribute("macros", Attribute_Config, &m_Macros);
RegisterAttribute("users", Attribute_Config, &m_Users);
RegisterAttribute("groups", Attribute_Config, &m_Groups);
return result;
}
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetNotificationInterval(void) const
+{
+ if (m_NotificationInterval.IsEmpty())
+ return 300;
+ else
+ return m_NotificationInterval;
+}
+
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetLastNotification(void) const
+{
+ if (m_LastNotification.IsEmpty())
+ return 0;
+ else
+ return m_LastNotification;
+}
+
+/**
+ * Sets the timestamp when the last notification was sent.
+ */
+void Notification::SetLastNotification(double time)
+{
+ m_LastNotification = time;
+ Touch("last_notification");
+}
+
+/**
+ * @threadsafety Always.
+ */
+double Notification::GetNextNotification(void) const
+{
+ if (m_NextNotification.IsEmpty())
+ return 0;
+ else
+ return m_NextNotification;
+}
+
+/**
+ * Sets the timestamp when the next periodical notification should be sent.
+ * This does not affect notifications that are sent for state changes.
+ */
+void Notification::SetNextNotification(double time)
+{
+ m_NextNotification = time;
+ Touch("next_notification");
+}
+
/**
* @threadsafety Always.
*/
{
ASSERT(!OwnsLock());
+ {
+ ObjectLock olock(this);
+
+ SetLastNotification(Utility::GetTime());
+ }
+
Dictionary::Ptr macros = cr->Get("macros");
std::set<User::Ptr> allUsers;
shared_ptr<Service> GetService(void) const;
Value GetNotificationCommand(void) const;
+ double GetNotificationInterval(void) const;
Dictionary::Ptr GetMacros(void) const;
std::set<User::Ptr> GetUsers(void) const;
std::set<UserGroup::Ptr> GetGroups(void) const;
+ double GetLastNotification(void) const;
+ void SetLastNotification(double time);
+
+ double GetNextNotification(void) const;
+ void SetNextNotification(double time);
+
void BeginExecuteNotification(NotificationType type, const Dictionary::Ptr& cr);
static String NotificationTypeToString(NotificationType type);
private:
Attribute<Value> m_NotificationCommand;
+ Attribute<double> m_NotificationInterval;
+ Attribute<double> m_LastNotification;
+ Attribute<double> m_NextNotification;
Attribute<Dictionary::Ptr> m_Macros;
Attribute<Array::Ptr> m_Users;
Attribute<Array::Ptr> m_Groups;
*/
void Service::RequestNotifications(NotificationType type, const Dictionary::Ptr& cr)
{
- {
- ObjectLock olock(this);
- SetLastNotification(Utility::GetTime());
- }
-
RequestMessage msg;
msg.SetMethod("icinga::SendNotifications");
}
}
- /* Clone attributes from the service object. */
+ /* Clone attributes from the host/service object. */
std::set<String, string_iless> keys;
keys.insert("users");
keys.insert("groups");
}
}
-/**
- * @threadsafety Always.
- */
-double Service::GetLastNotification(void) const
-{
- if (m_LastNotification.IsEmpty())
- return 0;
- else
- return m_LastNotification;
-}
-
-/**
- * @threadsafety Always.
- */
-void Service::SetLastNotification(double time)
-{
- m_LastNotification = time;
- Touch("last_notification");
-}
-
/**
* @threadsafety Always.
*/
m_EnableNotifications = enabled;
Touch("enable_notifications");
}
-
-/**
- * @threadsafety Always.
- */
-double Service::GetNotificationInterval(void) const
-{
- if (m_NotificationInterval.IsEmpty())
- return 300;
- else
- return m_NotificationInterval;
-}
RegisterAttribute("downtimes", Attribute_Replicated, &m_Downtimes);
RegisterAttribute("enable_notifications", Attribute_Replicated, &m_EnableNotifications);
- RegisterAttribute("last_notification", Attribute_Replicated, &m_LastNotification);
- RegisterAttribute("notification_interval", Attribute_Config, &m_NotificationInterval);
SetSchedulingOffset(rand());
}
bool GetEnableNotifications(void) const;
void SetEnableNotifications(bool enabled);
- double GetNotificationInterval(void) const;
-
void RequestNotifications(NotificationType type, const Dictionary::Ptr& cr);
void SendNotifications(NotificationType type, const Dictionary::Ptr& cr);
void UpdateSlaveNotifications(void);
- double GetLastNotification(void) const;
- void SetLastNotification(double time);
-
protected:
virtual void OnRegistrationCompleted(void);
virtual void OnAttributeChanged(const String& name);
/* Notifications */
Attribute<bool> m_EnableNotifications;
- Attribute<double> m_LastNotification;
- Attribute<double> m_NotificationInterval;
static void RefreshNotificationsCache(void);
};