package org.xbib.elasticsearch.common.metrics; import com.twitter.jsr166e.LongAdder; import org.xbib.metrics.ExpWeightedMovingAverage; import org.xbib.metrics.Metered; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** * A meter metric which measures mean throughput and one-, five-, and * fifteen-minute exponentially-weighted moving average throughputs. * * @see <a href="http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average">EMA</a> */ public class ElasticsearchMeterMetric implements Metered { private final static ScheduledExecutorService service = Executors.newScheduledThreadPool(3); private final ExpWeightedMovingAverage m1Rate = ExpWeightedMovingAverage.oneMinuteEWMA(); private final ExpWeightedMovingAverage m5Rate = ExpWeightedMovingAverage.fiveMinuteEWMA(); private final ExpWeightedMovingAverage m15Rate = ExpWeightedMovingAverage.fifteenMinuteEWMA(); private final LongAdder count; private final long startTime; private ScheduledFuture<?> future; public ElasticsearchMeterMetric() { this.count = new LongAdder(); this.startTime = System.nanoTime(); } public void spawn(long intervalSeconds) { this.future = service.scheduleAtFixedRate(new Runnable() { @Override public void run() { tick(); } }, intervalSeconds, intervalSeconds, TimeUnit.SECONDS); } /** * Updates the moving averages. */ public void tick() { m1Rate.tick(); m5Rate.tick(); m15Rate.tick(); } /** * Mark the occurrence of an event. */ public void mark() { mark(1); } /** * Mark the occurrence of a given number of events. * * @param n the number of events */ public void mark(long n) { count.add(n); m1Rate.update(n); m5Rate.update(n); m15Rate.update(n); } @Override public long getCount() { return count.sum(); } @Override public double getFifteenMinuteRate() { return m15Rate.getRate(TimeUnit.SECONDS); } @Override public double getFiveMinuteRate() { return m5Rate.getRate(TimeUnit.SECONDS); } @Override public double getMeanRate() { long count = getCount(); if (count == 0) { return 0.0; } else { final long elapsed = System.nanoTime() - startTime; return convertNsRate(count / (double) elapsed); } } @Override public double getOneMinuteRate() { return m1Rate.getRate(TimeUnit.SECONDS); } public void stop() { future.cancel(false); } private double convertNsRate(double ratePerNs) { return ratePerNs * (double) TimeUnit.SECONDS.toNanos(1); } }