diff --git a/src/main/java/io/ebean/cache/ServerCache.java b/src/main/java/io/ebean/cache/ServerCache.java
index 438817f4b..82bd452b0 100644
--- a/src/main/java/io/ebean/cache/ServerCache.java
+++ b/src/main/java/io/ebean/cache/ServerCache.java
@@ -1,5 +1,7 @@
package io.ebean.cache;
+import io.ebean.meta.MetricVisitor;
+
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -79,4 +81,11 @@ public interface ServerCache {
* @param reset if true the statistics are reset.
*/
ServerCacheStatistics getStatistics(boolean reset);
+
+ /**
+ * Visit the metrics for the cache.
+ */
+ default void visit(MetricVisitor visitor) {
+ // do nothing by default
+ }
}
diff --git a/src/main/java/io/ebean/cache/ServerCacheConfig.java b/src/main/java/io/ebean/cache/ServerCacheConfig.java
index a2a6d5c52..f5e429299 100644
--- a/src/main/java/io/ebean/cache/ServerCacheConfig.java
+++ b/src/main/java/io/ebean/cache/ServerCacheConfig.java
@@ -9,13 +9,15 @@ public class ServerCacheConfig {
private final ServerCacheType type;
private final String cacheKey;
+ private final String shortName;
private final ServerCacheOptions cacheOptions;
private final CurrentTenantProvider tenantProvider;
private final QueryCacheEntryValidate queryCacheEntryValidate;
- public ServerCacheConfig(ServerCacheType type, String cacheKey, ServerCacheOptions cacheOptions, CurrentTenantProvider tenantProvider, QueryCacheEntryValidate queryCacheEntryValidate) {
+ public ServerCacheConfig(ServerCacheType type, String cacheKey, String shortName, ServerCacheOptions cacheOptions, CurrentTenantProvider tenantProvider, QueryCacheEntryValidate queryCacheEntryValidate) {
this.type = type;
this.cacheKey = cacheKey;
+ this.shortName = shortName;
this.cacheOptions = cacheOptions;
this.tenantProvider = tenantProvider;
this.queryCacheEntryValidate = queryCacheEntryValidate;
@@ -35,6 +37,13 @@ public class ServerCacheConfig {
return cacheKey;
}
+ /**
+ * Return the short name for the cache.
+ */
+ public String getShortName() {
+ return shortName;
+ }
+
/**
* Return the tuning options.
*/
diff --git a/src/main/java/io/ebean/cache/ServerCacheManager.java b/src/main/java/io/ebean/cache/ServerCacheManager.java
index a81fe9a52..5cc1a6040 100644
--- a/src/main/java/io/ebean/cache/ServerCacheManager.java
+++ b/src/main/java/io/ebean/cache/ServerCacheManager.java
@@ -1,5 +1,7 @@
package io.ebean.cache;
+import io.ebean.meta.MetricVisitor;
+
import java.util.List;
/**
@@ -7,6 +9,11 @@ import java.util.List;
*/
public interface ServerCacheManager {
+ /**
+ * Visit the metrics for all the server caches.
+ */
+ void visitMetrics(MetricVisitor visitor);
+
/**
* Return true if the L2 caching is local.
*
diff --git a/src/main/java/io/ebean/cache/ServerCacheStatistics.java b/src/main/java/io/ebean/cache/ServerCacheStatistics.java
index bbe4de7c4..20e7d8e49 100644
--- a/src/main/java/io/ebean/cache/ServerCacheStatistics.java
+++ b/src/main/java/io/ebean/cache/ServerCacheStatistics.java
@@ -21,23 +21,13 @@ public class ServerCacheStatistics {
protected long missCount;
- protected long insertCount;
-
- protected long updateCount;
+ protected long putCount;
protected long removeCount;
protected long clearCount;
- protected long evictionRunCount;
-
- protected long evictionRunMicros;
-
- protected long evictByIdle;
-
- protected long evictByTTL;
-
- protected long evictByLRU;
+ protected long evictCount;
@Override
public String toString() {
@@ -49,15 +39,10 @@ public class ServerCacheStatistics {
sb.append(" hitRatio:").append(getHitRatio());
sb.append(" hit:").append(hitCount);
sb.append(" miss:").append(missCount);
- sb.append(" insert:").append(insertCount);
- sb.append(" update:").append(updateCount);
+ sb.append(" put:").append(putCount);
sb.append(" remove:").append(removeCount);
sb.append(" clear:").append(clearCount);
- sb.append(" evictByIdle:").append(evictByIdle);
- sb.append(" evictByTTL:").append(evictByTTL);
- sb.append(" evictByLRU:").append(evictByLRU);
- sb.append(" evictionRunCount:").append(evictionRunCount);
- sb.append(" evictionRunMicros:").append(evictionRunMicros);
+ sb.append(" evict:").append(evictCount);
return sb.toString();
}
@@ -153,29 +138,15 @@ public class ServerCacheStatistics {
/**
* Set the put insert count.
*/
- public void setInsertCount(long insertCount) {
- this.insertCount = insertCount;
+ public void setPutCount(long putCount) {
+ this.putCount = putCount;
}
/**
* Return the put insert count.
*/
- public long getInsertCount() {
- return insertCount;
- }
-
- /**
- * Set the put update count.
- */
- public void setUpdateCount(long updateCount) {
- this.updateCount = updateCount;
- }
-
- /**
- * Return the put update count.
- */
- public long getUpdateCount() {
- return updateCount;
+ public long getPutCount() {
+ return putCount;
}
/**
@@ -206,73 +177,18 @@ public class ServerCacheStatistics {
return clearCount;
}
- /**
- * Set the eviction run count.
- */
- public void setEvictionRunCount(long evictCount) {
- this.evictionRunCount = evictCount;
- }
-
- /**
- * Return the eviction run count.
- */
- public long getEvictionRunCount() {
- return evictionRunCount;
- }
-
- /**
- * Set the eviction run time in micros.
- */
- public void setEvictionRunMicros(long evictionRunMicros) {
- this.evictionRunMicros = evictionRunMicros;
- }
-
- /**
- * Return the eviction run time in micros.
- */
- public long getEvictionRunMicros() {
- return evictionRunMicros;
- }
-
/**
* Set the count of entries evicted due to idle time.
*/
- public void setEvictByIdle(long evictByIdle) {
- this.evictByIdle = evictByIdle;
+ public void setEvictCount(long evictCount) {
+ this.evictCount = evictCount;
}
/**
* Return the count of entries evicted due to idle time.
*/
- public long getEvictByIdle() {
- return evictByIdle;
+ public long getEvictCount() {
+ return evictCount;
}
- /**
- * Set the count of entries evicted due to time to live.
- */
- public void setEvictByTTL(long evictByTTL) {
- this.evictByTTL = evictByTTL;
- }
-
- /**
- * Return the count of entries evicted due to time to live.
- */
- public long getEvictByTTL() {
- return evictByTTL;
- }
-
- /**
- * Set the count of entries evicted due to time least recently used.
- */
- public void setEvictByLRU(long evictByLRU) {
- this.evictByLRU = evictByLRU;
- }
-
- /**
- * Return the count of entries evicted due to time least recently used.
- */
- public long getEvictByLRU() {
- return evictByLRU;
- }
}
diff --git a/src/main/java/io/ebean/meta/AbstractMetricVisitor.java b/src/main/java/io/ebean/meta/AbstractMetricVisitor.java
index c2eb25b99..323b572ec 100644
--- a/src/main/java/io/ebean/meta/AbstractMetricVisitor.java
+++ b/src/main/java/io/ebean/meta/AbstractMetricVisitor.java
@@ -8,11 +8,13 @@ public abstract class AbstractMetricVisitor implements MetricVisitor {
private final boolean reset;
private final boolean collectTransactionMetrics;
private final boolean collectQueryMetrics;
+ private final boolean collectL2Metrics;
- public AbstractMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics) {
+ public AbstractMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
this.reset = reset;
this.collectTransactionMetrics = collectTransactionMetrics;
this.collectQueryMetrics = collectQueryMetrics;
+ this.collectL2Metrics = collectL2Metrics;
}
@Override
@@ -30,6 +32,11 @@ public abstract class AbstractMetricVisitor implements MetricVisitor {
return collectQueryMetrics;
}
+ @Override
+ public boolean isCollectL2Metrics() {
+ return collectL2Metrics;
+ }
+
@Override
public void visitStart() {
// do nothing by default
diff --git a/src/main/java/io/ebean/meta/BasicMetricVisitor.java b/src/main/java/io/ebean/meta/BasicMetricVisitor.java
index bc1658a02..7e1d77909 100644
--- a/src/main/java/io/ebean/meta/BasicMetricVisitor.java
+++ b/src/main/java/io/ebean/meta/BasicMetricVisitor.java
@@ -11,19 +11,20 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
private final List timed = new ArrayList<>();
private final List dtoQuery = new ArrayList<>();
private final List ormQuery = new ArrayList<>();
+ private final List countMetrics = new ArrayList<>();
/**
* Construct to reset and collect everything.
*/
public BasicMetricVisitor() {
- super(true, true, true);
+ super(true, true, true, true);
}
/**
* Construct specifying reset and what to collect.
*/
- public BasicMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics) {
- super(reset, collectTransactionMetrics, collectQueryMetrics);
+ public BasicMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
+ super(reset, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
}
/**
@@ -50,6 +51,11 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
return ormQuery;
}
+ @Override
+ public List getCountMetrics() {
+ return countMetrics;
+ }
+
@Override
public void visitTimed(MetaTimedMetric metric) {
timed.add(metric);
@@ -64,4 +70,9 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
public void visitOrmQuery(MetaOrmQueryMetric metric) {
ormQuery.add(metric);
}
+
+ @Override
+ public void visitCount(MetaCountMetric metric) {
+ countMetrics.add(metric);
+ }
}
diff --git a/src/main/java/io/ebean/meta/MetaCountMetric.java b/src/main/java/io/ebean/meta/MetaCountMetric.java
new file mode 100644
index 000000000..ea3c833b0
--- /dev/null
+++ b/src/main/java/io/ebean/meta/MetaCountMetric.java
@@ -0,0 +1,23 @@
+package io.ebean.meta;
+
+/**
+ * Count metrics.
+ */
+public interface MetaCountMetric {
+
+ /**
+ * Return the metric type.
+ */
+ MetricType getMetricType();
+
+ /**
+ * Return the metric name.
+ */
+ String getName();
+
+ /**
+ * Return the total count.
+ */
+ long getCount();
+
+}
diff --git a/src/main/java/io/ebean/meta/MetricVisitor.java b/src/main/java/io/ebean/meta/MetricVisitor.java
index 8b39e6499..139e7b9f6 100644
--- a/src/main/java/io/ebean/meta/MetricVisitor.java
+++ b/src/main/java/io/ebean/meta/MetricVisitor.java
@@ -20,6 +20,11 @@ public interface MetricVisitor {
*/
boolean isCollectQueryMetrics();
+ /**
+ * Return true if we should visit the L2 cache metrics.
+ */
+ boolean isCollectL2Metrics();
+
/**
* Visit has started.
*/
@@ -40,6 +45,11 @@ public interface MetricVisitor {
*/
void visitOrmQuery(MetaOrmQueryMetric metric);
+ /**
+ * Visit a Counter metric.
+ */
+ void visitCount(MetaCountMetric metric);
+
/**
* Visit has completed.
*/
diff --git a/src/main/java/io/ebean/meta/ServerMetrics.java b/src/main/java/io/ebean/meta/ServerMetrics.java
index 8b556eb51..c00518715 100644
--- a/src/main/java/io/ebean/meta/ServerMetrics.java
+++ b/src/main/java/io/ebean/meta/ServerMetrics.java
@@ -21,4 +21,10 @@ public interface ServerMetrics {
* Return the ORM query metrics.
*/
List getOrmQueryMetrics();
+
+ /**
+ * Return the Counter metrics.
+ */
+ List getCountMetrics();
+
}
diff --git a/src/main/java/io/ebean/meta/SortMetric.java b/src/main/java/io/ebean/meta/SortMetric.java
index 32d4161d1..9df2c704b 100644
--- a/src/main/java/io/ebean/meta/SortMetric.java
+++ b/src/main/java/io/ebean/meta/SortMetric.java
@@ -7,12 +7,35 @@ import java.util.Comparator;
*/
public class SortMetric {
+ public static final Comparator COUNT_NAME = new CountName();
+
public static final Comparator NAME = new Name();
public static final Comparator COUNT = new Count();
public static final Comparator TOTAL = new Total();
public static final Comparator MEAN = new Mean();
public static final Comparator MAX = new Max();
+ private static int stringCompare(String name, String name2) {
+ if (name == null) {
+ return name2 == null ? 0 : -1;
+ }
+ if (name2 == null) {
+ return 1;
+ }
+ return name.compareTo(name2);
+ }
+
+ /**
+ * Sort MetaCountMetric's by name.
+ */
+ public static class CountName implements Comparator {
+
+ @Override
+ public int compare(MetaCountMetric o1, MetaCountMetric o2) {
+ return stringCompare(o1.getName(), o2.getName());
+ }
+ }
+
/**
* Sort by name.
*/
@@ -20,16 +43,7 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
- String name = o1.getName();
- String name2 = o2.getName();
- if (name == null) {
- return name2 == null ? 0 : -1;
- }
- if (name2 == null) {
- return 1;
- }
-
- int i = name.compareTo(name2);
+ int i = stringCompare(o1.getName(), o2.getName());
return i != 0 ? i : Long.compare(o1.getCount(), o2.getCount());
}
}
diff --git a/src/main/java/io/ebean/metric/CountMetric.java b/src/main/java/io/ebean/metric/CountMetric.java
new file mode 100644
index 000000000..3ce785c1e
--- /dev/null
+++ b/src/main/java/io/ebean/metric/CountMetric.java
@@ -0,0 +1,39 @@
+package io.ebean.metric;
+
+import io.ebean.meta.MetricVisitor;
+
+/**
+ * Metric for timed events like transaction execution times.
+ */
+public interface CountMetric {
+
+ /**
+ * Add to the counter.
+ */
+ void add(long micros);
+
+ /**
+ * Increment the counter by 1.
+ */
+ void increment();
+
+ /**
+ * Return the count value.
+ */
+ long get(boolean reset);
+
+ /**
+ * Return true if there are no metrics collected since the last collection.
+ */
+ boolean isEmpty();
+
+ /**
+ * Reset the statistics.
+ */
+ void reset();
+
+ /**
+ * Visit non empty metrics.
+ */
+ void visit(MetricVisitor visitor);
+}
diff --git a/src/main/java/io/ebean/metric/CountMetricStats.java b/src/main/java/io/ebean/metric/CountMetricStats.java
new file mode 100644
index 000000000..82bebfd25
--- /dev/null
+++ b/src/main/java/io/ebean/metric/CountMetricStats.java
@@ -0,0 +1,6 @@
+package io.ebean.metric;
+
+import io.ebean.meta.MetaCountMetric;
+
+public interface CountMetricStats extends MetaCountMetric {
+}
diff --git a/src/main/java/io/ebean/metric/MetricFactory.java b/src/main/java/io/ebean/metric/MetricFactory.java
index 241ca461c..d7eed095a 100644
--- a/src/main/java/io/ebean/metric/MetricFactory.java
+++ b/src/main/java/io/ebean/metric/MetricFactory.java
@@ -25,6 +25,11 @@ public interface MetricFactory {
*/
TimedMetric createTimedMetric(MetricType metricType, String name);
+ /**
+ * Create a counter metric.
+ */
+ CountMetric createCountMetric(MetricType metricType, String name);
+
/**
* Create a Timed metric.
*/
diff --git a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java
index 37e89b864..bd7b0a763 100644
--- a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java
+++ b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheAdapter.java
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.cache;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheManager;
import io.ebean.cache.ServerCacheRegion;
+import io.ebean.meta.MetricVisitor;
import java.util.List;
@@ -20,6 +21,11 @@ public class DefaultCacheAdapter implements ServerCacheManager {
this.cacheManager = cacheManager;
}
+ @Override
+ public void visitMetrics(MetricVisitor visitor) {
+ cacheManager.visitMetrics(visitor);
+ }
+
@Override
public boolean isLocalL2Caching() {
return cacheManager.isLocalL2Caching();
diff --git a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheHolder.java b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheHolder.java
index 8211e32c4..67ead88b3 100644
--- a/src/main/java/io/ebeaninternal/server/cache/DefaultCacheHolder.java
+++ b/src/main/java/io/ebeaninternal/server/cache/DefaultCacheHolder.java
@@ -10,6 +10,7 @@ import io.ebean.cache.ServerCacheFactory;
import io.ebean.cache.ServerCacheOptions;
import io.ebean.cache.ServerCacheType;
import io.ebean.config.CurrentTenantProvider;
+import io.ebean.meta.MetricVisitor;
import io.ebean.util.AnnotationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,32 +47,50 @@ class DefaultCacheHolder {
this.queryCacheEntryValidate = builder.getQueryCacheEntryValidate();
}
- ServerCache getCache(Class> beanType, String cacheKey, ServerCacheType type) {
-
- return getCacheInternal(beanType, cacheKey, type);
+ void visitMetrics(MetricVisitor visitor) {
+ for (ServerCache serverCache : allCaches.values()) {
+ serverCache.visit(visitor);
+ }
}
- private String key(String cacheKey, ServerCacheType type) {
- return cacheKey + type.code();
+ ServerCache getCache(Class> beanType, ServerCacheType type) {
+ return getCacheInternal(beanType, type, null);
+ }
+
+ ServerCache getCache(Class> beanType, String collectionProperty) {
+ return getCacheInternal(beanType, ServerCacheType.COLLECTION_IDS, collectionProperty);
+ }
+
+ private String key(String beanName, ServerCacheType type) {
+ return beanName + type.code();
+ }
+
+ private String key(String beanName, String collectionProperty, ServerCacheType type) {
+ if (collectionProperty != null) {
+ return beanName + "." + collectionProperty + type.code();
+ } else {
+ return beanName + type.code();
+ }
}
/**
* Return the cache for a given bean type.
*/
- private ServerCache getCacheInternal(Class> beanType, String cacheKey, ServerCacheType type) {
+ private ServerCache getCacheInternal(Class> beanType, ServerCacheType type, String collectionProperty) {
- String fullKey = key(cacheKey, type);
- return allCaches.computeIfAbsent(fullKey, s -> createCache(beanType, type, fullKey));
+ String shortName = key(beanType.getSimpleName(), collectionProperty, type);
+ String fullKey = key(beanType.getName(), collectionProperty, type);
+ return allCaches.computeIfAbsent(fullKey, s -> createCache(beanType, type, fullKey, shortName));
}
- private ServerCache createCache(Class> beanType, ServerCacheType type, String key) {
+ private ServerCache createCache(Class> beanType, ServerCacheType type, String key, String shortName) {
ServerCacheOptions options = getCacheOptions(beanType, type);
if (type == ServerCacheType.COLLECTION_IDS) {
synchronized (this) {
collectIdCaches.computeIfAbsent(beanType.getName(), s -> new ConcurrentSkipListSet<>()).add(key);
}
}
- return cacheFactory.createCache(new ServerCacheConfig(type, key, options, tenantProvider, queryCacheEntryValidate));
+ return cacheFactory.createCache(new ServerCacheConfig(type, key, shortName, options, tenantProvider, queryCacheEntryValidate));
}
void clearAll() {
@@ -107,12 +126,10 @@ class DefaultCacheHolder {
* Return the cache options for a given bean type.
*/
ServerCacheOptions getCacheOptions(Class> beanType, ServerCacheType type) {
- switch (type) {
- case QUERY:
- return getQueryOptions(beanType);
- default:
- return getBeanOptions(beanType);
+ if (type == ServerCacheType.QUERY) {
+ return getQueryOptions(beanType);
}
+ return getBeanOptions(beanType);
}
private ServerCacheOptions getQueryOptions(Class> cls) {
diff --git a/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java b/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java
index 33e85f34b..6c08d1975 100644
--- a/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java
+++ b/src/main/java/io/ebeaninternal/server/cache/DefaultServerCache.java
@@ -4,6 +4,9 @@ import io.ebean.BackgroundExecutor;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.cache.TenantAwareKey;
+import io.ebean.meta.MetricVisitor;
+import io.ebean.metric.CountMetric;
+import io.ebean.metric.MetricFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -14,7 +17,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.LongAdder;
+
+import static io.ebean.meta.MetricType.L2;
/**
* The default cache implementation.
@@ -37,39 +41,45 @@ public class DefaultServerCache implements ServerCache {
*/
protected final Map