Merge branch 'stable-2.13'

* stable-2.13:
  Make the hostname mandatory in the configuration
  Gracefully handle invalid port value in config
  Make the reporting rate configurable
  Shorten the "Reporting to Graphite... " info log message
  Extract config keys and defaults to constants

Change-Id: I48b6fb7a9e67d478c2c3ef34802d504b405b1d5c
diff --git a/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritGraphiteReporter.java b/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritGraphiteReporter.java
index 0c17cbb..6ac9db2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritGraphiteReporter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritGraphiteReporter.java
@@ -14,7 +14,6 @@
 package com.googlesource.gerrit.plugins.metricsreporters;
 
 import static com.codahale.metrics.MetricRegistry.name;
-import static com.google.common.base.MoreObjects.firstNonNull;
 
 import com.google.gerrit.extensions.annotations.Listen;
 import com.google.gerrit.extensions.annotations.PluginName;
@@ -43,7 +42,18 @@
   private static final Logger log =
       LoggerFactory.getLogger(GerritGraphiteReporter.class);
 
+  private static final String SECTION_GRAPHITE = "graphite";
+  private static final String KEY_HOST = "host";
+  private static final String KEY_PORT = "port";
+  private static final String KEY_PREFIX = "prefix";
+  private static final String KEY_RATE = "rate";
+  private static final int DEFAULT_PORT = 2003;
+  private static final String DEFAULT_PREFIX = "gerrit";
+  private static final TimeUnit DEFAULT_RATE_UNIT = TimeUnit.SECONDS;
+  private static final int DEFAULT_RATE = 60;
+
   private final GraphiteReporter graphiteReporter;
+  private final int rate;
 
   @Inject
   public GerritGraphiteReporter(
@@ -51,37 +61,71 @@
       @PluginName String pluginName,
       MetricRegistry registry) {
     Config config = configFactory.getGlobalPluginConfig(pluginName);
-    String host = firstNonNull(
-        config.getString("graphite", null, "host"), "localhost");
-    int port = config.getInt("graphite", "port", 2003);
-    String prefix = config.getString("graphite", null, "prefix");
-    if (prefix == null) {
-      try {
-        prefix = name("gerrit", InetAddress.getLocalHost().getHostName());
-      } catch (UnknownHostException e) {
-        log.error("Failed to get hostname", e);
-        throw new RuntimeException(e);
-      }
-    }
-    log.info(
-        String.format("Reporting to Graphite at host %s on port %d with prefix %s",
-        host, port, prefix));
+    String host = config.getString(SECTION_GRAPHITE, null, KEY_HOST);
 
-    graphiteReporter = GraphiteReporter.forRegistry(registry)
-        .convertRatesTo(TimeUnit.MINUTES)
-        .convertDurationsTo(TimeUnit.MILLISECONDS)
-        .prefixedWith(prefix)
-        .filter(MetricFilter.ALL)
-        .build(new Graphite(new InetSocketAddress(host, port)));
+    if (host != null) {
+      int port;
+      try {
+        port = config.getInt(SECTION_GRAPHITE, KEY_PORT, DEFAULT_PORT);
+      } catch (IllegalArgumentException e) {
+        log.warn(String.format("Invalid port value; default to %d", DEFAULT_PORT));
+        port = DEFAULT_PORT;
+      }
+      String prefix = config.getString(SECTION_GRAPHITE, null, KEY_PREFIX);
+      if (prefix == null) {
+        try {
+          prefix = name(DEFAULT_PREFIX, InetAddress.getLocalHost().getHostName());
+        } catch (UnknownHostException e) {
+          log.error("Failed to get hostname", e);
+          throw new RuntimeException(e);
+        }
+      }
+
+      long configRate;
+      try {
+        configRate = config.getTimeUnit(
+            SECTION_GRAPHITE, null, KEY_RATE, DEFAULT_RATE, DEFAULT_RATE_UNIT);
+      } catch (IllegalArgumentException e) {
+        log.warn(String.format(
+            "Invalid rate value; default to %ds", DEFAULT_RATE));
+        configRate = DEFAULT_RATE;
+      }
+      if (configRate > 0) {
+        rate = (int) configRate;
+      } else {
+        log.warn(String.format(
+            "Rate value must be positive; default to %ds", DEFAULT_RATE));
+        rate = DEFAULT_RATE;
+      }
+
+      log.info(String.format(
+          "Reporting to Graphite at %s:%d with prefix %s at rate %ds",
+          host, port, prefix, rate));
+
+      graphiteReporter = GraphiteReporter.forRegistry(registry)
+          .convertRatesTo(TimeUnit.MINUTES)
+          .convertDurationsTo(TimeUnit.MILLISECONDS)
+          .prefixedWith(prefix)
+          .filter(MetricFilter.ALL)
+          .build(new Graphite(new InetSocketAddress(host, port)));
+    } else {
+      log.warn("No hostname configured; not reporting to Graphite");
+      graphiteReporter = null;
+      rate = 0;
+    }
   }
 
   @Override
   public void start() {
-    graphiteReporter.start(1, TimeUnit.MINUTES);
+    if (graphiteReporter != null) {
+      graphiteReporter.start(rate, DEFAULT_RATE_UNIT);
+    }
   }
 
   @Override
   public void stop() {
-    graphiteReporter.stop();
+    if (graphiteReporter != null) {
+      graphiteReporter.stop();
+    }
   }
 }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index cbe5f14..b1f8e71 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -8,7 +8,8 @@
 config file that controls the settings for the @PLUGIN@ plugin.
 
 graphite.host
-:	Hostname of the Graphite server. Defaults to `localhost`.
+:	Hostname of the Graphite server. Mandatory. If not specified,
+	the plugin does not report to any Graphite instance.
 
 graphite.port
 :	Port number of the Graphite server. Defaults to `2003`.
@@ -16,3 +17,9 @@
 graphite.prefix
 :	Prefix to use when reporting metrics. Defaults to `gerrit.`
 	suffixed with the hostname of `localhost`.
+
+graphite.rate
+:	Reporting rate in seconds. May be specified in common time
+	units such as 'm', 's', 'ms', etc, but will be converted
+	to seconds. The lowest supported rate is `1 s`.
+	Defaults to `60 s`.