Merge "Add metrics for monitoring Java memory pools" into stable-3.4
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index 8931348..7a35d4d 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -50,6 +50,9 @@
 objects needing finalization.
 * `proc/jvm/gc/count`: Number of GCs.
 * `proc/jvm/gc/time`: Approximate accumulated GC elapsed time.
+* `proc/jvm/memory/pool/committed/<pool name>`: Committed amount of memory for pool.
+* `proc/jvm/memory/pool/max/<pool name>`: Maximum amount of memory for pool.
+* `proc/jvm/memory/pool/used/<pool name>`: Used amount of memory for pool.
 * `proc/jvm/thread/num_live`: Current live thread count.
 * `proc/jvm/thread/num_daemon_live`: Current live daemon threads count.
 * `proc/jvm/thread/num_peak_live`: Peak live thread count since the Java virtual machine started or peak was reset.
diff --git a/java/com/google/gerrit/metrics/proc/ProcMetricModule.java b/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
index 20ac8fa..09e40c1 100644
--- a/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
+++ b/java/com/google/gerrit/metrics/proc/ProcMetricModule.java
@@ -27,6 +27,7 @@
 import java.lang.management.GarbageCollectorMXBean;
 import java.lang.management.ManagementFactory;
 import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryPoolMXBean;
 import java.lang.management.MemoryUsage;
 import java.lang.management.OperatingSystemMXBean;
 import java.lang.management.ThreadMXBean;
@@ -41,6 +42,7 @@
     procCpuLoad(metrics);
     procJvmGc(metrics);
     procJvmMemory(metrics);
+    procJvmMemoryPool(metrics);
     procJvmThread(metrics);
   }
 
@@ -167,6 +169,50 @@
         });
   }
 
+  private void procJvmMemoryPool(MetricMaker metrics) {
+    Field<String> poolName =
+        Field.ofString("pool_name", Metadata.Builder::memoryPoolName)
+            .description("The name of the memory pool")
+            .build();
+
+    CallbackMetric1<String, Long> committed =
+        metrics.newCallbackMetric(
+            "proc/jvm/memory/pool/committed",
+            Long.class,
+            new Description("Committed pool size").setUnit(Units.BYTES),
+            poolName);
+
+    CallbackMetric1<String, Long> max =
+        metrics.newCallbackMetric(
+            "proc/jvm/memory/pool/max",
+            Long.class,
+            new Description("Max pool size").setUnit(Units.BYTES),
+            poolName);
+
+    CallbackMetric1<String, Long> used =
+        metrics.newCallbackMetric(
+            "proc/jvm/memory/pool/used",
+            Long.class,
+            new Description("Used pool size").setUnit(Units.BYTES),
+            poolName);
+
+    metrics.newTrigger(
+        committed,
+        max,
+        used,
+        () -> {
+          for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
+            if (!pool.isValid()) {
+              continue;
+            }
+            MemoryUsage u = pool.getUsage();
+            committed.set(pool.getName(), u.getCommitted());
+            max.set(pool.getName(), u.getMax());
+            used.set(pool.getName(), u.getUsed());
+          }
+        });
+  }
+
   private void procJvmGc(MetricMaker metrics) {
     Field<String> gcNameField =
         Field.ofString("gc_name", Metadata.Builder::garbageCollectorName)
diff --git a/java/com/google/gerrit/server/logging/Metadata.java b/java/com/google/gerrit/server/logging/Metadata.java
index 1a4a335..71ee01f 100644
--- a/java/com/google/gerrit/server/logging/Metadata.java
+++ b/java/com/google/gerrit/server/logging/Metadata.java
@@ -103,6 +103,9 @@
   public abstract Optional<Integer> indexVersion();
 
   /** The name of the implementation method. */
+  public abstract Optional<String> memoryPoolName();
+
+  /** The name of the implementation method. */
   public abstract Optional<String> methodName();
 
   /** One or more resources */
@@ -309,6 +312,8 @@
 
     public abstract Builder indexVersion(int indexVersion);
 
+    public abstract Builder memoryPoolName(@Nullable String memoryPoolName);
+
     public abstract Builder methodName(@Nullable String methodName);
 
     public abstract Builder multiple(boolean multiple);