]> granicus.if.org Git - icinga2/commitdiff
Implement a better Graphite tree schema
authorMichael Friedrich <michael.friedrich@netways.de>
Fri, 19 Jun 2015 16:11:55 +0000 (18:11 +0200)
committerMichael Friedrich <michael.friedrich@gmail.com>
Sun, 6 Sep 2015 09:10:49 +0000 (11:10 +0200)
This changes the entire tree, but with the prefix "icinga2"
not to conflict with existing installations. Includes
enable_legacy_mode and detailed documentation.

fixes #9461
fixes #8149

doc/5-advanced-topics.md
doc/6-object-types.md
lib/perfdata/graphitewriter.cpp
lib/perfdata/graphitewriter.hpp
lib/perfdata/graphitewriter.ti

index 36c36d7277cdf9c865aa230253c5b65bce2e1a6c..0ad250128a972a31ee4815e47e15c1e7e2bf058b 100644 (file)
@@ -612,7 +612,104 @@ You can enable the feature using
 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>
index 3a6d634b0ece2af504a4a8b8c05989560f5ed4f7..cbf1c87e94001443b62b60adf1a0fc3e4d1bc523 100644 (file)
@@ -446,17 +446,13 @@ Configuration Attributes:
   ----------------------|----------------------
   host                 |**Optional.** Graphite Carbon host address. Defaults to '127.0.0.1'.
   port                 |**Optional.** Graphite Carbon port. Defaults to 2003.
-  host_name_template   |**Optional.** Metric prefix for host name. Defaults to "icinga.$host.name$".
-  service_name_template |**Optional.** Metric prefix for service name. Defaults to "icinga.$host.name$.$service.name$".
+  host_name_template   |**Optional.** Metric prefix for host name. Defaults to "icinga2.$host.name$.host.$host.check_command$".
+  service_name_template |**Optional.** Metric prefix for service name. Defaults to "icinga2.$host.name$.services.$service.name$.$service.check_command$".
+  enable_send_thresholds | **Optional.** Send additional threshold metrics. Defaults to `false`.
+  enable_send_metadata         | **Optional.** Send additional metadata metrics. Defaults to `false`.
+  enable_legacy_mode   | **Optional.** Enable legacy mode for schema < 2.4. **Note**: This will be removed in future versions.
 
-Metric prefix names can be modified using [runtime macros](3-monitoring-basics.md#runtime-macros).
-
-Example with your custom [global constant](20-language-reference.md#constants) `GraphiteEnv`:
-
-    const GraphiteEnv = "icinga.env1"
-
-    host_name_template = GraphiteEnv + ".$host.name$"
-    service_name_template = GraphiteEnv + ".$host.name$.$service.name$"
+Additional usage examples can be found [here](5-advanced-topics.md#graphite-carbon-cache-writer).
 
 
 
index dd36104e733579fcaa0acf9118db2504856d46a8..4bd3291cd6d1ff53d1666bf85c3229d7adf10291 100644 (file)
@@ -117,24 +117,53 @@ void GraphiteWriter::CheckResultHandler(const Checkable::Ptr& checkable, const C
 
        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)
@@ -160,19 +189,36 @@ void GraphiteWriter::SendPerfdata(const String& prefix, const CheckResult::Ptr&
                        }
                }
 
-               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);
+               }
        }
 }
 
@@ -203,20 +249,36 @@ void GraphiteWriter::SendMetric(const String& prefix, const String& name, double
        }
 }
 
-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;
@@ -224,12 +286,12 @@ Value GraphiteWriter::EscapeMacroMetric(const Value& 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)
index 2e06b01e75200e81c08fdb16ba95047d8d09fdbe..e3dd6eede42826afdad0ec966eba640c4c96d415 100644 (file)
@@ -57,8 +57,9 @@ private:
        void CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr);
        void SendMetric(const String& prefix, const String& name, double value, double ts);
        void SendPerfdata(const String& prefix, const CheckResult::Ptr& cr, double ts);
-       static String EscapeMetric(const String& str);
-       static Value EscapeMacroMetric(const Value& value);
+       static String EscapeMetric(const String& str, bool legacyMode = false);
+       static String EscapeMetricLabel(const String& str);
+       static Value EscapeMacroMetric(const Value& value, bool legacyMode = false);
 
        void ReconnectTimerHandler(void);
 };
index 3863d4f3bfbbd1112c883fe666d408d6e561f35a..5d0685a2df5180d1980130ce688ae3a9c583c486 100644 (file)
@@ -33,11 +33,21 @@ class GraphiteWriter : ConfigObject
                default {{{ return "2003"; }}}
        };
        [config] String host_name_template {
-               default {{{ return "icinga.$host.name$"; }}}
+               default {{{ return "icinga2.$host.name$.host.$host.check_command$"; }}}
        };
        [config] String service_name_template {
-               default {{{ return "icinga.$host.name$.$service.name$"; }}}
+               default {{{ return "icinga2.$host.name$.services.$service.name$.$service.check_command$"; }}}
        };
+        [config] bool enable_send_thresholds {
+                default {{{ return false; }}}
+        };
+        [config] bool enable_send_metadata {
+                default {{{ return false; }}}
+        };
+        [config] bool enable_legacy_mode {
+                default {{{ return false; }}}
+        };
+
 };
 
 }