From 3a99842f9069ba3ff8aa0aaa5f81febfbcbd3330 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 28 Feb 2013 11:45:47 +0100 Subject: [PATCH] Implement the PerfdataWriter class. --- lib/icinga/Makefile.am | 2 + lib/icinga/i2-icinga.h | 2 + lib/icinga/notification.cpp | 3 - lib/icinga/perfdatawriter.cpp | 149 ++++++++++++++++++++++++++++++++++ lib/icinga/perfdatawriter.h | 67 +++++++++++++++ lib/icinga/service.cpp | 1 + 6 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 lib/icinga/perfdatawriter.cpp create mode 100644 lib/icinga/perfdatawriter.h diff --git a/lib/icinga/Makefile.am b/lib/icinga/Makefile.am index e0fea7705..f4c82ae9f 100644 --- a/lib/icinga/Makefile.am +++ b/lib/icinga/Makefile.am @@ -29,6 +29,8 @@ libicinga_la_SOURCES = \ notificationrequestmessage.h \ nullchecktask.cpp \ nullchecktask.h \ + perfdatawriter.cpp \ + perfdatawriter.h \ pluginchecktask.cpp \ pluginchecktask.h \ pluginnotificationtask.cpp \ diff --git a/lib/icinga/i2-icinga.h b/lib/icinga/i2-icinga.h index d368fdd93..393198820 100644 --- a/lib/icinga/i2-icinga.h +++ b/lib/icinga/i2-icinga.h @@ -69,4 +69,6 @@ using boost::algorithm::is_any_of; #include "api.h" +#include "perfdatawriter.h" + #endif /* I2ICINGA_H */ diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index 3e2d493c3..7cb4543c7 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -43,9 +43,6 @@ Notification::Ptr Notification::GetByName(const String& name) { DynamicObject::Ptr configObject = DynamicObject::GetObject("Notification", name); - if (!configObject) - BOOST_THROW_EXCEPTION(invalid_argument("Notification '" + name + "' does not exist.")); - return dynamic_pointer_cast(configObject); } diff --git a/lib/icinga/perfdatawriter.cpp b/lib/icinga/perfdatawriter.cpp new file mode 100644 index 000000000..70a8701d1 --- /dev/null +++ b/lib/icinga/perfdatawriter.cpp @@ -0,0 +1,149 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "i2-icinga.h" + +using namespace icinga; + +REGISTER_TYPE(PerfdataWriter, NULL); + +PerfdataWriter::PerfdataWriter(const Dictionary::Ptr& properties) + : DynamicObject(properties) +{ + RegisterAttribute("path_prefix", Attribute_Config, &m_PathPrefix); + RegisterAttribute("format_template", Attribute_Config, &m_FormatTemplate); + RegisterAttribute("rotation_interval", Attribute_Config, &m_RotationInterval); +} + +PerfdataWriter::~PerfdataWriter(void) +{ +} + +void PerfdataWriter::OnAttributeChanged(const String& name, const Value& oldValue) +{ + if (name == "rotation_interval") { + ObjectLock olock(this); + m_RotationTimer->SetInterval(GetRotationInterval()); + } +} + +void PerfdataWriter::Start(void) +{ + m_Endpoint = Endpoint::MakeEndpoint("perfdata_" + GetName(), false); + + { + ObjectLock olock(m_Endpoint); + m_Endpoint->RegisterTopicHandler("checker::CheckResult", + boost::bind(&PerfdataWriter::CheckResultRequestHandler, this, _3)); + } + + m_RotationTimer = boost::make_shared(); + m_RotationTimer->OnTimerExpired.connect(boost::bind(&PerfdataWriter::RotationTimerHandler, this)); + m_RotationTimer->SetInterval(GetRotationInterval()); + m_RotationTimer->Start(); + + RotateFile(); +} + +PerfdataWriter::Ptr PerfdataWriter::GetByName(const String& name) +{ + DynamicObject::Ptr configObject = DynamicObject::GetObject("PerfdataWriter", name); + + return dynamic_pointer_cast(configObject); +} + +String PerfdataWriter::GetPathPrefix(void) const +{ + if (!m_PathPrefix.IsEmpty()) + return m_PathPrefix; + else + return Application::GetLocalStateDir() + "/cache/icinga2/perfdata/perfdata"; +} + +String PerfdataWriter::GetFormatTemplate(void) const +{ + if (!m_FormatTemplate.IsEmpty()) { + return m_FormatTemplate; + } else { + return "DATATYPE::SERVICEPERFDATA\t" + "TIMET::$TIMET$\t" + "HOSTNAME::$HOSTNAME$\t" + "SERVICEDESC::$SERVICEDESC$\t" + "SERVICEPERFDATA::$SERVICEPERFDATA$\t" + "SERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\t" + "HOSTSTATE::$HOSTSTATE$\t" + "HOSTSTATETYPE::$HOSTSTATETYPE$\t" + "SERVICESTATE::$SERVICESTATE$\t" + "SERVICESTATETYPE::$SERVICESTATETYPE$"; + } +} + +double PerfdataWriter::GetRotationInterval(void) const +{ + if (!m_RotationInterval.IsEmpty()) + return m_RotationInterval; + else + return 30; +} + +void PerfdataWriter::CheckResultRequestHandler(const RequestMessage& request) +{ + CheckResultMessage params; + if (!request.GetParams(¶ms)) + return; + + String svcname = params.GetService(); + Service::Ptr service = Service::GetByName(svcname); + + Dictionary::Ptr cr = params.GetCheckResult(); + if (!cr) + return; + + Dictionary::Ptr macros = cr->Get("macros"); + String line = MacroProcessor::ResolveMacros(GetFormatTemplate(), macros); + + if (!m_OutputFile.good()) + return; + + ObjectLock olock(this); + m_OutputFile << line << "\n"; +} + +void PerfdataWriter::RotateFile(void) +{ + String tempFile = GetPathPrefix(); + + if (m_OutputFile.good()) { + m_OutputFile.close(); + + String finalFile = GetPathPrefix() + "." + Convert::ToString((long)Utility::GetTime()); + (void) rename(tempFile.CStr(), finalFile.CStr()); + } + + m_OutputFile.open(tempFile.CStr()); + + if (!m_OutputFile.good()) + Logger::Write(LogWarning, "icinga", "Could not open perfdata file '" + tempFile + "' for writing. Perfdata will be lost."); +} + +void PerfdataWriter::RotationTimerHandler(void) +{ + ObjectLock olock(this); + RotateFile(); +} diff --git a/lib/icinga/perfdatawriter.h b/lib/icinga/perfdatawriter.h new file mode 100644 index 000000000..1ec02048a --- /dev/null +++ b/lib/icinga/perfdatawriter.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef PERFDATAWRITER_H +#define PERFDATAWRITER_H + +namespace icinga +{ + +/** + * An Icinga perfdata writer. + * + * @ingroup icinga + */ +class I2_ICINGA_API PerfdataWriter : public DynamicObject +{ +public: + typedef shared_ptr Ptr; + typedef weak_ptr WeakPtr; + + PerfdataWriter(const Dictionary::Ptr& properties); + ~PerfdataWriter(void); + + static PerfdataWriter::Ptr GetByName(const String& name); + + String GetPathPrefix(void) const; + String GetFormatTemplate(void) const; + double GetRotationInterval(void) const; + +protected: + virtual void OnAttributeChanged(const String& name, const Value& oldValue); + virtual void Start(void); + +private: + Attribute m_PathPrefix; + Attribute m_FormatTemplate; + Attribute m_RotationInterval; + + Endpoint::Ptr m_Endpoint; + void CheckResultRequestHandler(const RequestMessage& request); + + Timer::Ptr m_RotationTimer; + void RotationTimerHandler(void); + + ofstream m_OutputFile; + void RotateFile(void); +}; + +} + +#endif /* PERFDATAWRITER_H */ diff --git a/lib/icinga/service.cpp b/lib/icinga/service.cpp index a951df828..c90499802 100644 --- a/lib/icinga/service.cpp +++ b/lib/icinga/service.cpp @@ -378,6 +378,7 @@ Dictionary::Ptr Service::CalculateDynamicMacros(const Service::Ptr& self) macros->Set("SERVICESTATETYPE", StateTypeToString(self->GetStateType())); macros->Set("SERVICEATTEMPT", self->GetCurrentCheckAttempt()); macros->Set("MAXSERVICEATTEMPT", self->GetMaxCheckAttempts()); + macros->Set("SERVICECHECKCOMMAND", "check_i2"); cr = self->GetLastCheckResult(); } -- 2.40.0