diff --git a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric.java b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric.java index 21e869bba9..226adef299 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric.java +++ b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric.java @@ -24,4 +24,5 @@ import com.google.gerrit.extensions.registration.RegistrationHandle; * @param type of the metric value, typically Integer or Long. */ public interface CallbackMetric extends RegistrationHandle { + public void prune(); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric0.java b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric0.java index 043e25fdab..35fe7a4e01 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric0.java +++ b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric0.java @@ -37,4 +37,7 @@ public abstract class CallbackMetric0 implements CallbackMetric { * @param value current value. */ public abstract void set(V value); + + @Override + public void prune() {} } diff --git a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric1.java b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric1.java index 0349db1542..0888e2107d 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric1.java +++ b/gerrit-server/src/main/java/com/google/gerrit/metrics/CallbackMetric1.java @@ -33,6 +33,7 @@ public abstract class CallbackMetric1 implements CallbackMetric { public abstract void forceCreate(F1 field1); /** Prune any submetrics that were not assigned during this trigger. */ + @Override public void prune() { } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/metrics/dropwizard/DropWizardMetricMaker.java b/gerrit-server/src/main/java/com/google/gerrit/metrics/dropwizard/DropWizardMetricMaker.java index 20320a77de..2658c24fa3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/metrics/dropwizard/DropWizardMetricMaker.java +++ b/gerrit-server/src/main/java/com/google/gerrit/metrics/dropwizard/DropWizardMetricMaker.java @@ -42,6 +42,7 @@ import com.google.gerrit.metrics.Timer2; import com.google.gerrit.metrics.Timer3; import com.google.gerrit.metrics.proc.JGitMetricModule; import com.google.gerrit.metrics.proc.ProcMetricModule; +import com.google.gerrit.server.cache.CacheMetrics; import com.google.inject.Inject; import com.google.inject.Scopes; import com.google.inject.Singleton; @@ -71,6 +72,7 @@ public class DropWizardMetricMaker extends MetricMaker { install(new ProcMetricModule()); install(new JGitMetricModule()); + bind(CacheMetrics.class); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/cache/CacheMetrics.java b/gerrit-server/src/main/java/com/google/gerrit/server/cache/CacheMetrics.java new file mode 100644 index 0000000000..a84cc0c270 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/cache/CacheMetrics.java @@ -0,0 +1,90 @@ +package com.google.gerrit.server.cache; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheStats; +import com.google.common.collect.ImmutableSet; +import com.google.gerrit.extensions.registration.DynamicMap; +import com.google.gerrit.metrics.CallbackMetric; +import com.google.gerrit.metrics.CallbackMetric1; +import com.google.gerrit.metrics.Description; +import com.google.gerrit.metrics.Field; +import com.google.gerrit.metrics.MetricMaker; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +import java.util.Set; + +@Singleton +public class CacheMetrics { + private static final Field F_NAME = Field.ofString("cache_name"); + + @Inject + public CacheMetrics(MetricMaker metrics, + final DynamicMap> cacheMap) { + final CallbackMetric1 memEnt = + metrics.newCallbackMetric("caches/memory_cached", Long.class, + new Description("Memory entries").setGauge().setUnit("entries"), + F_NAME); + final CallbackMetric1 memHit = + metrics.newCallbackMetric("caches/memory_hit_ratio", Double.class, + new Description("Memory hit ratio").setGauge().setUnit("percent"), + F_NAME); + final CallbackMetric1 memEvict = + metrics.newCallbackMetric("caches/memory_eviction_count", Long.class, + new Description("Memory eviction count").setGauge() + .setUnit("evicted entries"), + F_NAME); + final CallbackMetric1 perDiskEnt = + metrics.newCallbackMetric("caches/disk_cached", Long.class, + new Description("Disk entries used by persistent cache").setGauge() + .setUnit("entries"), + F_NAME); + final CallbackMetric1 perDiskHit = + metrics.newCallbackMetric("caches/disk_hit_ratio", Double.class, + new Description("Disk hit ratio for persistent cache").setGauge() + .setUnit("percent"), + F_NAME); + + final Set> cacheMetrics = + ImmutableSet.> of(memEnt, memHit, memEvict, + perDiskEnt, perDiskHit); + + metrics.newTrigger(cacheMetrics, new Runnable() { + @Override + public void run() { + for (DynamicMap.Entry> e : cacheMap) { + Cache c = e.getProvider().get(); + String name = metricNameOf(e); + CacheStats cstats = c.stats(); + memEnt.set(name, c.size()); + memHit.set(name, cstats.hitRate() * 100); + memEvict.set(name, cstats.evictionCount()); + if (c instanceof PersistentCache) { + PersistentCache.DiskStats d = ((PersistentCache) c).diskStats(); + perDiskEnt.set(name, d.size()); + perDiskHit.set(name, hitRatio(d)); + } + } + for (CallbackMetric cbm : cacheMetrics) { + cbm.prune(); + } + } + }); + } + + private static double hitRatio(PersistentCache.DiskStats d) { + if (d.requestCount() <= 0) { + return 100; + } + return ((double) d.hitCount() / d.requestCount() * 100); + } + + private static String metricNameOf(DynamicMap.Entry> e) { + if ("gerrit".equals(e.getPluginName())) { + return e.getExportName(); + } else { + return String.format("plugin/%s/%s", e.getPluginName(), + e.getExportName()); + } + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCaches.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCaches.java index 382c8fdfa4..653f5bd2d8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCaches.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCaches.java @@ -58,15 +58,19 @@ public class ListCaches implements RestReadView { this.cacheMap = cacheMap; } + public Map getCacheInfos() { + Map cacheInfos = new TreeMap<>(); + for (DynamicMap.Entry> e : cacheMap) { + cacheInfos.put(cacheNameOf(e.getPluginName(), e.getExportName()), + new CacheInfo(e.getProvider().get())); + } + return cacheInfos; + } + @Override public Object apply(ConfigResource rsrc) { if (format == null) { - Map cacheInfos = new TreeMap<>(); - for (DynamicMap.Entry> e : cacheMap) { - cacheInfos.put(cacheNameOf(e.getPluginName(), e.getExportName()), - new CacheInfo(e.getProvider().get())); - } - return cacheInfos; + return getCacheInfos(); } else { List cacheNames = new ArrayList<>(); for (DynamicMap.Entry> e : cacheMap) {