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

io.split.client.metrics.FireAndForgetMetrics Maven / Gradle / Ivy

package io.split.client.metrics;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.split.engine.metrics.Metrics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by adilaijaz on 9/4/15.
 */
public class FireAndForgetMetrics implements Metrics {

    private static final Logger _log = LoggerFactory.getLogger(FireAndForgetMetrics.class);

    private final ExecutorService _executorService;
    private final Metrics _delegate;

    public static FireAndForgetMetrics instance(Metrics delegate, int numberOfThreads, int queueSize) {
        ThreadFactoryBuilder threadFactoryBuilder = new ThreadFactoryBuilder();
        threadFactoryBuilder.setDaemon(true);
        threadFactoryBuilder.setNameFormat("split-fireAndForgetMetrics-%d");
        threadFactoryBuilder.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                _log.error("Error in thread: " + t.getName(), e);
            }
        });

        final ExecutorService executorService = new ThreadPoolExecutor(numberOfThreads,
                numberOfThreads,
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue(queueSize),
                threadFactoryBuilder.build(),
                new ThreadPoolExecutor.DiscardPolicy());



        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                executorService.shutdown();
                try {
                    if (!executorService.awaitTermination(10L, TimeUnit.SECONDS)) { //optional *
                        _log.info("Executor did not terminate in the specified time.");
                        List droppedTasks = executorService.shutdownNow(); //optional **
                        _log.info("Executor was abruptly shut down. These tasks will not be executed: " + droppedTasks);
                    }
                } catch (InterruptedException e) {
                    // reset the interrupt.
                    Thread.currentThread().interrupt();
                }
            }

        });

        return new FireAndForgetMetrics(delegate, executorService);
    }

    private FireAndForgetMetrics(Metrics delegate, ExecutorService executorService) {
        _delegate = delegate;
        _executorService = executorService;
    }


    @Override
    public void count(String counter, long delta) {
        try {
            _executorService.submit(new CountRunnable(_delegate, counter, delta));
        } catch (Throwable t) {
            // ignore
        }
    }

    @Override
    public void time(String operation, long timeInMs) {
        try {
            _executorService.submit(new TimeRunnable(_delegate, operation, timeInMs));
        } catch (Throwable t) {
            // ignore
        }
    }

    @Override
    public void gauge(String gauge, double value) {
        try {
            _executorService.submit(new GaugeRunnable(_delegate, gauge, value));
        } catch (Throwable t) {
            // ignore
        }
    }

    private static final class CountRunnable implements Runnable {

        private final Metrics _delegate;
        private final String _name;
        private final long _delta;

        public CountRunnable(Metrics delegate, String name, long delta) {
            _delegate = delegate;
            _name = name;
            _delta = delta;
        }

        @Override
        public void run() {
            _delegate.count(_name, _delta);
        }
    }

    private static final class GaugeRunnable implements Runnable {

        private final Metrics _delegate;
        private final String _name;
        private final double _value;

        public GaugeRunnable(Metrics delegate, String name, double value) {
            _delegate = delegate;
            _name = name;
            _value = value;
        }

        @Override
        public void run() {
            _delegate.gauge(_name, _value);
        }
    }

    private static final class TimeRunnable implements Runnable {

        private final Metrics _delegate;
        private final String _name;
        private final long _timeInMs;

        public TimeRunnable(Metrics delegate, String name, long timeInMs) {
            _delegate = delegate;
            _name = name;
            _timeInMs = timeInMs;
        }

        @Override
        public void run() {
            _delegate.time(_name, _timeInMs);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy