Add option to exclude metrics

The disk metrics of persistent caches were taking a long time to collect
(> 1 minute in some cases). This could block several threads, when trying
to scrape the metrics.

This change ports the commit a7d491a94ae5675b3582aa2f5636d72ae4969c8b of
the metrics-reporter-jmx plugin to this plugin. This change allows to
configure which metrics to exclude from reporting using regular expressions.
This allows to exclude problematic or unwanted metrics, thereby allowing to
avoid the issue described above.

Change-Id: I1f144bad3aa68d217fa3cd637a5f1445f5b79623
diff --git a/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java b/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java
index a43a779..7387838 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java
@@ -13,6 +13,8 @@
 // limitations under the License.
 package com.googlesource.gerrit.plugins.metricsreporters;
 
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricFilter;
 import com.codahale.metrics.MetricRegistry;
 import com.google.common.base.Strings;
 import com.google.common.net.HttpHeaders;
@@ -24,7 +26,10 @@
 import io.prometheus.client.dropwizard.DropwizardExports;
 import io.prometheus.client.exporter.MetricsServlet;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.Optional;
+import java.util.Set;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -35,6 +40,7 @@
 @Singleton
 public class GerritPrometheusExporter extends MetricsServlet {
   private static final String PROMETHEUS_BEARER_TOKEN = "prometheusBearerToken";
+  private static final String EXCLUDE_KEY = "excludeMetrics";
 
   private final CapabilityChecker capabilityChecker;
   private final String prometheusBearerToken;
@@ -49,9 +55,28 @@
     this.prometheusBearerToken =
         cfgFactory.getFromGerritConfig(pluginName).getString(PROMETHEUS_BEARER_TOKEN);
 
+    /* Copy the registry to avoid filtering the global one */
+    MetricRegistry filteredRegistry = new MetricRegistry();
+    filteredRegistry.registerAll(registry);
+
+    Set<String> excludedMetrics = new HashSet<>();
+    excludedMetrics.addAll(
+        Arrays.asList(cfgFactory.getFromGerritConfig(pluginName).getStringList(EXCLUDE_KEY)));
+
+    excludedMetrics.forEach(
+        exclude -> {
+          filteredRegistry.removeMatching(
+              new MetricFilter() {
+                @Override
+                public boolean matches(String name, Metric metric) {
+                  return name.matches(exclude);
+                }
+              });
+        });
+
     // Hook the Dropwizard registry into the Prometheus registry
     // via the DropwizardExports collector.
-    CollectorRegistry.defaultRegistry.register(new DropwizardExports(registry));
+    CollectorRegistry.defaultRegistry.register(new DropwizardExports(filteredRegistry));
   }
 
   @Override
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index c8edf5c..f45f16f 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -24,6 +24,12 @@
 See [Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration)
 for how to configure the integration with Prometheus.
 
+plugin.@PLUGIN@.excludeMetrics
+:   String used to exclude metrics from the report. It can be specified multiple times.
+    Parsed as regular expression. Note, ^ and $ are automatically added around the string.
+    By default no metric is excluded.
+    For example, to exclude all cache metrics, use: `excludeMetrics = cache.*`
+
 [Back to @PLUGIN@ documentation index][index]
 
 [index]: index.html