Move store related metrics to ChronicleMapStore

Do not emit all metrics from the chronicle-map cache implementation, but
rather split them so that the cache only emits cache-related metrics,
whilst the store emits storage-related ones.

This unlocks the possibility to centralize the emission of
store-related metrics regardless whether the store is accessed from
the ChronicleMapCacheImpl or the ChronicleMapCacheLoader.

Change-Id: Ie5e50a79f48f6e1e1ae4845b899bd9ad52e4c638
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheFactory.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheFactory.java
index 6d1f7b8..6ba86ff 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheFactory.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheFactory.java
@@ -120,7 +120,8 @@
 
     ChronicleMapCacheImpl<K, V> cache;
     try {
-      ChronicleMapStore<K, V> store = ChronicleMapCacheImpl.createOrRecoverStore(in, config);
+      ChronicleMapStore<K, V> store =
+          ChronicleMapCacheImpl.createOrRecoverStore(in, config, metricMaker);
 
       ChronicleMapCacheLoader<K, V> memLoader =
           new ChronicleMapCacheLoader<>(
@@ -184,7 +185,8 @@
     ChronicleMapCacheDefProxy<K, V> def = new ChronicleMapCacheDefProxy<>(in);
 
     try {
-      ChronicleMapStore<K, V> store = ChronicleMapCacheImpl.createOrRecoverStore(in, config);
+      ChronicleMapStore<K, V> store =
+          ChronicleMapCacheImpl.createOrRecoverStore(in, config, metricMaker);
 
       ChronicleMapCacheLoader<K, V> memLoader =
           new ChronicleMapCacheLoader<>(
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheImpl.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheImpl.java
index bdb5348..4d7a343 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheImpl.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapCacheImpl.java
@@ -52,19 +52,20 @@
 
   ChronicleMapCacheImpl(PersistentCacheDef<K, V> def, ChronicleMapCacheConfig config)
       throws IOException {
+    DisabledMetricMaker metricMaker = new DisabledMetricMaker();
 
     this.cacheDefinition = def;
     this.config = config;
     this.hotEntries =
         new InMemoryLRU<>(
             (int) Math.max(config.getMaxEntries() * config.getpercentageHotKeys() / 100, 1));
-    this.store = createOrRecoverStore(def, config);
+    this.store = createOrRecoverStore(def, config, metricMaker);
     this.memLoader =
         new ChronicleMapCacheLoader<>(
             MoreExecutors.directExecutor(), store, config.getExpireAfterWrite());
     this.mem = memLoader.asInMemoryCacheBypass();
 
-    ChronicleMapStorageMetrics metrics = new ChronicleMapStorageMetrics(new DisabledMetricMaker());
+    ChronicleMapCacheMetrics metrics = new ChronicleMapCacheMetrics(metricMaker);
     metrics.registerCallBackMetrics(def.name(), this);
   }
 
@@ -84,13 +85,14 @@
     this.mem = mem;
     this.store = memLoader.getStore();
 
-    ChronicleMapStorageMetrics metrics = new ChronicleMapStorageMetrics(metricMaker);
+    ChronicleMapCacheMetrics metrics = new ChronicleMapCacheMetrics(metricMaker);
     metrics.registerCallBackMetrics(def.name(), this);
   }
 
   @SuppressWarnings({"unchecked", "cast", "rawtypes"})
   static <K, V> ChronicleMapStore<K, V> createOrRecoverStore(
-      PersistentCacheDef<K, V> def, ChronicleMapCacheConfig config) throws IOException {
+      PersistentCacheDef<K, V> def, ChronicleMapCacheConfig config, MetricMaker metricMaker)
+      throws IOException {
     CacheSerializers.registerCacheDef(def);
 
     final Class<KeyWrapper<K>> keyWrapperClass = (Class<KeyWrapper<K>>) (Class) KeyWrapper.class;
@@ -136,46 +138,26 @@
         store.remainingAutoResizes(),
         store.percentageFreeSpace());
 
-    return new ChronicleMapStore<>(store, config);
+    return new ChronicleMapStore<>(store, config, metricMaker);
   }
 
   protected PersistentCacheDef<K, V> getCacheDefinition() {
     return cacheDefinition;
   }
 
-  private static class ChronicleMapStorageMetrics {
+  private static class ChronicleMapCacheMetrics {
 
     private final MetricMaker metricMaker;
 
-    ChronicleMapStorageMetrics(MetricMaker metricMaker) {
+    ChronicleMapCacheMetrics(MetricMaker metricMaker) {
       this.metricMaker = metricMaker;
     }
 
     <K, V> void registerCallBackMetrics(String name, ChronicleMapCacheImpl<K, V> cache) {
       String sanitizedName = metricMaker.sanitizeMetricName(name);
-      String PERCENTAGE_FREE_SPACE_METRIC =
-          "cache/chroniclemap/percentage_free_space_" + sanitizedName;
-      String REMAINING_AUTORESIZES_METRIC =
-          "cache/chroniclemap/remaining_autoresizes_" + sanitizedName;
-      String MAX_AUTORESIZES_METRIC = "cache/chroniclemap/max_autoresizes_" + sanitizedName;
       String HOT_KEYS_CAPACITY_METRIC = "cache/chroniclemap/hot_keys_capacity_" + sanitizedName;
       String HOT_KEYS_SIZE_METRIC = "cache/chroniclemap/hot_keys_size_" + sanitizedName;
 
-      metricMaker.newCallbackMetric(
-          PERCENTAGE_FREE_SPACE_METRIC,
-          Long.class,
-          new Description(
-              String.format("The amount of free space in the %s cache as a percentage", name)),
-          () -> (long) cache.store.percentageFreeSpace());
-
-      metricMaker.newCallbackMetric(
-          REMAINING_AUTORESIZES_METRIC,
-          Integer.class,
-          new Description(
-              String.format(
-                  "The number of times the %s cache can automatically expand its capacity", name)),
-          cache.store::remainingAutoResizes);
-
       metricMaker.newConstantMetric(
           HOT_KEYS_CAPACITY_METRIC,
           cache.hotEntries.getCapacity(),
@@ -190,14 +172,6 @@
               String.format(
                   "The number of hot cache keys for %s cache that are currently in memory", name)),
           cache.hotEntries::size);
-
-      metricMaker.newConstantMetric(
-          MAX_AUTORESIZES_METRIC,
-          cache.store.maxAutoResizes(),
-          new Description(
-              String.format(
-                  "The maximum number of times the %s cache can automatically expand its capacity",
-                  name)));
     }
   }
 
diff --git a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapStore.java b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapStore.java
index bc90451..5161cd0 100644
--- a/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapStore.java
+++ b/src/main/java/com/googlesource/gerrit/modules/cache/chroniclemap/ChronicleMapStore.java
@@ -15,6 +15,8 @@
 package com.googlesource.gerrit.modules.cache.chroniclemap;
 
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.metrics.Description;
+import com.google.gerrit.metrics.MetricMaker;
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Type;
@@ -40,9 +42,15 @@
   private final ChronicleMapCacheConfig config;
 
   ChronicleMapStore(
-      ChronicleMap<KeyWrapper<K>, TimedValue<V>> store, ChronicleMapCacheConfig config) {
+      ChronicleMap<KeyWrapper<K>, TimedValue<V>> store,
+      ChronicleMapCacheConfig config,
+      MetricMaker metricMaker) {
+
     this.store = store;
     this.config = config;
+
+    ChronicleMapStoreMetrics metrics = new ChronicleMapStoreMetrics(metricMaker);
+    metrics.registerCallBackMetrics(this);
   }
 
   @SuppressWarnings("rawtypes")
@@ -298,4 +306,46 @@
   public boolean isOpen() {
     return store.isOpen();
   }
+
+  private static class ChronicleMapStoreMetrics {
+
+    private final MetricMaker metricMaker;
+
+    ChronicleMapStoreMetrics(MetricMaker metricMaker) {
+      this.metricMaker = metricMaker;
+    }
+
+    <K, V> void registerCallBackMetrics(ChronicleMapStore<K, V> store) {
+      String name = store.name();
+      String sanitizedName = metricMaker.sanitizeMetricName(name);
+      String PERCENTAGE_FREE_SPACE_METRIC =
+          "cache/chroniclemap/percentage_free_space_" + sanitizedName;
+      String REMAINING_AUTORESIZES_METRIC =
+          "cache/chroniclemap/remaining_autoresizes_" + sanitizedName;
+      String MAX_AUTORESIZES_METRIC = "cache/chroniclemap/max_autoresizes_" + sanitizedName;
+
+      metricMaker.newCallbackMetric(
+          PERCENTAGE_FREE_SPACE_METRIC,
+          Long.class,
+          new Description(
+              String.format("The amount of free space in the %s cache as a percentage", name)),
+          () -> (long) store.percentageFreeSpace());
+
+      metricMaker.newCallbackMetric(
+          REMAINING_AUTORESIZES_METRIC,
+          Integer.class,
+          new Description(
+              String.format(
+                  "The number of times the %s cache can automatically expand its capacity", name)),
+          store::remainingAutoResizes);
+
+      metricMaker.newConstantMetric(
+          MAX_AUTORESIZES_METRIC,
+          store.maxAutoResizes(),
+          new Description(
+              String.format(
+                  "The maximum number of times the %s cache can automatically expand its capacity",
+                  name)));
+    }
+  }
 }