package com.codahale.metrics.ehcache;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.EhcacheDecoratorAdapter;
import net.sf.ehcache.statistics.StatisticsGateway;
import java.io.Serializable;
import static com.codahale.metrics.MetricRegistry.name;
An instrumented Ehcache
instance. /**
* An instrumented {@link Ehcache} instance.
*/
public class InstrumentedEhcache extends EhcacheDecoratorAdapter {
Instruments the given Ehcache
instance with get and put timers and a set of gauges for Ehcache's built-in statistics:
Ehcache timered metrics
hits
The number of times a requested item was found in the
cache.
in-memory-hits
Number of times a requested item was found in the memory
store.
off-heap-hits
Number of times a requested item was found in the off-heap
store.
on-disk-hits
Number of times a requested item was found in the disk
store.
misses
Number of times a requested item was not found in the
cache.
in-memory-misses
Number of times a requested item was not found in the memory
store.
off-heap-misses
Number of times a requested item was not found in the
off-heap store.
on-disk-misses
Number of times a requested item was not found in the disk
store.
objects
Number of elements stored in the cache.
in-memory-objects
Number of objects in the memory store.
off-heap-objects
Number of objects in the off-heap store.
on-disk-objects
Number of objects in the disk store.
mean-get-time
The average get time. Because ehcache support JDK1.4.2, each get time uses System.currentTimeMillis()
, rather than nanoseconds. The accuracy is thus limited.
mean-search-time
The average execution time (in milliseconds) within the last
sample period.
eviction-count
The number of cache evictions, since the cache was created,
or statistics were cleared.
searches-per-second
The number of search executions that have completed in the
last second.
accuracy
A human readable description of the accuracy setting. One of
"None", "Best Effort" or "Guaranteed".
N.B.: This enables Ehcache's sampling statistics with an accuracy
level of "none."
Params: - cache – an
Ehcache
instance - registry – a
MetricRegistry
See Also: Returns: an instrumented decorator for cache
/**
* Instruments the given {@link Ehcache} instance with get and put timers
* and a set of gauges for Ehcache's built-in statistics:
* <p>
* <table>
* <caption>Ehcache timered metrics</caption>
* <tr>
* <td>{@code hits}</td>
* <td>The number of times a requested item was found in the
* cache.</td>
* </tr>
* <tr>
* <td>{@code in-memory-hits}</td>
* <td>Number of times a requested item was found in the memory
* store.</td>
* </tr>
* <tr>
* <td>{@code off-heap-hits}</td>
* <td>Number of times a requested item was found in the off-heap
* store.</td>
* </tr>
* <tr>
* <td>{@code on-disk-hits}</td>
* <td>Number of times a requested item was found in the disk
* store.</td>
* </tr>
* <tr>
* <td>{@code misses}</td>
* <td>Number of times a requested item was not found in the
* cache.</td>
* </tr>
* <tr>
* <td>{@code in-memory-misses}</td>
* <td>Number of times a requested item was not found in the memory
* store.</td>
* </tr>
* <tr>
* <td>{@code off-heap-misses}</td>
* <td>Number of times a requested item was not found in the
* off-heap store.</td>
* </tr>
* <tr>
* <td>{@code on-disk-misses}</td>
* <td>Number of times a requested item was not found in the disk
* store.</td>
* </tr>
* <tr>
* <td>{@code objects}</td>
* <td>Number of elements stored in the cache.</td>
* </tr>
* <tr>
* <td>{@code in-memory-objects}</td>
* <td>Number of objects in the memory store.</td>
* </tr>
* <tr>
* <td>{@code off-heap-objects}</td>
* <td>Number of objects in the off-heap store.</td>
* </tr>
* <tr>
* <td>{@code on-disk-objects}</td>
* <td>Number of objects in the disk store.</td>
* </tr>
* <tr>
* <td>{@code mean-get-time}</td>
* <td>The average get time. Because ehcache support JDK1.4.2, each
* get time uses {@link System#currentTimeMillis()}, rather than
* nanoseconds. The accuracy is thus limited.</td>
* </tr>
* <tr>
* <td>{@code mean-search-time}</td>
* <td>The average execution time (in milliseconds) within the last
* sample period.</td>
* </tr>
* <tr>
* <td>{@code eviction-count}</td>
* <td>The number of cache evictions, since the cache was created,
* or statistics were cleared.</td>
* </tr>
* <tr>
* <td>{@code searches-per-second}</td>
* <td>The number of search executions that have completed in the
* last second.</td>
* </tr>
* <tr>
* <td>{@code accuracy}</td>
* <td>A human readable description of the accuracy setting. One of
* "None", "Best Effort" or "Guaranteed".</td>
* </tr>
* </table>
* <p>
* <b>N.B.: This enables Ehcache's sampling statistics with an accuracy
* level of "none."</b>
*
* @param cache an {@link Ehcache} instance
* @param registry a {@link MetricRegistry}
* @return an instrumented decorator for {@code cache}
* @see StatisticsGateway
*/
public static Ehcache instrument(MetricRegistry registry, final Ehcache cache) {
final String prefix = name(cache.getClass(), cache.getName());
registry.register(name(prefix, "hits"),
(Gauge<Long>) () -> cache.getStatistics().cacheHitCount());
registry.register(name(prefix, "in-memory-hits"),
(Gauge<Long>) () -> cache.getStatistics().localHeapHitCount());
registry.register(name(prefix, "off-heap-hits"),
(Gauge<Long>) () -> cache.getStatistics().localOffHeapHitCount());
registry.register(name(prefix, "on-disk-hits"),
(Gauge<Long>) () -> cache.getStatistics().localDiskHitCount());
registry.register(name(prefix, "misses"),
(Gauge<Long>) () -> cache.getStatistics().cacheMissCount());
registry.register(name(prefix, "in-memory-misses"),
(Gauge<Long>) () -> cache.getStatistics().localHeapMissCount());
registry.register(name(prefix, "off-heap-misses"),
(Gauge<Long>) () -> cache.getStatistics().localOffHeapMissCount());
registry.register(name(prefix, "on-disk-misses"),
(Gauge<Long>) () -> cache.getStatistics().localDiskMissCount());
registry.register(name(prefix, "objects"),
(Gauge<Long>) () -> cache.getStatistics().getSize());
registry.register(name(prefix, "in-memory-objects"),
(Gauge<Long>) () -> cache.getStatistics().getLocalHeapSize());
registry.register(name(prefix, "off-heap-objects"),
(Gauge<Long>) () -> cache.getStatistics().getLocalOffHeapSize());
registry.register(name(prefix, "on-disk-objects"),
(Gauge<Long>) () -> cache.getStatistics().getLocalDiskSize());
registry.register(name(prefix, "mean-get-time"),
(Gauge<Double>) () -> cache.getStatistics().cacheGetOperation().latency().average().value());
registry.register(name(prefix, "mean-search-time"),
(Gauge<Double>) () -> cache.getStatistics().cacheSearchOperation().latency().average().value());
registry.register(name(prefix, "eviction-count"),
(Gauge<Long>) () -> cache.getStatistics().cacheEvictionOperation().count().value());
registry.register(name(prefix, "searches-per-second"),
(Gauge<Double>) () -> cache.getStatistics().cacheSearchOperation().rate().value());
registry.register(name(prefix, "writer-queue-size"),
(Gauge<Long>) () -> cache.getStatistics().getWriterQueueLength());
return new InstrumentedEhcache(registry, cache);
}
private final Timer getTimer, putTimer;
private InstrumentedEhcache(MetricRegistry registry, Ehcache cache) {
super(cache);
this.getTimer = registry.timer(name(cache.getClass(), cache.getName(), "gets"));
this.putTimer = registry.timer(name(cache.getClass(), cache.getName(), "puts"));
}
@Override
public Element get(Object key) throws IllegalStateException, CacheException {
final Timer.Context ctx = getTimer.time();
try {
return underlyingCache.get(key);
} finally {
ctx.stop();
}
}
@Override
public Element get(Serializable key) throws IllegalStateException, CacheException {
final Timer.Context ctx = getTimer.time();
try {
return underlyingCache.get(key);
} finally {
ctx.stop();
}
}
@Override
public void put(Element element) throws IllegalArgumentException, IllegalStateException, CacheException {
final Timer.Context ctx = putTimer.time();
try {
underlyingCache.put(element);
} finally {
ctx.stop();
}
}
@Override
public void put(Element element, boolean doNotNotifyCacheReplicators) throws IllegalArgumentException, IllegalStateException, CacheException {
final Timer.Context ctx = putTimer.time();
try {
underlyingCache.put(element, doNotNotifyCacheReplicators);
} finally {
ctx.stop();
}
}
@Override
public Element putIfAbsent(Element element) throws NullPointerException {
final Timer.Context ctx = putTimer.time();
try {
return underlyingCache.putIfAbsent(element);
} finally {
ctx.stop();
}
}
}