com.codahale.metrics.ScheduledReporter Maven / Gradle / Ivy
package com.codahale.metrics;
import java.util.Locale;
import java.util.SortedMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* The abstract base class for all scheduled reporters (i.e., reporters which process a registry's
* metrics periodically).
*
* @see ConsoleReporter
* @see CsvReporter
* @see Slf4jReporter
*/
public abstract class ScheduledReporter {
/**
* A simple named thread factory.
*/
@SuppressWarnings("NullableProblems")
private static class NamedThreadFactory implements ThreadFactory {
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
private NamedThreadFactory(String name) {
final SecurityManager s = System.getSecurityManager();
this.group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
this.namePrefix = "metrics-" + name + "-thread-";
}
@Override
public Thread newThread(Runnable r) {
final Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
t.setDaemon(true);
if (t.getPriority() != Thread.NORM_PRIORITY) {
t.setPriority(Thread.NORM_PRIORITY);
}
return t;
}
}
private final MetricRegistry registry;
private final ScheduledExecutorService executor;
private final MetricFilter filter;
private final double durationFactor;
private final String durationUnit;
private final double rateFactor;
private final String rateUnit;
/**
* Creates a new {@link ScheduledReporter} instance.
*
* @param registry the {@link com.codahale.metrics.MetricRegistry} containing the metrics this
* reporter will report
* @param name the reporter's name
* @param filter the filter for which metrics to report
*/
protected ScheduledReporter(MetricRegistry registry,
String name,
MetricFilter filter,
TimeUnit rateUnit,
TimeUnit durationUnit) {
this.registry = registry;
this.filter = filter;
this.executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory(name));
this.rateFactor = rateUnit.toSeconds(1);
this.rateUnit = calculateRateUnit(rateUnit);
this.durationFactor = 1.0 / durationUnit.toNanos(1);
this.durationUnit = durationUnit.toString().toLowerCase(Locale.US);
}
/**
* Starts the reporter polling at the given period.
*
* @param period the amount of time between polls
* @param unit the unit for {@code period}
*/
public void start(long period, TimeUnit unit) {
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
report(registry.getGauges(filter),
registry.getCounters(filter),
registry.getHistograms(filter),
registry.getMeters(filter),
registry.getTimers(filter));
}
}, period, period, unit);
}
/**
* Stops the reporter and shuts down its thread of execution.
*/
public void stop() {
executor.shutdown();
try {
executor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException ignored) {
// do nothing
}
}
/**
* Called periodically by the polling thread. Subclasses should report all the given metrics.
*
* @param gauges all of the gauges in the registry
* @param counters all of the counters in the registry
* @param histograms all of the histograms in the registry
* @param meters all of the meters in the registry
* @param timers all of the timers in the registry
*/
public abstract void report(SortedMap gauges,
SortedMap counters,
SortedMap histograms,
SortedMap meters,
SortedMap timers);
protected String getRateUnit() {
return rateUnit;
}
protected String getDurationUnit() {
return durationUnit;
}
protected double convertDuration(double duration) {
return duration * durationFactor;
}
protected double convertRate(double rate) {
return rate * rateFactor;
}
private String calculateRateUnit(TimeUnit unit) {
final String s = unit.toString().toLowerCase(Locale.US);
return s.substring(0, s.length() - 1);
}
}