]> granicus.if.org Git - icinga2/commitdiff
Graphite/PerfdataWriter: Add host perfdata.
authorMichael Friedrich <michael.friedrich@netways.de>
Tue, 1 Apr 2014 18:30:44 +0000 (20:30 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Wed, 2 Apr 2014 12:13:24 +0000 (14:13 +0200)
Fixes #5908

components/perfdata/graphitewriter.cpp
components/perfdata/graphitewriter.h
components/perfdata/perfdatawriter.cpp
components/perfdata/perfdatawriter.h
components/perfdata/perfdatawriter.ti
doc/2.1-setting-up-icinga-2.md
doc/3.11-performance-data.md
doc/4.3-object-types.md
doc/8-differences-between-icinga-1x-and-2.md
lib/icinga/host.cpp

index dabb2386ce7234149799669fd095f86a2450d384..a64df710893a5a0e946d8546cbb9505faba7c9ad 100644 (file)
@@ -82,7 +82,7 @@ void GraphiteWriter::ReconnectTimerHandler(void)
                        return;
                }
        } catch (const std::exception& ex) {
-               Log(LogWarning, "perfdata", "GraphiteWriter socket on host '" + GetHost() + "' port '" + GetPort() + "' gone. Attempting to reconnect.");       
+               Log(LogWarning, "perfdata", "GraphiteWriter socket on host '" + GetHost() + "' port '" + GetPort() + "' gone. Attempting to reconnect.");
        }
 
        TcpSocket::Ptr socket = make_shared<TcpSocket>();
@@ -99,16 +99,17 @@ void GraphiteWriter::CheckResultHandler(const Service::Ptr& service, const Check
        if (!IcingaApplication::GetInstance()->GetEnablePerfdata() || !service->GetEnablePerfdata())
                return;
 
-       /* TODO: sanitize host and service names */
-       String hostName = service->GetHost()->GetName();
-       String serviceName = service->GetShortName();   
+       Host::Ptr host = service->GetHost();
+
+       String hostName = host->GetName();
+       String serviceName = service->GetShortName();
 
        SanitizeMetric(hostName);
        SanitizeMetric(serviceName);
 
        String prefix = "icinga." + hostName + "." + serviceName;
 
-       /* basic metrics */
+       /* service metrics */
        SendMetric(prefix, "current_attempt", service->GetCheckAttempt());
        SendMetric(prefix, "max_check_attempts", service->GetMaxCheckAttempts());
        SendMetric(prefix, "state_type", service->GetStateType());
@@ -116,6 +117,25 @@ void GraphiteWriter::CheckResultHandler(const Service::Ptr& service, const Check
        SendMetric(prefix, "latency", Service::CalculateLatency(cr));
        SendMetric(prefix, "execution_time", Service::CalculateExecutionTime(cr));
 
+       SendPerfdata(prefix, cr);
+
+       if (service == host->GetCheckService()) {
+               prefix = "icinga." + hostName; // TODO works?
+
+               /* host metrics */
+               SendMetric(prefix, "current_attempt", service->GetCheckAttempt());
+               SendMetric(prefix, "max_check_attempts", service->GetMaxCheckAttempts());
+               SendMetric(prefix, "state_type", host->GetStateType());
+               SendMetric(prefix, "state", host->GetState());
+               SendMetric(prefix, "latency", Service::CalculateLatency(cr));
+               SendMetric(prefix, "execution_time", Service::CalculateExecutionTime(cr));
+
+               SendPerfdata(prefix, cr);
+       }
+}
+
+void GraphiteWriter::SendPerfdata(const String& prefix, const CheckResult::Ptr& cr)
+{
        Value pdv = cr->GetPerformanceData();
 
        if (!pdv.IsObjectType<Dictionary>())
index 9c830f2a3861a41bb948ea27c3bf4737545b8b0a..219bc818f45bc4aaf35b87c92cb0cc5209785a4c 100644 (file)
@@ -53,6 +53,7 @@ private:
 
        void CheckResultHandler(const Service::Ptr& service, const CheckResult::Ptr& cr);
         void SendMetric(const String& prefix, const String& name, double value);
+        void SendPerfdata(const String& prefix, const CheckResult::Ptr& cr);
         static void SanitizeMetric(String& str);
 
        void ReconnectTimerHandler(void);
index ca0634f02e8ebcd6310d434342d66bcfa82987a6..68b7e29201c8ed63a4ef435076c600db52aa992e 100644 (file)
@@ -60,7 +60,8 @@ void PerfdataWriter::Start(void)
        m_RotationTimer->SetInterval(GetRotationInterval());
        m_RotationTimer->Start();
 
-       RotateFile();
+       RotateFile(m_ServiceOutputFile, GetServiceTempPath(), GetServicePerfdataPath());
+       RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
 }
 
 void PerfdataWriter::CheckResultHandler(const Service::Ptr& service, const CheckResult::Ptr& cr)
@@ -77,36 +78,52 @@ void PerfdataWriter::CheckResultHandler(const Service::Ptr& service, const Check
        resolvers.push_back(host);
        resolvers.push_back(IcingaApplication::GetInstance());
 
-       String line = MacroProcessor::ResolveMacros(GetFormatTemplate(), resolvers, cr);
+       String line = MacroProcessor::ResolveMacros(GetServiceFormatTemplate(), resolvers, cr);
 
-       ObjectLock olock(this);
-       if (!m_OutputFile.good())
-               return;
+       {
+               ObjectLock olock(this);
+               if (!m_ServiceOutputFile.good())
+                       return;
+
+               m_ServiceOutputFile << line << "\n";
+       }
 
-       m_OutputFile << line << "\n";
+       if (service == host->GetCheckService()) {
+               resolvers.clear();
+               resolvers.push_back(host);
+               resolvers.push_back(IcingaApplication::GetInstance());
+               line = MacroProcessor::ResolveMacros(GetHostFormatTemplate(), resolvers, cr);
+
+               {
+                       ObjectLock olock(this);
+                       if (!m_HostOutputFile.good())
+                               return;
+
+                       m_HostOutputFile << line << "\n";
+               }
+       }
 }
 
-void PerfdataWriter::RotateFile(void)
+void PerfdataWriter::RotateFile(std::ofstream& output, const String& temp_path, const String& perfdata_path)
 {
        ObjectLock olock(this);
 
-       String tempFile = GetTempPath();
-
-       if (m_OutputFile.good()) {
-               m_OutputFile.close();
+       if (output.good()) {
+               output.close();
 
-               String finalFile = GetPerfdataPath() + "." + Convert::ToString((long)Utility::GetTime());
-               (void) rename(tempFile.CStr(), finalFile.CStr());
+               String finalFile = perfdata_path + "." + Convert::ToString((long)Utility::GetTime());
+               (void) rename(temp_path.CStr(), finalFile.CStr());
        }
 
-       m_OutputFile.open(tempFile.CStr());
+       output.open(temp_path.CStr());
 
-       if (!m_OutputFile.good())
-               Log(LogWarning, "icinga", "Could not open perfdata file '" + tempFile + "' for writing. Perfdata will be lost.");
+       if (!output.good())
+               Log(LogWarning, "icinga", "Could not open perfdata file '" + temp_path + "' for writing. Perfdata will be lost.");
 }
 
 void PerfdataWriter::RotationTimerHandler(void)
 {
-       RotateFile();
+       RotateFile(m_ServiceOutputFile, GetServiceTempPath(), GetServicePerfdataPath());
+       RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
 }
 
index 85edd0d122c005e24d7261da96b361c33b9123f5..2def5b84da723398ebe8e869dadb65aa9aafa009 100644 (file)
@@ -51,8 +51,9 @@ private:
        Timer::Ptr m_RotationTimer;
        void RotationTimerHandler(void);
 
-       std::ofstream m_OutputFile;
-       void RotateFile(void);
+       std::ofstream m_ServiceOutputFile;
+        std::ofstream m_HostOutputFile;
+       void RotateFile(std::ofstream& output, const String& temp_path, const String& perfdata_path);
 };
 
 }
index cea802274f6d739924121d3e82f68777358ee728..4003921038d104fd92b73940b81d8b3eef189f31 100644 (file)
@@ -6,13 +6,30 @@ namespace icinga
 
 class PerfdataWriter : DynamicObject
 {
-       [config] String perfdata_path {
-               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/perfdata/perfdata"; }}}
+       [config] String host_perfdata_path {
+               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/perfdata/host-perfdata"; }}}
        };
-       [config] String temp_path {
-               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/tmp/perfdata"; }}}
+       [config] String service_perfdata_path {
+               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/perfdata/service-perfdata"; }}}
        };
-       [config] String format_template {
+       [config] String host_temp_path {
+               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/tmp/host-perfdata"; }}}
+       };
+       [config] String service_temp_path {
+               default {{{ return Application::GetLocalStateDir() + "/spool/icinga2/tmp/service-perfdata"; }}}
+       };
+       [config] String host_format_template {
+               default {{{
+                       return "DATATYPE::HOSTPERFDATA\t"
+                           "TIMET::$TIMET$\t"
+                           "HOSTNAME::$HOSTNAME$\t"
+                           "HOSTPERFDATA::$HOSTPERFDATA$\t"
+                           "HOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\t"
+                           "HOSTSTATE::$HOSTSTATE$\t"
+                           "HOSTSTATETYPE::$HOSTSTATETYPE$";
+               }}}
+       };
+       [config] String service_format_template {
                default {{{
                        return "DATATYPE::SERVICEPERFDATA\t"
                            "TIMET::$TIMET$\t"
index 68b557703303dd50ac98709f63c15a5d24a50698..0196c8cf2b04702a53a06d985e9b35b94e4882d3 100644 (file)
@@ -57,7 +57,7 @@ By default Icinga 2 uses the following files and directories:
   /usr/share/icinga2/itl              | The Icinga Template Library.
   /var/run/icinga2                    | PID file.
   /var/run/icinga2/cmd                | Command pipe and Livestatus socket.
-  /var/cache/icinga2                  | Performance data files and status.dat/objects.cache.
+  /var/cache/icinga2                  | status.dat/objects.cache.
   /var/spool/icinga2                  | Used for performance data spool files.
   /var/lib/icinga2                    | Icinga 2 state file, cluster feature replay log and configuration files.
   /var/log/icinga2                    | Log file location and compat/ directory for the CompatLogger feature.
index ac71053eb3dc37555d2b571ab5581470e23b5165..c8a8cbe5799446fd7225ea5a16a24a503013a98d 100644 (file)
@@ -13,26 +13,29 @@ inGraph and Graphite.
 
 > **Note**
 >
-> As there are no real host checks in Icinga 2, there is no performance
-> data generated for hosts.
+> As there are no real host checks in Icinga 2, the performance data is
+> generated from the host check service, if existing.
 
 ### <a id="writing-performance-data-files"></a> Writing Performance Data Files
 
-PNP4Nagios and inGraph use performance data collector daemons to fetch
+PNP4Nagios, inGraph and Graphios use performance data collector daemons to fetch
 the current performance files for their backend updates.
 
 Therefore the Icinga 2 `PerfdataWriter` object allows you to define
-the output template format backed with Icinga 2 runtime macros.
+the output template format for host and services backed with Icinga 2
+runtime macros.
 
-    format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
-    
-The default template is already provided with the Icinga 2 feature configuration
+    host_format_template = "DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$"
+    service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
+
+The default templates are already provided with the Icinga 2 feature configuration
 which can be enabled using
 
     # icinga2-enable-feature perfdata
 
 By default all performance data files are rotated in a 15 seconds interval into
-the `/var/spool/icinga2/perfdata/` directory as `service-perfdata.<timestamp>`.
+the `/var/spool/icinga2/perfdata/` directory as `host-perfdata.<timestamp>` and
+`service-perfdata.<timestamp>`.
 External collectors need to parse the rotated performance data files and then
 remove the processed files.
 
@@ -46,18 +49,19 @@ remove the processed files.
 
 ### <a id="graphite-carbon-cache-writer"></a> Graphite Carbon Cache Writer
 
-While there are some Graphite collector scripts for Icinga 1.x available it's
-more reasonable to directly process the check and plugin performance in memory
-in Icinga 2. Once there are new metrics available, Icinga 2 will directly
+While there are some Graphite collector scripts and daemons like Graphios available for
+Icinga 1.x it's more reasonable to directly process the check and plugin performance
+in memory in Icinga 2. Once there are new metrics available, Icinga 2 will directly
 write them to the defined Graphite Carbon daemon tcp socket.
 
 You can enable the feature using
 
     # icinga2-enable-feature graphite
-    
+
 The `GraphiteWriter` object expects the Graphite Carbon Cache socket listening
 at `127.0.0.1` on port `2003` by default.
 
 The current naming schema is
 
+    icinga.<hostname>.<metricname>
     icinga.<hostname>.<servicename>.<metricname>
index 9498b73aa74e6fe876334ec0e52717dae2628c66..b3306659cc686352d9250a6131c965a94d5ef8de 100644 (file)
@@ -523,26 +523,33 @@ Example:
     library "perfdata"
 
     object PerfdataWriter "pnp" {
-      perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata"
+      host_perfdata_path = "/var/spool/icinga2/perfdata/host-perfdata"
 
-      format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
+      service_perfdata_path = "/var/spool/icinga2/perfdata/service-perfdata"
+
+      host_format_template = "DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$"
+
+      service_format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$"
 
       rotation_interval = 15s
     }
 
 Attributes:
 
-  Name            |Description
-  ----------------|----------------
-  perfdata\_path  |**Optional.** Path to the service performance data file. Defaults to IcingaLocalStateDir + "/spool/icinga2/perfdata/perfdata".
-  temp\_path      |**Optional.** Path to the temporary file. Defaults to IcingaLocalStateDir + "/spool/icinga2/tmp/perfdata".
-  format\_template|**Optional.** Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
-  rotation\_interval|**Optional.** Rotation interval for the file specified in `perfdata\_path`. Defaults to 30 seconds.
+  Name                    |Description
+  ------------------------|----------------
+  host_perfdata\_path     |**Optional.** Path to the host performance data file. Defaults to IcingaLocalStateDir + "/spool/icinga2/perfdata/host-perfdata".
+  service_perfdata\_path  |**Optional.** Path to the service performance data file. Defaults to IcingaLocalStateDir + "/spool/icinga2/perfdata/service-perfdata".
+  host_temp\_path         |**Optional.** Path to the temporary host file. Defaults to IcingaLocalStateDir + "/spool/icinga2/tmp/host-perfdata".
+  service_temp\_path      |**Optional.** Path to the temporary service file. Defaults to IcingaLocalStateDir + "/spool/icinga2/tmp/service-perfdata".
+  host_format\_template   |**Optional.** Host Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
+  service_format\_template|**Optional.** Service Format template for the performance data file. Defaults to a template that's suitable for use with PNP4Nagios.
+  rotation\_interval      |**Optional.** Rotation interval for the files specified in `{host,service}\_perfdata\_path`. Defaults to 30 seconds.
 
 > **Note**
 >
 > When rotating the performance data file the current UNIX timestamp is appended to the path specified
-> in `perfdata\_path` to generate a unique filename.
+> in `host_perfdata\_path` and `service_perfdata\_path` to generate a unique filename.
 
 ### <a id="objecttype-graphitewriter"></a> GraphiteWriter
 
index f12aac8eeec1368aca6d265cf6b04888d678dd0a..8d14da876514ca5ad3a492c8ee82ad8e41740ed1 100644 (file)
@@ -330,12 +330,6 @@ where the initial state checks must have happened. Icinga 2 will use the
 `retry_interval` setting instead and `check_interval` divided by 5 if
 `retry_interval` is not defined.
 
-### <a id="differences-1x-2-performance-data"></a> Performance Data
-
-There is no host performance data generated in Icinga 2 because there are no
-real host checks. Therefore the PerfDataWriter will only write service
-performance data files.
-
 ## <a id="differences-1x-2-commands"></a> Commands
 
 Unlike in Icinga 1.x there are 3 different command types in Icinga 2:
index cf40a2a066a17b739c0be19d2878053360243dc7..486cf4229f72bf2f5a8750127984ed38137bbb83 100644 (file)
@@ -486,6 +486,15 @@ bool Host::ResolveMacro(const String& macro, const CheckResult::Ptr&, String *re
                        return true;
                } else if (macro == "HOSTPERFDATA") {
                        *result = PluginUtility::FormatPerfdata(hccr->GetPerformanceData());
+                       return true;
+               } else if (macro == "HOSTCHECKCOMMAND") {
+                       CheckCommand::Ptr commandObj = hc->GetCheckCommand();
+
+                       if (commandObj)
+                               *result = commandObj->GetName();
+                       else
+                               *result = "";
+
                        return true;
                } else if (macro == "LASTHOSTCHECK") {
                        *result = Convert::ToString((long)hccr->GetScheduleStart());