Allow to report JVM metrics to Cloudwatch

Allow to configure the reporter to include JVM statistics in the
metric registry so that they can be reported to cloudwatch.

Feature: Issue 13149
Change-Id: I8037a7e07854d7beed44784c53d5b7d4dd2a5c74
diff --git a/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporter.java b/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporter.java
index 91b7f63..56b6769 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporter.java
@@ -49,6 +49,10 @@
       cloudWatchReporterBuilder = cloudWatchReporterBuilder.withDryRun();
     }
 
+    if (config.getJvmMetrics()) {
+      cloudWatchReporterBuilder = cloudWatchReporterBuilder.withJvmMetrics();
+    }
+
     cloudWatchReporter = cloudWatchReporterBuilder.build();
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfig.java b/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfig.java
index b5960f7..951f526 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfig.java
@@ -33,10 +33,12 @@
   protected static final String KEY_DRYRUN = "dryRun";
   protected static final String KEY_INITIAL_DELAY = "initialDelay";
   protected static final String KEY_EXCLUDE_METRICS = "excludeMetrics";
+  protected static final String KEY_JVM_METRICS = "jvmMetrics";
 
   protected static final String DEFAULT_NAMESPACE = "gerrit";
   protected static final String DEFAULT_EMPTY_STRING = "";
   protected static final Boolean DEFAULT_DRY_RUN = false;
+  protected static final Boolean DEFAULT_JVM_METRICS = false;
   protected static final Long DEFAULT_RATE_SECS = 60L;
   protected static final Integer DEFAULT_INITIAL_DELAY_SECS = 0;
 
@@ -45,6 +47,7 @@
   private final int initialDelay;
   private final Boolean dryRun;
   private final MetricFilter exclusionFilter;
+  private final Boolean jvmMetrics;
 
   @Inject
   public GerritCloudwatchReporterConfig(
@@ -55,6 +58,8 @@
 
     this.dryRun = pluginConfig.getBoolean(KEY_DRYRUN, DEFAULT_DRY_RUN);
 
+    this.jvmMetrics = pluginConfig.getBoolean(KEY_JVM_METRICS, DEFAULT_JVM_METRICS);
+
     this.rate =
         (int)
             ConfigUtil.getTimeUnit(
@@ -92,6 +97,10 @@
     return exclusionFilter;
   }
 
+  public boolean getJvmMetrics() {
+    return jvmMetrics;
+  }
+
   private MetricFilter buildExclusionFilter(String[] exclusionList) {
     final List<Pattern> excludedMetricPatterns =
         Arrays.stream(exclusionList).map(Pattern::compile).collect(toList());
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 2d6da8c..cb645c5 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -52,6 +52,21 @@
     * Default: "0"
     * Example: 60 seconds
 
+* `plugin.@PLUGIN@.jvmMetrics` (Optional): Add JVM metrics to the registry
+
+   * Type: Boolean
+   * Default: false
+   * Example: true
+
+  Supported metrics include:
+
+  _jvm.uptime.*_, _jvm.current_time.*_, _jvm.classes.*_, _jvm.fd_usage.*_, _jvm.buffers.*_,
+  _jvm.gc.*_, _jvm.memory.*_, _jvm.thread-states.*_
+
+  Refer to the [codahale-aggregated-metrics-cloudwatch-reporter](https://github.com/azagniotov/codahale-aggregated-metrics-cloudwatch-reporter/)
+documentation for more information on this.
+
+
 * `plugin.@PLUGIN@.excludeMetrics` (Optional): Regex pattern used to exclude
 metrics from the report. It can be specified multiple times.
 Note that pattern matching is done on the whole metric name, not only on a part of it.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfigTest.java b/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfigTest.java
index dbaf40d..30c769e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfigTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/GerritCloudwatchReporterConfigTest.java
@@ -51,6 +51,8 @@
         .isEqualTo(GerritCloudwatchReporterConfig.DEFAULT_RATE_SECS);
     assertThat(reporterConfig.getDryRun())
         .isEqualTo(GerritCloudwatchReporterConfig.DEFAULT_DRY_RUN);
+    assertThat(reporterConfig.getJvmMetrics())
+        .isEqualTo(GerritCloudwatchReporterConfig.DEFAULT_JVM_METRICS);
   }
 
   @Test
@@ -60,6 +62,7 @@
     globalPluginConfig.setString(GerritCloudwatchReporterConfig.KEY_RATE, "3m");
     globalPluginConfig.setString(GerritCloudwatchReporterConfig.KEY_INITIAL_DELAY, "20s");
     globalPluginConfig.setBoolean(GerritCloudwatchReporterConfig.KEY_DRYRUN, true);
+    globalPluginConfig.setBoolean(GerritCloudwatchReporterConfig.KEY_JVM_METRICS, true);
 
     when(configFactory.getFromGerritConfig(PLUGIN_NAME)).thenReturn(globalPluginConfig);
     reporterConfig = new GerritCloudwatchReporterConfig(configFactory, PLUGIN_NAME);
@@ -68,6 +71,7 @@
     assertThat(reporterConfig.getNamespace()).isEqualTo("foobar");
     assertThat(reporterConfig.getRate()).isEqualTo(180);
     assertThat(reporterConfig.getDryRun()).isTrue();
+    assertThat(reporterConfig.getJvmMetrics()).isTrue();
   }
 
   @Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/MetricsReporterCloudwatchIT.java b/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/MetricsReporterCloudwatchIT.java
index 463d05f..43b448f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/MetricsReporterCloudwatchIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/metricsreportercloudwatch/MetricsReporterCloudwatchIT.java
@@ -46,6 +46,7 @@
 public class MetricsReporterCloudwatchIT extends LightweightPluginDaemonTest {
   private static final String TEST_METRIC_NAME = "test/metric/name";
   private static final long TEST_METRIC_INCREMENT = 1234567L;
+  private static final String TEST_JVM_METRIC_NAME = "jvm.uptime";
   private static final String TEST_TIMEOUT = "10";
   private static final Duration TEST_TIMEOUT_DURATION =
       Duration.ofSeconds(Integer.valueOf(TEST_TIMEOUT));
@@ -106,6 +107,36 @@
         });
   }
 
+  @GerritConfig(name = "plugin.metrics-reporter-cloudwatch.dryrun", value = "true")
+  @GerritConfig(name = "plugin.metrics-reporter-cloudwatch.jvmMetrics", value = "true")
+  @GerritConfig(name = "plugin.metrics-reporter-cloudwatch.rate", value = TEST_TIMEOUT)
+  public void shouldReportJVMMetricsToCloudwatch() throws Exception {
+    InMemoryLoggerAppender dryRunMetricsOutput = newInMemoryLogger();
+
+    waitUntil(
+        () ->
+            dryRunMetricsOutput
+                .metricsStream()
+                .anyMatch(l -> l.contains("MetricName=" + TEST_JVM_METRIC_NAME)));
+  }
+
+  @Test
+  @GerritConfig(name = "plugin.metrics-reporter-cloudwatch.dryrun", value = "true")
+  @GerritConfig(name = "plugin.metrics-reporter-cloudwatch.rate", value = TEST_TIMEOUT)
+  public void shouldNotReportJVMMetricsToCloudwatchByDefault() throws Exception {
+    InMemoryLoggerAppender dryRunMetricsOutput = newInMemoryLogger();
+
+    assertThrows(
+        InterruptedException.class,
+        () -> {
+          waitUntil(
+              () ->
+                  dryRunMetricsOutput
+                      .metricsStream()
+                      .anyMatch(l -> l.contains("MetricName=" + TEST_JVM_METRIC_NAME)));
+        });
+  }
+
   private static InMemoryLoggerAppender newInMemoryLogger() {
     InMemoryLoggerAppender dryRunMetricsOutput = new InMemoryLoggerAppender();
     for (Enumeration<?> logger = LogManager.getCurrentLoggers(); logger.hasMoreElements(); ) {