#1685 - Add support for MetaCounterMetrics and refactor DefaultServerCache to use them

This commit is contained in:
rob bygrave
2019-04-27 00:34:45 +12:00
parent d3ead5d2f9
commit 25e6d05542
31 changed files with 449 additions and 235 deletions
+9
View File
@@ -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
}
}
+10 -1
View File
@@ -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.
*/
+7
View File
@@ -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.
* <p>
+12 -96
View File
@@ -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;
}
}
@@ -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
@@ -11,19 +11,20 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
private final List<MetaTimedMetric> timed = new ArrayList<>();
private final List<MetaQueryMetric> dtoQuery = new ArrayList<>();
private final List<MetaOrmQueryMetric> ormQuery = new ArrayList<>();
private final List<MetaCountMetric> 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<MetaCountMetric> 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);
}
}
@@ -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();
}
@@ -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.
*/
@@ -21,4 +21,10 @@ public interface ServerMetrics {
* Return the ORM query metrics.
*/
List<MetaOrmQueryMetric> getOrmQueryMetrics();
/**
* Return the Counter metrics.
*/
List<MetaCountMetric> getCountMetrics();
}
+24 -10
View File
@@ -7,12 +7,35 @@ import java.util.Comparator;
*/
public class SortMetric {
public static final Comparator<MetaCountMetric> COUNT_NAME = new CountName();
public static final Comparator<MetaTimedMetric> NAME = new Name();
public static final Comparator<MetaTimedMetric> COUNT = new Count();
public static final Comparator<MetaTimedMetric> TOTAL = new Total();
public static final Comparator<MetaTimedMetric> MEAN = new Mean();
public static final Comparator<MetaTimedMetric> 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<MetaCountMetric> {
@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());
}
}
@@ -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);
}
@@ -0,0 +1,6 @@
package io.ebean.metric;
import io.ebean.meta.MetaCountMetric;
public interface CountMetricStats extends MetaCountMetric {
}
@@ -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.
*/
@@ -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();
@@ -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) {
@@ -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<Object, CacheEntry> map;
protected final LongAdder missCount = new LongAdder();
protected final LongAdder hitCount = new LongAdder();
protected final LongAdder insertCount = new LongAdder();
protected final LongAdder updateCount = new LongAdder();
protected final LongAdder removeCount = new LongAdder();
protected final LongAdder clearCount = new LongAdder();
protected final LongAdder evictByIdle = new LongAdder();
protected final LongAdder evictByTTL = new LongAdder();
protected final LongAdder evictByLRU = new LongAdder();
protected final LongAdder evictCount = new LongAdder();
protected final LongAdder evictMicros = new LongAdder();
protected final CountMetric hitCount;
protected final CountMetric missCount;
protected final CountMetric putCount;
protected final CountMetric removeCount;
protected final CountMetric clearCount;
protected final CountMetric evictCount;
protected final String name;
protected final String shortName;
protected int maxSize;
private int maxSize;
protected final int trimFrequency;
private final int trimFrequency;
protected int maxIdleSecs;
private int maxIdleSecs;
protected int maxSecsToLive;
private int maxSecsToLive;
protected TenantAwareKey tenantAwareKey;
private TenantAwareKey tenantAwareKey;
public DefaultServerCache(DefaultServerCacheConfig config) {
this.name = config.getName();
this.shortName = config.getShortName();
this.map = config.getMap();
this.maxSize = config.getMaxSize();
this.tenantAwareKey = new TenantAwareKey(config.getTenantProvider());
this.maxIdleSecs = config.getMaxIdleSecs();
this.maxSecsToLive = config.getMaxSecsToLive();
this.trimFrequency = config.determineTrimFrequency();
MetricFactory factory = MetricFactory.get();
String prefix = "l2n.";
this.hitCount = factory.createCountMetric(L2, prefix + shortName + ".hit");
this.missCount = factory.createCountMetric(L2, prefix + shortName + ".miss");
this.putCount = factory.createCountMetric(L2, prefix + shortName + ".put");
this.removeCount = factory.createCountMetric(L2, prefix + shortName + ".remove");
this.clearCount = factory.createCountMetric(L2, prefix + shortName + ".clear");
this.evictCount = factory.createCountMetric(L2, prefix + shortName + ".evict");
}
public void periodicTrim(BackgroundExecutor executor) {
@@ -81,6 +91,16 @@ public class DefaultServerCache implements ServerCache {
executor.executePeriodically(trim, trimFreqSecs, TimeUnit.SECONDS);
}
@Override
public void visit(MetricVisitor visitor) {
hitCount.visit(visitor);
missCount.visit(visitor);
putCount.visit(visitor);
removeCount.visit(visitor);
clearCount.visit(visitor);
evictCount.visit(visitor);
}
@Override
public ServerCacheStatistics getStatistics(boolean reset) {
@@ -88,38 +108,13 @@ public class DefaultServerCache implements ServerCache {
cacheStats.setCacheName(name);
cacheStats.setMaxSize(maxSize);
// these counters won't necessarily be consistent with
// respect to each other as activity can occur while
// they are being calculated here but they should be good enough
// and we don't want to reduce concurrent use to make them consistent
long clear = reset ? clearCount.sumThenReset() : clearCount.sum();
long remove = reset ? removeCount.sumThenReset() : removeCount.sum();
long update = reset ? updateCount.sumThenReset() : updateCount.sum();
long insert = reset ? insertCount.sumThenReset() : insertCount.sum();
long miss = reset ? missCount.sumThenReset() : missCount.sum();
long hit = reset ? hitCount.sumThenReset() : hitCount.sum();
long evict = reset ? evictCount.sumThenReset() : evictCount.sum();
long evictTime = reset ? evictMicros.sumThenReset() : evictMicros.sum();
long evictIdle = reset ? evictByIdle.sumThenReset() : evictByIdle.sum();
long evictTTL = reset ? evictByTTL.sumThenReset() : evictByTTL.sum();
long evictLRU = reset ? evictByLRU.sumThenReset() : evictByLRU.sum();
int size = size();
cacheStats.setSize(size);
cacheStats.setHitCount(hit);
cacheStats.setMissCount(miss);
cacheStats.setInsertCount(insert);
cacheStats.setUpdateCount(update);
cacheStats.setRemoveCount(remove);
cacheStats.setClearCount(clear);
cacheStats.setEvictionRunCount(evict);
cacheStats.setEvictionRunMicros(evictTime);
cacheStats.setEvictByIdle(evictIdle);
cacheStats.setEvictByTTL(evictTTL);
cacheStats.setEvictByLRU(evictLRU);
cacheStats.setSize(size());
cacheStats.setHitCount(hitCount.get(reset));
cacheStats.setMissCount(missCount.get(reset));
cacheStats.setPutCount(putCount.get(reset));
cacheStats.setRemoveCount(removeCount.get(reset));
cacheStats.setClearCount(clearCount.get(reset));
cacheStats.setEvictCount(evictCount.get(reset));
return cacheStats;
}
@@ -127,8 +122,8 @@ public class DefaultServerCache implements ServerCache {
@Override
public int getHitRatio() {
long mc = missCount.sum();
long hc = hitCount.sum();
long mc = missCount.get(false);
long hc = hitCount.get(false);
long totalCount = hc + mc;
if (totalCount == 0) {
@@ -145,6 +140,10 @@ public class DefaultServerCache implements ServerCache {
return name;
}
public String getShortName() {
return shortName;
}
/**
* Clear the cache.
*/
@@ -171,10 +170,7 @@ public class DefaultServerCache implements ServerCache {
if (entry == null) {
missCount.increment();
return null;
} else {
// Important that hitCount.increment() MUST be low latency under concurrent
// use hence must use LongAdder or better here
hitCount.increment();
return unwrapEntry(entry);
}
@@ -204,14 +200,9 @@ public class DefaultServerCache implements ServerCache {
*/
@Override
public void put(Object id, Object value) {
Object key = key(id);
CacheEntry entry = map.put(key, new CacheEntry(key, value));
if (entry == null) {
insertCount.increment();
} else {
updateCount.increment();
}
map.put(key, new CacheEntry(key, value));
putCount.increment();
}
/**
@@ -219,7 +210,6 @@ public class DefaultServerCache implements ServerCache {
*/
@Override
public void remove(Object id) {
CacheEntry entry = map.remove(key(id));
if (entry != null) {
removeCount.increment();
@@ -269,7 +259,7 @@ public class DefaultServerCache implements ServerCache {
List<CacheEntry> activeList = new ArrayList<>(map.size());
long idleExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxIdleSecs);
long idleExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxIdleSecs);
long ttlExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxSecsToLive);
Iterator<CacheEntry> it = map.values().iterator();
@@ -301,17 +291,12 @@ public class DefaultServerCache implements ServerCache {
}
}
long exeNanos = System.nanoTime() - startNanos;
long exeMicros = TimeUnit.MICROSECONDS.convert(exeNanos, TimeUnit.NANOSECONDS);
// increment the eviction statistics
evictMicros.add(exeMicros);
evictCount.increment();
evictByIdle.add(trimmedByIdle);
evictByTTL.add(trimmedByTTL);
evictByLRU.add(trimmedByLRU);
evictCount.add(trimmedByIdle);
evictCount.add(trimmedByTTL);
evictCount.add(trimmedByLRU);
if (logger.isTraceEnabled()) {
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}]"
, name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU);
}
@@ -46,6 +46,10 @@ public class DefaultServerCacheConfig {
return config.getCacheKey();
}
public String getShortName() {
return config.getShortName();
}
public Map<Object, DefaultServerCache.CacheEntry> getMap() {
return map;
}
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.cache;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheRegion;
import io.ebean.cache.ServerCacheType;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiCacheRegion;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.deploy.DCacheRegion;
@@ -99,6 +100,11 @@ public class DefaultServerCacheManager implements SpiCacheManager {
return regionMap.computeIfAbsent(region, DCacheRegion::new);
}
@Override
public void visitMetrics(MetricVisitor visitor) {
cacheHolder.visitMetrics(visitor);
}
/**
* Clear all caches.
*/
@@ -117,7 +123,7 @@ public class DefaultServerCacheManager implements SpiCacheManager {
@Override
public void clear(Class<?> beanType) {
cacheHolder.clear(name(beanType));
cacheHolder.clear(beanType.getName());
if (clusterManager != null) {
clusterManager.cacheClear(serverName, beanType);
}
@@ -125,17 +131,17 @@ public class DefaultServerCacheManager implements SpiCacheManager {
@Override
public void clearLocal(Class<?> beanType) {
cacheHolder.clear(name(beanType));
cacheHolder.clear(beanType.getName());
}
@Override
public ServerCache getCollectionIdsCache(Class<?> beanType, String propertyName) {
return cacheHolder.getCache(beanType, name(beanType) + "." + propertyName, ServerCacheType.COLLECTION_IDS);
public ServerCache getCollectionIdsCache(Class<?> beanType, String collectionProperty) {
return cacheHolder.getCache(beanType, collectionProperty);
}
@Override
public ServerCache getNaturalKeyCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.NATURAL_KEY);
return cacheHolder.getCache(beanType, ServerCacheType.NATURAL_KEY);
}
/**
@@ -143,7 +149,7 @@ public class DefaultServerCacheManager implements SpiCacheManager {
*/
@Override
public ServerCache getQueryCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.QUERY);
return cacheHolder.getCache(beanType, ServerCacheType.QUERY);
}
/**
@@ -151,11 +157,7 @@ public class DefaultServerCacheManager implements SpiCacheManager {
*/
@Override
public ServerCache getBeanCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.BEAN);
}
private String name(Class<?> beanType) {
return beanType.getName();
return cacheHolder.getCache(beanType, ServerCacheType.BEAN);
}
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.cache;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheRegion;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiCacheRegion;
import java.util.List;
@@ -11,6 +12,11 @@ import java.util.List;
*/
public interface SpiCacheManager {
/**
* Visit and collect the metrics.
*/
void visitMetrics(MetricVisitor visitor);
/**
* Return true if the L2 caching is local.
* <p>
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.core;
import io.ebean.meta.AbstractMetricVisitor;
import io.ebean.meta.BasicMetricVisitor;
import io.ebean.meta.MetaCountMetric;
import io.ebean.meta.MetaInfoManager;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaOrmQueryNode;
@@ -71,7 +72,7 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
private static class ResetVisitor extends AbstractMetricVisitor {
ResetVisitor() {
super(true, true, true);
super(true, true, true, true);
}
@Override
@@ -88,6 +89,11 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
public void visitOrmQuery(MetaOrmQueryMetric metric) {
// ignore
}
@Override
public void visitCount(MetaCountMetric metric) {
// ignore
}
}
}
@@ -2389,6 +2389,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
if (visitor.isCollectTransactionMetrics()) {
transactionManager.visitMetrics(visitor);
}
if (visitor.isCollectL2Metrics()) {
serverCacheManager.visitMetrics(visitor);
}
if (visitor.isCollectQueryMetrics()) {
beanDescriptorManager.visitMetrics(visitor);
dtoBeanManager.visitMetrics(visitor);
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.core;
import io.ebean.ProfileLocation;
import io.ebean.meta.MetaCountMetric;
import io.ebean.meta.MetaOrmQueryMetric;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaTimedMetric;
@@ -83,6 +84,15 @@ class DumpMetrics {
log(metric);
}
List<MetaCountMetric> countMetrics = serverMetrics.getCountMetrics();
if (!countMetrics.isEmpty()) {
out("\n-- Counters --");
countMetrics.sort(SortMetric.COUNT_NAME);
for (MetaCountMetric metric : countMetrics) {
logCount(metric);
}
}
List<MetaOrmQueryMetric> ormQueryMetrics = serverMetrics.getOrmQueryMetrics();
if (!ormQueryMetrics.isEmpty()) {
out("\n-- ORM queries --");
@@ -102,6 +112,14 @@ class DumpMetrics {
}
}
private void logCount(MetaCountMetric metric) {
StringBuilder sb = new StringBuilder();
sb.append(padNameTimed(metric.getName())).append(" ");
sb.append(" count:").append(pad(metric.getCount()));
out(sb.toString());
}
private void out(String sb) {
System.out.println(sb);
}
@@ -0,0 +1,90 @@
package io.ebeaninternal.server.profile;
import io.ebean.meta.MetricType;
import io.ebean.meta.MetricVisitor;
import io.ebean.metric.CountMetric;
import io.ebean.metric.CountMetricStats;
import java.util.concurrent.atomic.LongAdder;
/**
* Used to collect counter metrics.
*/
class DCountMetric implements CountMetric {
private final MetricType metricType;
private final String name;
private final LongAdder count = new LongAdder();
DCountMetric(MetricType metricType, String name) {
this.metricType = metricType;
this.name = name;
}
/**
* Add a value. Usually the value is Time or Bytes etc.
*/
@Override
public void add(long value) {
count.add(value);
}
public void increment() {
count.increment();
}
@Override
public boolean isEmpty() {
return count.sum() == 0;
}
@Override
public void reset() {
count.reset();
}
@Override
public long get(boolean reset) {
return reset ? count.sumThenReset() : count.sum();
}
@Override
public void visit(MetricVisitor visitor) {
long val = visitor.isReset() ? count.sumThenReset() : count.sum();
if (val > 0) {
visitor.visitCount(new DCountMetricStats(metricType, name, val));
}
}
private static class DCountMetricStats implements CountMetricStats {
private final MetricType metricType;
private final String name;
private final long count;
private DCountMetricStats(MetricType metricType, String name, long count) {
this.metricType = metricType;
this.name = name;
this.count = count;
}
@Override
public MetricType getMetricType() {
return metricType;
}
@Override
public String getName() {
return name;
}
@Override
public long getCount() {
return count;
}
}
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.profile;
import io.ebean.ProfileLocation;
import io.ebean.meta.MetricType;
import io.ebean.metric.CountMetric;
import io.ebean.metric.MetricFactory;
import io.ebean.metric.QueryPlanMetric;
import io.ebean.metric.TimedMetric;
@@ -22,6 +23,11 @@ public class DMetricFactory implements MetricFactory {
return new DTimedMetric(metricType, name);
}
@Override
public CountMetric createCountMetric(MetricType metricType, String name) {
return new DCountMetric(metricType, name);
}
@Override
public QueryPlanMetric createQueryPlanMetric(MetricType metricType, Class<?> type, String label, ProfileLocation profileLocation, String sql) {
return new DQueryPlanMetric(new DQueryPlanMeta(type, label, profileLocation, sql), new DTimedMetric(metricType, label));