package org.kie.perf.metrics;
import static com.codahale.metrics.MetricRegistry.name;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.MetricSet;
public class MemoryUsageGaugeSet implements MetricSet {
private Class<?> scenario;
private final MemoryMXBean mxBean;
private final List<MemoryPoolMXBean> memoryPools;
public MemoryUsageGaugeSet(Class<?> scenario) {
this.scenario = scenario;
this.mxBean = ManagementFactory.getMemoryMXBean();
this.memoryPools = new ArrayList<MemoryPoolMXBean>(ManagementFactory.getMemoryPoolMXBeans());
}
@Override
public Map<String, Metric> getMetrics() {
final Map<String, Metric> gauges = new HashMap<String, Metric>();
gauges.put(MetricRegistry.name(scenario, "heap.init"), new Gauge<String>() {
@Override
public String getValue() {
return readableFileSize(mxBean.getHeapMemoryUsage().getInit());
}
});
gauges.put(MetricRegistry.name(scenario, "heap.used"), new Gauge<String>() {
@Override
public String getValue() {
return readableFileSize(mxBean.getHeapMemoryUsage().getUsed());
}
});
gauges.put(MetricRegistry.name(scenario, "heap.max"), new Gauge<String>() {
@Override
public String getValue() {
return readableFileSize(mxBean.getHeapMemoryUsage().getMax());
}
});
gauges.put(MetricRegistry.name(scenario, "heap.committed"), new Gauge<String>() {
@Override
public String getValue() {
return readableFileSize(mxBean.getHeapMemoryUsage().getCommitted());
}
});
gauges.put(MetricRegistry.name(scenario, "heap.usage"), new Gauge<String>() {
@Override
public String getValue() {
final MemoryUsage usage = mxBean.getHeapMemoryUsage();
NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(2);
return percentFormat.format(((double) usage.getUsed()) / usage.getMax());
}
});
for (final MemoryPoolMXBean pool : memoryPools) {
gauges.put(name(scenario, pool.getName().toLowerCase().replace(" ", "."), "usage"), new Gauge<String>() {
@Override
public String getValue() {
final long max = pool.getUsage().getMax() == -1 ? pool.getUsage().getCommitted() : pool.getUsage().getMax();
NumberFormat percentFormat = NumberFormat.getPercentInstance();
percentFormat.setMaximumFractionDigits(2);
return percentFormat.format(((double) pool.getUsage().getUsed()) / max);
}
});
gauges.put(name(scenario, pool.getName().toLowerCase().replace(" ", "."), "used"), new Gauge<String>() {
@Override
public String getValue() {
return readableFileSize(pool.getUsage().getUsed());
}
});
}
return Collections.unmodifiableMap(gauges);
}
private static String readableFileSize(long size) {
if (size <= 0)
return "0";
final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}
}