package com.sixsq.slipstream.metrics;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import com.codahale.metrics.*;
import com.codahale.metrics.jvm.*;
import org.slf4j.LoggerFactory;
import com.codahale.metrics.graphite.Graphite;
import com.codahale.metrics.graphite.GraphiteReporter;
import com.codahale.metrics.graphite.GraphiteReporter.Builder;
public class Metrics {
private static Metrics instance = null;
private MetricRegistry registry;
private List<Reporter> reporters;
private Map<String, MetricsTimer> timers;
private Metrics() {
registry = new MetricRegistry();
reporters = new ArrayList<Reporter>();
timers = new ConcurrentHashMap<String, MetricsTimer>();
}
private static synchronized Metrics getInstance() {
if (instance == null) {
instance = new Metrics();
}
return instance;
}
@SuppressWarnings("unused")
private static String generateName(Object instance, String... names) {
return MetricRegistry.name(instance.getClass(), names);
}
private static String generateName(Class<?> klass, String... names) {
return MetricRegistry.name(klass, names);
}
public static MetricsTimer getTimer(Object instance, String... names){
return getTimer(instance.getClass(), names);
}
public static synchronized MetricsTimer getTimer(Class<?> klass, String... names) {
String name = generateName(klass, names);
Metrics instance = getInstance();
if (instance.timers.containsKey(name)) {
return instance.timers.get(name);
} else {
MetricsTimer timer = new MetricsTimer(instance.getRegistry().timer(name));
instance.timers.put(name, timer);
return timer;
}
}
public static MetricsTimer newTimer(Object instance, String... names){
return newTimer(instance.getClass(), names);
}
public static MetricsTimer newTimer(Class<?> klass, String... names){
return new MetricsTimer(getInstance().getRegistry().timer(generateName(klass, names)));
}
/*
public void deleteAllReporters() {
for (Reporter reporter: reporters) {
reporter.stop();
}
}
*/
public static void addJmxReporter() {
getInstance().createJmxReporter();
}
public static void addConsoleReporter() {
getInstance().createConsoleReporter();
}
public static void addCsvReporter(String filename) {
getInstance().createCsvReporter(filename);
}
public static void addSlf4jReporter() {
getInstance().createSlf4jReporter();
}
public static void addGraphiteReporter() {
addGraphiteReporter("127.0.0.1");
}
public static void addGraphiteReporter(String host) {
addGraphiteReporter(host, null);
}
public static void addGraphiteReporter(String host, int port){
addGraphiteReporter(host, port, null);
}
public static void addGraphiteReporter(String host, String prefix){
addGraphiteReporter(host, 2003, prefix);
}
public static void addGraphiteReporter(String host, int port, String prefix){
getInstance().createGraphiteReporter(host, port, prefix);
}
public static void addJvmMetrics() {
getInstance().registerJvmMetrics();
}
private MetricRegistry getRegistry(){
return this.registry;
}
private void registerMetricSetRecursively(String name, MetricSet metricSet) {
registerMetricSetRecursively(this, name, metricSet);
}
private void registerMetricSetRecursively(Object instance, String name, MetricSet metricSet) {
registerMetricSetRecursively(instance.getClass(), name, metricSet);
}
private void registerMetricSetRecursively(Class<?> klass, String name, MetricSet metricSet) {
for (Map.Entry<String, Metric> metricEntry : metricSet.getMetrics().entrySet()) {
Metric metric = metricEntry.getValue();
String metricName = metricEntry.getKey();
if (metric instanceof MetricSet) {
registerMetricSetRecursively(klass, name + "." + metricName, (MetricSet) metric);
} else {
registry.register(generateName(klass, name, metricName), metric);
}
}
}
private void registerJvmMetrics() {
String prefix = "jvm.";
registerMetricSetRecursively(prefix + "gc", new GarbageCollectorMetricSet());
registerMetricSetRecursively(prefix + "memory", new MemoryUsageGaugeSet());
registerMetricSetRecursively(prefix + "threads", new ThreadStatesGaugeSet());
registerMetricSetRecursively(prefix + "buffers", new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
registerMetricSetRecursively(prefix + "classloader", new ClassLoadingGaugeSet());
registry.register(generateName(this, prefix, "fd", "used-ratio"), new FileDescriptorRatioGauge());
}
private void createJmxReporter() {
JmxReporter reporter = JmxReporter.forRegistry(registry).build();
reporters.add(reporter);
reporter.start();
}
private void createConsoleReporter() {
ConsoleReporter reporter = ConsoleReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(1, TimeUnit.MINUTES);
reporters.add(reporter);
}
private void createCsvReporter(String filename) {
CsvReporter reporter = CsvReporter.forRegistry(registry)
.formatFor(Locale.US)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build(new File(filename));
reporter.start(1, TimeUnit.SECONDS);
reporters.add(reporter);
}
private void createSlf4jReporter() {
Slf4jReporter reporter = Slf4jReporter.forRegistry(registry)
.outputTo(LoggerFactory.getLogger(this.getClass()))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
reporter.start(10, TimeUnit.SECONDS);
reporters.add(reporter);
}
private void createGraphiteReporter(String host, int port, String prefix) {
Graphite graphite = new Graphite(new InetSocketAddress(host, port));
Builder builder = GraphiteReporter.forRegistry(registry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.filter(MetricFilter.ALL);
if (prefix != null) {
builder = builder.prefixedWith(prefix);
}
GraphiteReporter reporter = builder.build(graphite);
reporter.start(1, TimeUnit.SECONDS);
reporters.add(reporter);
}
}