package org.jvalue.ods.admin.monitoring;
import com.codahale.metrics.Clock;
import com.codahale.metrics.ExponentiallyDecayingReservoir;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public final class PauseableTimer {
public static PauseableTimer createTimer(MetricRegistry registry, String name) {
Map<String, Timer> timers = registry.getTimers(new StringMetricFilter(name));
if (timers.isEmpty()) {
PauseableTimer timer = new PauseableTimer();
registry.register(name, timer.getTimer());
return timer;
} else if (timers.size() == 1) return new PauseableTimer(timers.get(name));
else throw new IllegalStateException("found more than one timer for name " + name);
}
private final Timer timer;
private final Clock clock;
private PauseableTimer(Timer timer) {
this.timer = timer;
this.clock = Clock.defaultClock();
}
private PauseableTimer() {
this(new Timer(new ExponentiallyDecayingReservoir(), Clock.defaultClock()));
}
public Context createContext() {
return new Context(timer, clock);
}
public Timer getTimer() {
return timer;
}
public static class Context {
private final Timer timer;
private final Clock clock;
private long startTime;
private boolean started = false;
private long pausedTime = 0;
private long idleTime = 0;
private boolean paused = false;
private Context(Timer timer, Clock clock) {
this.timer = timer;
this.clock = clock;
}
public void pause() {
if (paused) throw new IllegalStateException("already paused");
paused = true;
pausedTime = clock.getTick();
}
public void resume() {
if (!started) {
startTime = clock.getTick();
started = true;
} else {
if (!paused) throw new IllegalStateException("not paused");
paused = false;
idleTime += (clock.getTick() - pausedTime);
}
}
public long stop() {
if (!started) throw new IllegalStateException("not started");
if (paused) resume();
long elapsedTime = clock.getTick() - startTime - idleTime;
timer.update(elapsedTime, TimeUnit.NANOSECONDS);
return elapsedTime;
}
}
}