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 8cd6c56..217badb 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/metricsreporters/GerritPrometheusExporter.java
@@ -13,13 +13,20 @@
 // 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.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.server.config.PluginConfigFactory;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import io.prometheus.client.CollectorRegistry;
 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.Set;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -29,14 +36,38 @@
 @Singleton
 public class GerritPrometheusExporter extends MetricsServlet {
   CapabilityChecker capabilityChecker;
+  private static final String EXCLUDE_KEY = "excludeMetrics";
 
   @Inject
-  public GerritPrometheusExporter(MetricRegistry registry, CapabilityChecker capabilityChecker) {
+  public GerritPrometheusExporter(
+      MetricRegistry registry,
+      CapabilityChecker capabilityChecker,
+      PluginConfigFactory cfgFactory,
+      @PluginName String pluginName) {
     this.capabilityChecker = capabilityChecker;
 
+    /* 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 fa180cf..265a6c7 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -11,6 +11,12 @@
 It is possible to allow anonymous access to the metrics by giving the capability
 to the 'Anonymous Users' group.
 
+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
\ No newline at end of file