com.signalfx.codahale.util.BasicJvmMetrics Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of signalfx-codahale Show documentation
Show all versions of signalfx-codahale Show documentation
Dropwizard Codahale metrics plugin for signalfx
The newest version!
/**
* Copyright (C) 2014 SignalFx, Inc.
*/
package com.signalfx.codahale.util;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricRegistry;
/**
* Report a basic set of JVM metrics to SignalFx.
*
*/
public class BasicJvmMetrics {
/**
* Report JVM uptime (milliseconds).
*/
public final Gauge uptimeGauge;
/**
* Reports total memory used by the JVM heap (bytes).
*/
public final Gauge totalMemoryGauge;
/**
* Reports current in-use memory in the JVP heap (bytes).
*/
public final Gauge usedMemoryGauge;
/**
* Reports maximum size of JVM heap (bytes).
*/
public final Gauge maxMemoryGauge;
/**
* Reports current CPU load (percent, normalized by number of CPUs available to the JVM.
*/
public final Gauge cpuLoadGauge;
/**
* Reports total number of user and daemon threads.
*/
public final Gauge totalThreadCountGauge;
/**
* Reports number of daemon threads.
*/
public final Gauge daemonThreadCountGauge;
/**
* Reports total time spent in garbage collection (nanoseconds).
*/
public final Gauge gcTimeGauge;
/**
* Reports number of young-generation garbage collections.
*/
public final Gauge gcYoungCountGauge;
/**
* Reports number of old-generation garbage collections.
*/
public final Gauge gcOldCountGauge;
/**
* Reports current GC load (percent, normalized by number of CPUs available to the JVM.
*/
public final Gauge gcLoadGauge;
private final RuntimeMXBean runtimeBean;
private final MemoryMXBean memoryBean;
private final ThreadMXBean threadBean;
private final List oldGenGcBeans = new ArrayList();
private final List youngGenGcBeans = new ArrayList();
private final List allGcBeans = new ArrayList();
// observed name of the old generation memory pool.
private static final String OLD_GEN_POOL_NAME = "PS Old Gen";
/**
* Construct the basic JVM metrics using a supplied SignalFx MetricFactory.
*
* @param metricRegistry The registry to give these metrics to
*/
public BasicJvmMetrics(MetricRegistry metricRegistry) {
runtimeBean = ManagementFactory.getRuntimeMXBean();
memoryBean = ManagementFactory.getMemoryMXBean();
threadBean = ManagementFactory.getThreadMXBean();
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
allGcBeans.add(gcBean);
Set poolNames = new HashSet(Arrays.asList(gcBean.getMemoryPoolNames()));
if (poolNames.contains(OLD_GEN_POOL_NAME)) {
// We'll count garbage collectors managing the OLD_GEN_POOL_NAME as 'old generation'
oldGenGcBeans.add(gcBean);
} else {
// and all others as 'young generation'
youngGenGcBeans.add(gcBean);
}
}
this.uptimeGauge = createPeriodicGauge(metricRegistry, "jvm.uptime", new UptimeCallback());
this.totalMemoryGauge = createPeriodicGauge(metricRegistry, "jvm.heap.size",
new TotalMemoryCallback());
this.usedMemoryGauge = createPeriodicGauge(metricRegistry, "jvm.heap.used",
new UsedMemoryCallback());
this.maxMemoryGauge = createPeriodicGauge(metricRegistry, "jvm.heap.max",
new MaxMemoryCallback());
this.cpuLoadGauge = createDoublePeriodicGauge(metricRegistry, "jvm.cpu.load", new CpuLoadCallback());
this.totalThreadCountGauge = createIntegerPeriodicGauge(metricRegistry, "jvm.threads.total",
new TotalThreadCountCallback());
this.daemonThreadCountGauge = createIntegerPeriodicGauge(metricRegistry, "jvm.threads.daemon",
new DaemonThreadCountCallback());
this.gcTimeGauge = createPeriodicGauge(metricRegistry, "jvm.gc.time", new GcTimeCallback());
this.gcLoadGauge = createDoublePeriodicGauge(metricRegistry, "jvm.gc.load", new GcLoadCallback());
this.gcYoungCountGauge = createPeriodicGauge(metricRegistry, "jvm.gc.young.count",
new GcCountCallback(youngGenGcBeans));
this.gcOldCountGauge = createPeriodicGauge(metricRegistry, "jvm.gc.old.count",
new GcCountCallback(oldGenGcBeans));
}
private Gauge createPeriodicGauge(MetricRegistry metricRegistry, String name,
Gauge gauge) {
return metricRegistry.register(name, gauge);
}
private Gauge createIntegerPeriodicGauge(MetricRegistry metricRegistry, String name,
Gauge gauge) {
return metricRegistry.register(name, gauge);
}
private Gauge createDoublePeriodicGauge(MetricRegistry metricRegistry, String name,
Gauge gauge) {
return metricRegistry.register(name, gauge);
}
private class UptimeCallback implements Gauge {
@Override
public Long getValue() {
return runtimeBean.getUptime();
}
}
private class TotalMemoryCallback implements Gauge {
@Override
public Long getValue() {
return memoryBean.getHeapMemoryUsage().getCommitted();
}
}
private class UsedMemoryCallback implements Gauge {
@Override
public Long getValue() {
return memoryBean.getHeapMemoryUsage().getUsed();
}
}
private class MaxMemoryCallback implements Gauge {
@Override
public Long getValue() {
return memoryBean.getHeapMemoryUsage().getMax();
}
}
private class TotalThreadCountCallback implements Gauge {
@Override
public Integer getValue() {
return threadBean.getThreadCount();
}
}
private class DaemonThreadCountCallback implements Gauge {
@Override
public Integer getValue() {
return threadBean.getDaemonThreadCount();
}
}
private class GcTimeCallback implements Gauge {
@Override
public Long getValue() {
long total = 0;
for (GarbageCollectorMXBean gcBean : allGcBeans) {
long sample = gcBean.getCollectionTime();
if (sample > 0) {
total += sample;
}
}
return total;
}
}
private static class GcCountCallback implements Gauge {
final private List gcBeans;
private GcCountCallback(List gcBeans) {
this.gcBeans = gcBeans;
}
@Override
public Long getValue() {
long total = 0;
for (GarbageCollectorMXBean gcBean : gcBeans) {
long sample = gcBean.getCollectionCount();
if (sample > 0) {
total += sample;
}
}
return total;
}
}
private abstract class LoadCallback implements Gauge {
private static final int PERCENT = 100;
private long previousTime;
private double previousValue;
private Map samples = new HashMap();
private final TimeUnit timeUnit;
LoadCallback(TimeUnit timeUnit) {
this.previousTime = 0;
this.previousValue = 0;
this.timeUnit = timeUnit;
}
protected abstract Map getSamples();
private long computeDelta(Map newSamples) {
long delta = 0;
for (Map.Entry entry : newSamples.entrySet()) {
T key = entry.getKey();
Long sample = entry.getValue();
if (sample < 0) {
// not valid for this key
} else {
Long previous = samples.get(key);
if (previous == null) {
delta += sample; // first sample
} else {
delta += sample - previous;
}
}
}
samples = newSamples;
return delta;
}
@Override
public Double getValue() {
long time = runtimeBean.getUptime();
long deltaTime = time - previousTime;
if (deltaTime < 100) {
return previousValue;
}
Map samples = getSamples();
long deltaLoad = computeDelta(samples);
previousValue = (double) PERCENT * timeUnit.toNanos(deltaLoad)
/ TimeUnit.MILLISECONDS.toNanos(deltaTime)
/ Runtime.getRuntime().availableProcessors();
previousTime = time;
return previousValue;
}
}
// com.sun.management.OperatingSystemMXBean has a getProcessCpuTime()
// but java.lang.management.OperatingSystemMXBean does not
private class CpuLoadCallback extends LoadCallback {
CpuLoadCallback() {
super(TimeUnit.NANOSECONDS);
}
@Override
protected Map getSamples() {
Map samples = new HashMap();
for (long threadId : threadBean.getAllThreadIds()) {
samples.put(threadId, threadBean.getThreadCpuTime(threadId));
}
return samples;
}
}
// factor stuff out of this and CpuLoadCallback
private class GcLoadCallback extends LoadCallback {
GcLoadCallback() {
super(TimeUnit.MILLISECONDS);
}
@Override
protected Map getSamples() {
Map samples = new HashMap();
for (GarbageCollectorMXBean gcBean : allGcBeans) {
samples.put(gcBean.getName(), gcBean.getCollectionTime());
}
return samples;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy