package org.jactr.core.utils; /* * default logging */ import java.util.function.BiConsumer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.commonreality.time.impl.BasicClock; import org.jactr.core.model.ModelTerminatedException; /** * static class with various diagnostic tools. Exposes the following system * properties: "jactr.diagnostics.timeWindow" (TimeWindow name), * "jactr.diagnostics.terminateOnFail" (false) * * @author harrison */ public class Diagnostics { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(Diagnostics.class); static enum TimeWindow { DAY(86400.0), WEEK(604800.0), MONTH(2628000.0), YEAR(31536000.0), ADULTHOOD( 567648000.0), CENTURY(3153600000.0); double _value; TimeWindow(double value) { _value = value; } public double getSeconds() { return _value; } } static private TimeWindow DEFAULT_WINDOW; static private BiConsumer<Double, Double> DEFAULT_PRECISION_FAILURE; static private BiConsumer<Double, TimeWindow> DEFAULT_SANITY_FAILURE; static public final BiConsumer<Double, Double> PRECISION_IGNORE = (c, p) -> { String msg = String .format( "Precision violation. Desired [%.5f], got [%.5f]", c, p); LOGGER .debug(msg); }; static public final BiConsumer<Double, Double> PRECISION_STOP = (c, p) -> { String msg = String .format( "Precision violation. Desired [%.5f], got [%.5f]", c, p); LOGGER .error(msg); throw new ModelTerminatedException( msg); }; static public final BiConsumer<Double, Double> PRECISION_TERMINATE = (c, p) -> { String msg = String .format( "Precision violation. Desired [%.5f], got [%.5f]", c, p); LOGGER .error(msg); System .exit(-1); }; static public final BiConsumer<Double, TimeWindow> SANITY_IGNORE = (c, w) -> { String msg = String .format( "Age violation. [%.5f] exceeded [%s:%.5f]", c, w, w.getSeconds()); LOGGER .debug(msg); }; static public final BiConsumer<Double, TimeWindow> SANITY_STOP = (c, w) -> { String msg = String .format( "Age violation. [%.5f] exceeded [%s:%.5f]", c, w, w.getSeconds()); LOGGER .error(msg); throw new ModelTerminatedException( msg); }; static public final BiConsumer<Double, TimeWindow> SANITY_TERMINATE = (c, w) -> { String msg = String .format( "Age violation. [%.5f] exceeded [%s:%.5f]", c, w, w.getSeconds()); LOGGER .error(msg); System .exit(-1); }; static { String property = System.getProperty("jactr.diagnostics.timeWindow"); try { if (property == null) property = "YEAR"; DEFAULT_WINDOW = TimeWindow.valueOf(property); } catch (Exception e) { if (LOGGER.isDebugEnabled()) LOGGER.debug(String.format( "Failed to set timeWindow for %s, using YEAR. ", property), e); DEFAULT_WINDOW = TimeWindow.YEAR; } String strat = System.getProperty("jactr.diagnostics.onFail", "stop"); if (strat.equalsIgnoreCase("terminate")) { DEFAULT_PRECISION_FAILURE = PRECISION_TERMINATE; DEFAULT_SANITY_FAILURE = SANITY_TERMINATE; } else if (strat.equalsIgnoreCase("stop")) { DEFAULT_PRECISION_FAILURE = PRECISION_STOP; DEFAULT_SANITY_FAILURE = SANITY_STOP; } else { DEFAULT_PRECISION_FAILURE = PRECISION_IGNORE; DEFAULT_SANITY_FAILURE = SANITY_IGNORE; } } /** * @param precisionFailure * called when there is a failure. passed clock time, actual * precision * @param clock */ static public void precisionTest(double clock, BiConsumer<Double, Double> precisionFailure) { double next = Math.nextAfter(clock, Double.POSITIVE_INFINITY); double delta = Math.abs(next - clock); if (delta > BasicClock.getPrecision()) { LOGGER .fatal(String .format( "Precision violation, minimum increment : %.5f, requested precision: %.5f.", delta, BasicClock.getPrecision())); if (precisionFailure != null) precisionFailure.accept(clock, delta); } } /** * @param clock * @param window * @param windowFailure * @param precisionFailure */ static public void timeSanityCheck(double clock, TimeWindow window, BiConsumer<Double, TimeWindow> windowFailure, BiConsumer<Double, Double> precisionFailure) { if (clock > window.getSeconds()) { LOGGER.error(String.format( "Time sanity check failed. %.2f exceeds %.2f (%s).", clock, window.getSeconds(), window.toString())); if (windowFailure != null) windowFailure.accept(clock, window); } precisionTest(clock, precisionFailure); } static public void timeSanityCheck(double clock) { timeSanityCheck(clock, DEFAULT_WINDOW, DEFAULT_SANITY_FAILURE, DEFAULT_PRECISION_FAILURE); } }