All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ajjpj.asysmon.impl.RobustScalarMeasurerWrapper Maven / Gradle / Ivy

There is a newer version: 1.0-pre28
Show newest version
package com.ajjpj.asysmon.impl;

import com.ajjpj.asysmon.config.log.ASysMonLogger;
import com.ajjpj.asysmon.data.AScalarDataPoint;
import com.ajjpj.asysmon.measure.scalar.AScalarMeasurer;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * This class limits the impact on A-SysMon itself if some measurer runs into problems or uses large amounts of resources
 *
 * @author arno
 */
class RobustScalarMeasurerWrapper {
    private static final ASysMonLogger log = ASysMonLogger.get(RobustScalarMeasurerWrapper.class);

    private final AScalarMeasurer inner;

    private final long timeoutNanos;
    private final int maxNumTimeouts;

    private final AtomicInteger numTimeouts = new AtomicInteger(0);

    private interface Strategy {
        void prepareMeasurements(Map mementos);
        void contributeMeasurements(Map data, long timestamp, Map mementos);
    }

    private final Strategy ENABLED = new Strategy() {
        @Override public void prepareMeasurements(Map mementos) {
            try {
                final long start = System.nanoTime();
                inner.prepareMeasurements(mementos);
                handleDuration(System.nanoTime() - start);
            } catch (Exception e) {
                log.warn("Disabling scalar measurer " + inner.getClass().getName() + " because an exception occurred", e);
                strategy = DISABLED;
            }
        }

        private void handleDuration(long durationNanos) {
            if(durationNanos > timeoutNanos) {
                log.warn("Scalar measurer " + inner.getClass().getName() + " timed out (took " + durationNanos + "ns)");
                numTimeouts.incrementAndGet();
                strategy = TIMED_OUT;
            }
        }

        @Override public void contributeMeasurements(Map data, long timestamp, Map mementos) {
            try {
                final long start = System.nanoTime();
                inner.contributeMeasurements(data, timestamp, mementos);
                handleDuration(System.nanoTime() - start);
            } catch (Exception e) {
                log.warn("Disabling scalar measurer " + inner.getClass().getName() + " because an exception occurred", e);
                strategy = DISABLED;
            }
        }
    };

    private final Strategy TIMED_OUT = new Strategy() {
        @Override public void prepareMeasurements(Map mementos) {
            try {
                final long start = System.nanoTime();
                inner.prepareMeasurements(mementos);
                handleDuration(System.nanoTime() - start);
            } catch (Exception e) {
                log.warn("Disabling scalar measurer " + inner.getClass().getName() + " because an exception occurred", e);
                strategy = DISABLED;
            }
        }

        private void handleDuration(long durationNanos) {
            if(durationNanos > timeoutNanos) {
                if(numTimeouts.incrementAndGet() >= maxNumTimeouts) {
                    log.warn("Scalar measurer " + inner.getClass().getName() + " timed out " + maxNumTimeouts + " times in row - permanently disabling");
                    strategy = DISABLED;
                }
                else {
                    strategy = ENABLED;
                }
            }
        }

        @Override public void contributeMeasurements(Map data, long timestamp, Map mementos) {
            try {
                final long start = System.nanoTime();
                inner.contributeMeasurements(data, timestamp, mementos);
                handleDuration(System.nanoTime() - start);
            } catch (Exception e) {
                log.warn("Disabling scalar measurer " + inner.getClass().getName() + " because an exception occurred", e);
                strategy = DISABLED;
            }
        }
    };

    private final Strategy DISABLED = new Strategy() {
        @Override public void prepareMeasurements(Map mementos) {
        }

        @Override public void contributeMeasurements(Map data, long timestamp, Map mementos) {
        }
    };

    private volatile Strategy strategy = ENABLED;

    RobustScalarMeasurerWrapper(AScalarMeasurer inner, long timeoutNanos, int maxNumTimeouts) {
        this.inner = inner;
        this.timeoutNanos = timeoutNanos;
        this.maxNumTimeouts = maxNumTimeouts;
    }

    public void prepareMeasurements(Map mementos) {
        strategy.prepareMeasurements(mementos);
    }

    public void contributeMeasurements(Map data, long timestamp, Map mementos) {
        strategy.contributeMeasurements(data, timestamp, mementos);
    }

    public void shutdown() {
        try {
            inner.shutdown();
        } catch (Exception exc) {
            log.error("failed to shut down scalar measurer " + inner.getClass().getName() + ".", exc);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy