package io.mangoo.models; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.LongAdder; import com.google.inject.Singleton; /** * Base class for counting system metrics * * @author svenkubiak * */ @Singleton public class Metrics { private final AtomicIntegerFieldUpdater<Metrics> maxRequestTimeUpdater = AtomicIntegerFieldUpdater.newUpdater(Metrics.class, "maxRequestTime"); private final AtomicIntegerFieldUpdater<Metrics> minRequestTimeUpdater = AtomicIntegerFieldUpdater.newUpdater(Metrics.class, "minRequestTime"); private final AtomicLongFieldUpdater<Metrics> totalRequestTimeUpdater = AtomicLongFieldUpdater.newUpdater(Metrics.class, "totalRequestTime"); private final AtomicLongFieldUpdater<Metrics> totalRequestsUpdater = AtomicLongFieldUpdater.newUpdater(Metrics.class, "totalRequests"); private final Map<Integer, LongAdder> metricsCount = new ConcurrentHashMap<>(16, 0.9F, 1); private volatile long avgRequestTime; private volatile long totalRequestTime; private volatile long totalRequests; private volatile int maxRequestTime; private volatile int minRequestTime; public Metrics() { //Empty constructor for Google Guice } public Metrics(Metrics copy) { this.totalRequestTime = copy.totalRequestTime; this.maxRequestTime = copy.maxRequestTime; this.minRequestTime = copy.minRequestTime; this.totalRequests = copy.totalRequests; } public void inc(int responseCode) { this.metricsCount.computeIfAbsent(responseCode, t -> new LongAdder()).increment(); } public void update(final int requestTime) { this.totalRequestTimeUpdater.addAndGet(this, requestTime); int tempMaxRequestTime; do { tempMaxRequestTime = this.maxRequestTime; if (requestTime < tempMaxRequestTime) { break; } } while (!this.maxRequestTimeUpdater.compareAndSet(this, tempMaxRequestTime, requestTime)); int tempMinRequestTime; do { tempMinRequestTime = this.minRequestTime; if (requestTime > tempMinRequestTime && tempMinRequestTime != -1) { break; } } while (!this.minRequestTimeUpdater.compareAndSet(this, tempMinRequestTime, requestTime)); this.totalRequestsUpdater.incrementAndGet(this); this.avgRequestTime = this.totalRequestTime / this.totalRequests; } public Map<Integer, LongAdder> getMetrics() { return this.metricsCount; } public int getMaxRequestTime() { return maxRequestTime; } public int getMinRequestTime() { return minRequestTime; } public long getAvgRequestTime() { return avgRequestTime; } }