package de.is24.util.monitoring; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.atomic.AtomicLong; /** * Timers count and measure timed events. <br> * Timers allow adding timer measurements, implicitly incrementing the count<br> * <pre> Examples * DB Query duration * rendering duration * parsing time of xml input * </pre> * <br> * Note that operations might not appear consistent especially with only a few measurements * as none of the timer operations are atomic. With many measurements these inconsistencies * should not be notable anymore though. * * @author OSchmitz */ public class Timer implements Reportable { private static final Logger LOGGER = LoggerFactory.getLogger(Timer.class); private final String name; private final AtomicLong count = new AtomicLong(); private final AtomicLong timerSum = new AtomicLong(); private final AtomicLong timerSumOfSquares = new AtomicLong(); /** * This class is only constructed by {@link InApplicationMonitor} * @param name name of this Timer */ Timer(String name) { this.name = name; } /** * Implements the visitor pattern to read this StateValueProvider */ @Override public void accept(ReportVisitor aVisitor) { LOGGER.debug("+++ entering Timer.accept +++"); aVisitor.reportTimer(this); } /** * Add a timer measurement for this timer.<br> * The application decides which unit to use for timing. * Milliseconds are suggested and some {@link ReportVisitor} implementations * may imply this. * @param durationInMillis */ public void addMeasurement(long durationInMillis) { count.addAndGet(1); timerSum.addAndGet(durationInMillis); timerSumOfSquares.addAndGet(durationInMillis * durationInMillis); } /** * initialize with 0 */ public void initializeMeasurement() { count.set(0); this.timerSum.set(0); this.timerSumOfSquares.set(0); } @Override public String getName() { return name; } public long getCount() { return count.get(); } /** * @return the sum of all timer measurements. */ public long getTimerSum() { return timerSum.get(); } /** * Note that this calculation might be notably inconsistent * unless there are many measurements as a timer is not atomic. * * @return the average of all timer measurements. */ public double getTimerAvg() { return Math.average(count.get(), timerSum.get()); } /** * Note that this calculation might be notably inconsistent * unless there are many measurements as a timer is not atomic. * * @return the standard deviation of all timer measurements. */ public double getTimerStdDev() { return Math.stdDeviation(count.get(), timerSum.get(), timerSumOfSquares.get()); } }