package io.lumify.core.util;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class MetricReportingExecutorService extends ThreadPoolExecutor {
private LumifyLogger logger;
private ScheduledExecutorService scheduledExecutorService;
private FixedSizeCircularLinkedList<AtomicInteger> executionCount;
private FixedSizeCircularLinkedList<AtomicInteger> maxActive;
private FixedSizeCircularLinkedList<AtomicInteger> maxWaiting;
public MetricReportingExecutorService(LumifyLogger logger, int nThreads) {
super(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
this.logger = logger;
executionCount = new FixedSizeCircularLinkedList<AtomicInteger>(16, AtomicInteger.class);
maxActive = new FixedSizeCircularLinkedList<AtomicInteger>(16, AtomicInteger.class);
maxWaiting = new FixedSizeCircularLinkedList<AtomicInteger>(16, AtomicInteger.class);
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
tick();
}
}, 1, 1, TimeUnit.MINUTES);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
report();
}
}, 1, 5, TimeUnit.MINUTES);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
executionCount.head().incrementAndGet();
int active = getActiveCount();
int currentMaxActive = maxActive.head().get();
if (active > currentMaxActive) {
maxActive.head().set(active);
}
int waiting = getQueue().size();
int currentMaxWaiting = maxWaiting.head().get();
if (waiting > currentMaxWaiting) {
maxWaiting.head().set(waiting);
}
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
}
public void tick() {
executionCount.rotateForward();
executionCount.head().set(0);
maxActive.rotateForward();
maxActive.head().set(0);
maxWaiting.rotateForward();
maxWaiting.head().set(0);
}
public void report() {
List<AtomicInteger> executionCountList = executionCount.readBackward(15);
List<AtomicInteger> maxActiveList = maxActive.readBackward(15);
List<AtomicInteger> maxWaitingList = maxWaiting.readBackward(15);
report("executions: ", executionCountList);
report("max active: ", maxActiveList);
report("max waiting:", maxWaitingList);
}
private void report(String label, List<AtomicInteger> list) {
int one = list.get(0).get();
int five = 0;
int fifteen = 0;
for (int i = 0; i < 15; i++) {
int value = list.get(i).get();
if (i < 5) {
five += value;
}
fifteen += value;
}
logger.debug("%s %3d / %6.2f / %6.2f", label, one, five / 5.0, fifteen / 15.0);
}
@Override
public void shutdown() {
scheduledExecutorService.shutdown();
super.shutdown();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
scheduledExecutorService.awaitTermination(timeout, unit);
return super.awaitTermination(timeout, unit);
}
@Override
public List<Runnable> shutdownNow() {
scheduledExecutorService.shutdownNow();
return super.shutdownNow();
}
}