package com.codahale.metrics; import delight.json.JSON; import delight.json.JSONObject; import delight.json.ToJSON; /** * A meter metric which measures mean throughput and one-, five-, and * fifteen-minute exponentially-weighted moving average throughputs. * * @see EWMA */ public class Meter implements Metered, ToJSON { private static final long TICK_INTERVAL = 5000000000L;// TimeUnit.SECONDS.toNanos(5); private final EWMA m1Rate = EWMA.oneMinuteEWMA(); private final EWMA m5Rate = EWMA.fiveMinuteEWMA(); private final EWMA m15Rate = EWMA.fifteenMinuteEWMA(); private final LongAdder count = new LongAdderGwt(); private final long startTime; private long lastTick; private final Clock clock; /** * Creates a new {@link Meter}. */ public Meter() { this(Clock.defaultClock()); } /** * Creates a new {@link Meter}. * * @param clock * the clock to use for the meter ticks */ public Meter(final Clock clock) { this.clock = clock; this.startTime = this.clock.getTick(); this.lastTick = startTime; } /** * 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(final long n) { tickIfNecessary(); count.add(n); m1Rate.update(n); m5Rate.update(n); m15Rate.update(n); } private void tickIfNecessary() { final long oldTick = lastTick; final long newTick = clock.getTick(); final long age = newTick - oldTick; if (age > TICK_INTERVAL) { final long newIntervalStartTick = newTick - age % TICK_INTERVAL; if (lastTick == oldTick) { lastTick = newIntervalStartTick; final long requiredTicks = age / TICK_INTERVAL; for (long i = 0; i < requiredTicks; i++) { m1Rate.tick(); m5Rate.tick(); m15Rate.tick(); } } } } @Override public long getCount() { return count.sum(); } @Override public double getFifteenMinuteRate() { tickIfNecessary(); return m15Rate.getRate(1000000000 /* 1 s in nanosecons */); } @Override public double getFiveMinuteRate() { tickIfNecessary(); return m5Rate.getRate(1000000000 /* 1 s in nanosecons */); } @Override public double getMeanRate() { if (getCount() == 0) { return 0.0; } else { final double elapsed = (clock.getTick() - startTime); return getCount() / elapsed * 1000000000 /* 1 s in nanosecons */; } } @Override public double getOneMinuteRate() { tickIfNecessary(); return m1Rate.getRate(1000000000 /* 1 s in nanosecons */); } @Override public String toString() { return toJSON().render(); } @Override public JSON toJSON() { final JSONObject o = JSON.create(); o.add("Total Events", count); o.add("Events per Second (last Minute)", getOneMinuteRate()); o.add("Events per Second (last 5 Minutes)", getFiveMinuteRate()); o.add("Events per Second (last 15 Minutes)", getFifteenMinuteRate()); return o; } }