By default the `GraphiteWriter` object expects the Graphite Carbon Cache to listen at
`127.0.0.1` on TCP port `2003`.
-The current naming schema is
+#### <a id="graphite-carbon-cache-writer-schema"></a> Current Graphite Schema
+
+The current naming schema is defined as follows. The official Icinga Web 2 Graphite
+module will use that schema too.
+
+The default prefix for hosts and services is configured using
+[runtime macros](3-monitoring-basics.md#runtime-macros)like this:
+
+ icinga2.$host.name$.host.$host.check_command$
+ icinga2.$host.name$.services.$service.name$.$service.check_command$
+
+You can customize the prefix name by using the `host_name_template` and
+`service_name_template` configuration attributes.
+
+The additional levels will allow fine granular filters and also template
+capabilities, e.g. by using the check command `disk` for specific
+graph templates in web applications rendering the Graphite data.
+
+The following characters are escaped in prefix labels:
+
+ Character | Escaped character
+ --------------|--------------------------
+ whitespace | _
+ . | _
+ \ | _
+ / | _
+
+Metric values are stored like this:
+
+ <prefix>.perfdata.<perfdata-label>.value
+
+The following characters are escaped in perfdata labels:
+
+ Character | Escaped character
+ --------------|--------------------------
+ whitespace | _
+ \ | _
+ / | _
+ :: | .
+
+Note that perfdata labels may contain dots (`.`) allowing to
+add more subsequent levels inside the Graphite tree.
+`::` adds support for [multi performance labels](http://my-plugin.de/wiki/projects/check_multi/configuration/performance)
+and is therefore replaced by `.`.
+
+By enabling `enable_send_thresholds` Icinga 2 automatically adds the following threshold metrics:
+
+ <prefix>.perfdata.<perfdata-label>.min
+ <prefix>.perfdata.<perfdata-label>.max
+ <prefix>.perfdata.<perfdata-label>.warn
+ <prefix>.perfdata.<perfdata-label>.crit
+
+By enabling `enable_send_metadata` Icinga 2 automatically adds the following metadata metrics:
+
+ <prefix>.metadata.current_attempt
+ <prefix>.metadata.downtime_depth
+ <prefix>.metadata.execution_time
+ <prefix>.metadata.latency
+ <prefix>.metadata.max_check_attempts
+ <prefix>.metadata.reachable
+ <prefix>.metadata.state
+ <prefix>.metadata.state_type
+
+Metadata metric overview:
+
+ metric | description
+ -------------------|------------------------------------------
+ current_attempt | current check attempt
+ max_check_attempts | maximum check attempts until the hard state is reached
+ reachable | checked object is reachable
+ downtime_depth | number of downtimes this object is in
+ execution_time | check execution time
+ latency | check latency
+ state | current state of the checked object
+ state_type | 0=SOFT, 1=HARD state
+
+The following example illustrates how to configure the storage schemas for Graphite Carbon
+Cache.
+
+ [icinga2_default]
+ # intervals like PNP4Nagios uses them per default
+ pattern = ^icinga2\.
+ retentions = 1m:2d,5m:10d,30m:90d,360m:4y
+
+#### <a id="graphite-carbon-cache-writer-schema-legacy"></a> Graphite Schema < 2.4
+
+In order to restore the old legacy schema, you'll need to adopt the `GraphiteWriter`
+configuration:
+
+ object GraphiteWriter "graphite" {
+
+ enable_legacy_mode = true
+
+ host_name_template = "icinga.$host.name$"
+ service_name_template = "icinga.$host.name$.$service.name$"
+ }
+
+The old legacy naming schema is
icinga.<hostname>.<metricname>
icinga.<hostname>.<servicename>.<metricname>
double ts = cr->GetExecutionEnd();
- if (service) {
- prefix = MacroProcessor::ResolveMacros(GetServiceNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMacroMetric);
+ /* new mode below. old mode in else tree with 2.4, deprecate it in 2.6 */
+ if (!GetEnableLegacyMode()) {
+ if (service) {
+ prefix = MacroProcessor::ResolveMacros(GetServiceNameTemplate(), resolvers, cr, NULL, boost::bind(&GraphiteWriter::EscapeMacroMetric, _1, false));
+ } else {
+ prefix = MacroProcessor::ResolveMacros(GetHostNameTemplate(), resolvers, cr, NULL, boost::bind(&GraphiteWriter::EscapeMacroMetric, _1, false));
+ }
+
+ String prefix_perfdata = prefix + ".perfdata";
+ String prefix_metadata = prefix + ".metadata";
+
+ if (GetEnableSendMetadata()) {
+
+ if (service) {
+ SendMetric(prefix_metadata, "state", service->GetState(), ts);
+ } else {
+ SendMetric(prefix_metadata, "state", host->GetState(), ts);
+ }
+
+ SendMetric(prefix_metadata, "current_attempt", checkable->GetCheckAttempt(), ts);
+ SendMetric(prefix_metadata, "max_check_attempts", checkable->GetMaxCheckAttempts(), ts);
+ SendMetric(prefix_metadata, "state_type", checkable->GetStateType(), ts);
+ SendMetric(prefix_metadata, "reachable", checkable->IsReachable(), ts);
+ SendMetric(prefix_metadata, "downtime_depth", checkable->GetDowntimeDepth(), ts);
+ SendMetric(prefix_metadata, "latency", Service::CalculateLatency(cr), ts);
+ SendMetric(prefix_metadata, "execution_time", Service::CalculateExecutionTime(cr), ts);
+ }
- SendMetric(prefix, "state", service->GetState(), ts);
+ SendPerfdata(prefix_perfdata, cr, ts);
} else {
- prefix = MacroProcessor::ResolveMacros(GetHostNameTemplate(), resolvers, cr, NULL, &GraphiteWriter::EscapeMacroMetric);
+ if (service) {
+ prefix = MacroProcessor::ResolveMacros(GetServiceNameTemplate(), resolvers, cr, NULL, boost::bind(&GraphiteWriter::EscapeMacroMetric, _1, true));
+ SendMetric(prefix, "state", service->GetState(), ts);
+ } else {
+ prefix = MacroProcessor::ResolveMacros(GetHostNameTemplate(), resolvers, cr, NULL, boost::bind(&GraphiteWriter::EscapeMacroMetric, _1, true));
+ SendMetric(prefix, "state", host->GetState(), ts);
+ }
- SendMetric(prefix, "state", host->GetState(), ts);
+ SendMetric(prefix, "current_attempt", checkable->GetCheckAttempt(), ts);
+ SendMetric(prefix, "max_check_attempts", checkable->GetMaxCheckAttempts(), ts);
+ SendMetric(prefix, "state_type", checkable->GetStateType(), ts);
+ SendMetric(prefix, "reachable", checkable->IsReachable(), ts);
+ SendMetric(prefix, "downtime_depth", checkable->GetDowntimeDepth(), ts);
+ SendMetric(prefix, "latency", Service::CalculateLatency(cr), ts);
+ SendMetric(prefix, "execution_time", Service::CalculateExecutionTime(cr), ts);
+ SendPerfdata(prefix, cr, ts);
}
-
- SendMetric(prefix, "current_attempt", checkable->GetCheckAttempt(), ts);
- SendMetric(prefix, "max_check_attempts", checkable->GetMaxCheckAttempts(), ts);
- SendMetric(prefix, "state_type", checkable->GetStateType(), ts);
- SendMetric(prefix, "reachable", checkable->IsReachable(), ts);
- SendMetric(prefix, "downtime_depth", checkable->GetDowntimeDepth(), ts);
- SendMetric(prefix, "latency", Service::CalculateLatency(cr), ts);
- SendMetric(prefix, "execution_time", Service::CalculateExecutionTime(cr), ts);
- SendPerfdata(prefix, cr, ts);
}
void GraphiteWriter::SendPerfdata(const String& prefix, const CheckResult::Ptr& cr, double ts)
}
}
- String escaped_key = EscapeMetric(pdv->GetLabel());
- boost::algorithm::replace_all(escaped_key, "::", ".");
-
- SendMetric(prefix, escaped_key, pdv->GetValue(), ts);
-
- if (pdv->GetCrit())
- SendMetric(prefix, escaped_key + "_crit", pdv->GetCrit(), ts);
- if (pdv->GetWarn())
- SendMetric(prefix, escaped_key + "_warn", pdv->GetWarn(), ts);
- if (pdv->GetMin())
- SendMetric(prefix, escaped_key + "_min", pdv->GetMin(), ts);
- if (pdv->GetMax())
- SendMetric(prefix, escaped_key + "_max", pdv->GetMax(), ts);
+ /* new mode below. old mode in else tree with 2.4, deprecate it in 2.6 */
+ if (!GetEnableLegacyMode()) {
+ String escaped_key = EscapeMetricLabel(pdv->GetLabel());
+
+ SendMetric(prefix, escaped_key + ".value", pdv->GetValue(), ts);
+
+ if (GetEnableSendThresholds()) {
+ if (pdv->GetCrit())
+ SendMetric(prefix, escaped_key + ".crit", pdv->GetCrit(), ts);
+ if (pdv->GetWarn())
+ SendMetric(prefix, escaped_key + ".warn", pdv->GetWarn(), ts);
+ if (pdv->GetMin())
+ SendMetric(prefix, escaped_key + ".min", pdv->GetMin(), ts);
+ if (pdv->GetMax())
+ SendMetric(prefix, escaped_key + ".max", pdv->GetMax(), ts);
+ }
+ } else {
+ String escaped_key = EscapeMetric(pdv->GetLabel());
+ boost::algorithm::replace_all(escaped_key, "::", ".");
+ SendMetric(prefix, escaped_key, pdv->GetValue(), ts);
+
+ if (pdv->GetCrit())
+ SendMetric(prefix, escaped_key + "_crit", pdv->GetCrit(), ts);
+ if (pdv->GetWarn())
+ SendMetric(prefix, escaped_key + "_warn", pdv->GetWarn(), ts);
+ if (pdv->GetMin())
+ SendMetric(prefix, escaped_key + "_min", pdv->GetMin(), ts);
+ if (pdv->GetMax())
+ SendMetric(prefix, escaped_key + "_max", pdv->GetMax(), ts);
+ }
}
}
}
}
-String GraphiteWriter::EscapeMetric(const String& str)
+String GraphiteWriter::EscapeMetric(const String& str, bool legacyMode)
{
String result = str;
+ //don't allow '.' in metric prefixes
boost::replace_all(result, " ", "_");
boost::replace_all(result, ".", "_");
- boost::replace_all(result, "-", "_");
boost::replace_all(result, "\\", "_");
boost::replace_all(result, "/", "_");
+ if (legacyMode)
+ boost::replace_all(result, "-", "_");
+
+ return result;
+}
+
+String GraphiteWriter::EscapeMetricLabel(const String& str)
+{
+ String result = str;
+
+ //allow to pass '.' in perfdata labels
+ boost::replace_all(result, " ", "_");
+ boost::replace_all(result, "\\", "_");
+ boost::replace_all(result, "/", "_");
+ boost::replace_all(result, "::", ".");
+
return result;
}
-Value GraphiteWriter::EscapeMacroMetric(const Value& value)
+Value GraphiteWriter::EscapeMacroMetric(const Value& value, bool legacyMode)
{
if (value.IsObjectType<Array>()) {
Array::Ptr arr = value;
ObjectLock olock(arr);
BOOST_FOREACH(const Value& arg, arr) {
- result->Add(EscapeMetric(arg));
+ result->Add(EscapeMetric(arg, legacyMode));
}
return Utility::Join(result, '.');
} else
- return EscapeMetric(value);
+ return EscapeMetric(value, legacyMode);
}
void GraphiteWriter::ValidateHostNameTemplate(const String& value, const ValidationUtils& utils)