Implement last_notification_result handling for Notification objects

This commit is contained in:
Michael Friedrich 2018-07-25 14:33:28 +02:00
parent ac483f2a8a
commit 1706b297a5
8 changed files with 60 additions and 18 deletions

View File

@ -532,10 +532,14 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User::
String commandName = command->GetName(); String commandName = command->GetName();
try { try {
command->Execute(this, user, cr, type, author, text); NotificationResult::Ptr nr = new NotificationResult();
nr->SetExecutionStart(Utility::GetTime());
command->Execute(this, user, cr, nr, type, author, text);
/* required by compatlogger */ /* required by compatlogger */
Service::OnNotificationSentToUser(this, GetCheckable(), user, type, cr, author, text, commandName, nullptr); Checkable::OnNotificationSentToUser(this, GetCheckable(), user, type, cr, author, text, command->GetName(), nullptr);
Log(LogInformation, "Notification") Log(LogInformation, "Notification")
<< "Completed sending '" << NotificationTypeToStringInternal(type) << "Completed sending '" << NotificationTypeToStringInternal(type)
@ -556,6 +560,27 @@ void Notification::ProcessNotificationResult(const NotificationResult::Ptr& nr,
if (!nr) if (!nr)
return; return;
double now = Utility::GetTime();
if (nr->GetExecutionStart() == 0)
nr->SetExecutionStart(now);
if (nr->GetExecutionEnd() == 0)
nr->SetExecutionEnd(now);
/* Determine the execution endpoint from a locally executed check. */
if (!origin || origin->IsLocal())
nr->SetExecutionEndpoint(IcingaApplication::GetInstance()->GetNodeName());
if (!IsActive())
return;
{
ObjectLock olock(this);
SetLastNotificationResult(nr);
}
/* Notify cluster, API and feature events. */ /* Notify cluster, API and feature events. */
OnNewNotificationResult(this, nr, origin); OnNewNotificationResult(this, nr, origin);
} }

View File

@ -83,7 +83,7 @@ public:
Endpoint::Ptr GetCommandEndpoint() const; Endpoint::Ptr GetCommandEndpoint() const;
void ProcessNotificationResult(const NotificationResult::Ptr& nr, const MessageOrigin::Ptr& origin); void ProcessNotificationResult(const NotificationResult::Ptr& nr, const MessageOrigin::Ptr& origin = nullptr);
static String NotificationTypeToString(NotificationType type); static String NotificationTypeToString(NotificationType type);
static String NotificationFilterToString(int filter, const std::map<String, int>& filterMap); static String NotificationFilterToString(int filter, const std::map<String, int>& filterMap);

View File

@ -1,6 +1,8 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "icinga/customvarobject.hpp" #include "icinga/customvarobject.hpp"
#include "icinga/notificationresult.hpp"
#include "base/array.hpp"
#impl_include "icinga/notificationcommand.hpp" #impl_include "icinga/notificationcommand.hpp"
#impl_include "icinga/service.hpp" #impl_include "icinga/service.hpp"
@ -16,6 +18,7 @@ public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const; virtual Dictionary::Ptr ParseName(const String& name) const;
}; };
}}} }}}
class Notification : CustomVarObject < NotificationNameComposer class Notification : CustomVarObject < NotificationNameComposer
@ -81,6 +84,7 @@ class Notification : CustomVarObject < NotificationNameComposer
[state] Timestamp next_notification; [state] Timestamp next_notification;
[state] int notification_number; [state] int notification_number;
[state] Timestamp last_problem_notification; [state] Timestamp last_problem_notification;
[state] NotificationResult::Ptr last_notification_result;
[config, navigation] name(Endpoint) command_endpoint (CommandEndpointRaw) { [config, navigation] name(Endpoint) command_endpoint (CommandEndpointRaw) {
navigate {{{ navigate {{{

View File

@ -8,14 +8,15 @@ using namespace icinga;
REGISTER_TYPE(NotificationCommand); REGISTER_TYPE(NotificationCommand);
Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notification, Dictionary::Ptr NotificationCommand::Execute(const Notification::Ptr& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationType& type, const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationResult::Ptr& nr,
const String& author, const String& comment, const Dictionary::Ptr& resolvedMacros, const NotificationType& type, const String& author, const String& comment,
bool useResolvedMacros) const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{ {
return GetExecute()->Invoke({ return GetExecute()->Invoke({
notification, notification,
user, user,
cr, cr,
nr,
type, type,
author, author,
comment, comment,

View File

@ -23,8 +23,8 @@ public:
DECLARE_OBJECTNAME(NotificationCommand); DECLARE_OBJECTNAME(NotificationCommand);
virtual Dictionary::Ptr Execute(const intrusive_ptr<Notification>& notification, virtual Dictionary::Ptr Execute(const intrusive_ptr<Notification>& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationType& type, const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationResult::Ptr& nr,
const String& author, const String& comment, const NotificationType& type, const String& author, const String& comment,
const Dictionary::Ptr& resolvedMacros = nullptr, const Dictionary::Ptr& resolvedMacros = nullptr,
bool useResolvedMacros = false); bool useResolvedMacros = false);
}; };

View File

@ -19,7 +19,6 @@
#include "icinga/notificationresult.hpp" #include "icinga/notificationresult.hpp"
#include "icinga/notificationresult-ti.cpp" #include "icinga/notificationresult-ti.cpp"
#include "base/scriptglobal.hpp"
using namespace icinga; using namespace icinga;

View File

@ -15,12 +15,12 @@
using namespace icinga; using namespace icinga;
REGISTER_FUNCTION_NONCONST(Internal, PluginNotification, &PluginNotificationTask::ScriptFunc, "notification:user:cr:itype:author:comment:resolvedMacros:useResolvedMacros"); REGISTER_FUNCTION_NONCONST(Internal, PluginNotification, &PluginNotificationTask::ScriptFunc, "notification:user:cr:nr:itype:author:comment:resolvedMacros:useResolvedMacros");
void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification, void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, int itype, const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationResult::Ptr& nr,
const String& author, const String& comment, const Dictionary::Ptr& resolvedMacros, int itype, const String& author, const String& comment,
bool useResolvedMacros) const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros)
{ {
REQUIRE_NOT_NULL(notification); REQUIRE_NOT_NULL(notification);
REQUIRE_NOT_NULL(user); REQUIRE_NOT_NULL(user);
@ -55,16 +55,28 @@ void PluginNotificationTask::ScriptFunc(const Notification::Ptr& notification,
PluginUtility::ExecuteCommand(commandObj, checkable, cr, resolvers, PluginUtility::ExecuteCommand(commandObj, checkable, cr, resolvers,
resolvedMacros, useResolvedMacros, timeout, resolvedMacros, useResolvedMacros, timeout,
std::bind(&PluginNotificationTask::ProcessFinishedHandler, checkable, _1, _2)); std::bind(&PluginNotificationTask::ProcessFinishedHandler, checkable, notification, nr, _1, _2));
} }
void PluginNotificationTask::ProcessFinishedHandler(const Checkable::Ptr& checkable, const Value& commandLine, const ProcessResult& pr) void PluginNotificationTask::ProcessFinishedHandler(const Checkable::Ptr& checkable,
const Notification::Ptr& notification, const NotificationResult::Ptr& nr, const Value& commandLine, const ProcessResult& pr)
{ {
if (pr.ExitStatus != 0) { if (pr.ExitStatus != 0) {
Process::Arguments parguments = Process::PrepareCommand(commandLine); Process::Arguments parguments = Process::PrepareCommand(commandLine);
Log(LogWarning, "PluginNotificationTask") Log(LogWarning, "PluginNotificationTask")
<< "Notification command for object '" << checkable->GetName() << "' (PID: " << pr.PID << "Notification command for checkable '" << checkable->GetName()
<< "' and notification '" << notification->GetName() << "' (PID: " << pr.PID
<< ", arguments: " << Process::PrettyPrintArguments(parguments) << ") terminated with exit code " << ", arguments: " << Process::PrettyPrintArguments(parguments) << ") terminated with exit code "
<< pr.ExitStatus << ", output: " << pr.Output; << pr.ExitStatus << ", output: " << pr.Output;
} }
String output = pr.Output.Trim();
nr->SetCommand(commandLine);
nr->SetOutput(output);
nr->SetExitStatus(pr.ExitStatus);
nr->SetExecutionStart(pr.ExecutionStart);
nr->SetExecutionEnd(pr.ExecutionEnd);
notification->ProcessNotificationResult(nr);
} }

View File

@ -20,14 +20,15 @@ class PluginNotificationTask
{ {
public: public:
static void ScriptFunc(const Notification::Ptr& notification, static void ScriptFunc(const Notification::Ptr& notification,
const User::Ptr& user, const CheckResult::Ptr& cr, int itype, const User::Ptr& user, const CheckResult::Ptr& cr, const NotificationResult::Ptr& nr,
const String& author, const String& comment, int itype, const String& author, const String& comment,
const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros); const Dictionary::Ptr& resolvedMacros, bool useResolvedMacros);
private: private:
PluginNotificationTask(); PluginNotificationTask();
static void ProcessFinishedHandler(const Checkable::Ptr& checkable, static void ProcessFinishedHandler(const Checkable::Ptr& checkable,
const Notification::Ptr& notification, const NotificationResult::Ptr& nr,
const Value& commandLine, const ProcessResult& pr); const Value& commandLine, const ProcessResult& pr);
}; };