Graphite/PerfdataWriter: Add host perfdata.

Fixes #5908
This commit is contained in:
Michael Friedrich 2014-04-01 20:30:44 +02:00
parent 22c9caa6ec
commit 3fe169cd7a
10 changed files with 127 additions and 57 deletions

View 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>())

View 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);

View 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_OutputFile << line << "\n";
m_ServiceOutputFile << 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 (output.good()) {
output.close();
if (m_OutputFile.good()) {
m_OutputFile.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());
}

View 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);
};
}

View 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"

View 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.

View 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>

View 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

View 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:

View 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());