package de.is24.util.monitoring; import de.is24.util.monitoring.measurement.MeasurementHandler; import org.slf4j.LoggerFactory; /** * Helper class to perform timer measurements. Once a timer it is created it measures the current system time. * Calling measure() will measure the time again, calculate the difference in milli seconds and return it. * <p> * Usage: * <pre> * final PerfTimer actionTimer = PerfTimer.createDebugTimer(getClass()); * doAction(); * System.out.println("Executing action took " + actionTimer.measure() + " ms"); * </pre> * * PerfTimer provides an {@link InApplicationMonitor} (createMonitor()) connection as well as debug-only measurement facilities. * * @author <a href="mailto:sschubert@immobilienscout24.de">Stefan Schubert</a>, IT-E, IS24 */ public abstract class PerfTimer { /** * @return a timer measuring at any time. */ public static PerfTimer createTimer() { return create(true); } /** * @return a {@link PerfMonitor}. Use PerfMonitor.monitor({@link String}) * to perform a measurement and submit it to the {@link InApplicationMonitor}. */ public static PerfMonitor createMonitor() { return PerfMonitor.create(); } /** * @param type the logger category used for debugging. A null argument performs equally to createTimer(). * @return a timer that only performs valid measurements on debug level and below. */ public static PerfTimer createDebugTimer(Class<?> type) { return create(LoggerFactory.getLogger(type).isDebugEnabled()); } /** * @param type the logger category used for info-level debugging. A null argument performs equally to createTimer(). * @return a timer that only performs valid measurements on info level and below. */ public static PerfTimer createInfoTimer(Class<?> type) { return create(LoggerFactory.getLogger(type).isInfoEnabled()); } /** * @param active determining whether to measure or not to measure. * @return a timer that only performs valid measurements if the argument is true. */ private static PerfTimer create(final boolean active) { if (active) { return DefaultPerfTimer.create(); } return NoPerfTimer.create(); } /** * @return the time in milli seconds from the creation of this timer until the call of this method. */ public abstract long measure(); /** * A timer that always returns 0 on measurements for performance reasons (null object). * * @author <a href="mailto:sschubert@immobilienscout24.de">Stefan Schubert</a>, IT-E, IS24 */ private static final class NoPerfTimer extends PerfTimer { private static final PerfTimer INSTANCE = new NoPerfTimer(); static PerfTimer create() { return INSTANCE; } private NoPerfTimer() { } @Override public long measure() { return 0L; } } /** * A timer implementing the default measurement behaviour based on system time. * * @author <a href="mailto:sschubert@immobilienscout24.de">Stefan Schubert</a>, IT-E, IS24 */ private static class DefaultPerfTimer extends PerfTimer { static PerfTimer create() { return new DefaultPerfTimer(); } protected final long start; protected DefaultPerfTimer() { start = System.currentTimeMillis(); } @Override public long measure() { return System.currentTimeMillis() - start; } } /** * A timer providing an interface for submitting measurements to InApplicationMonitor. * Simply call monitor(String) to submit the measurement. * * @author <a href="mailto:sschubert@immobilienscout24.de">Stefan Schubert</a>, IT-E, IS24 */ public static final class PerfMonitor extends DefaultPerfTimer { static PerfMonitor create() { return new PerfMonitor(); } protected PerfMonitor() { super(); } /** * Performs a measurement and submits the result to the InApplicationMonitor using the specified monitor name(s). * * @param monitorNames the keys where monitoring results for a class of measurements can be looked up. * @deprecated use handleMeasurement instead */ @Deprecated public void monitor(String... monitorNames) { assert (monitorNames != null) && (monitorNames.length > 0); final long time = measure(); for (String monitor : monitorNames) { assert (monitor != null) && (monitor.trim().length() > 0); InApplicationMonitor.getInstance().addTimerMeasurement(monitor, time); } } public void handleMeasurement(String monitorName, MeasurementHandler... handlers) { long time = measure(); for (MeasurementHandler handler : handlers) { handler.handle(monitorName, time); } } } }