Skip to content

Commit

Permalink
JVM metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
fhanik committed Sep 22, 2017
1 parent 3393c82 commit 3a78488
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 17 deletions.
Expand Up @@ -29,14 +29,19 @@
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServerConnection;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

import static java.util.Optional.ofNullable;
import static org.springframework.util.ReflectionUtils.*;
import static org.springframework.util.ReflectionUtils.findMethod;

public class UaaMetricsEmitter {
private static Log logger = LogFactory.getLog(UaaMetricsEmitter.class);
Expand Down Expand Up @@ -69,7 +74,7 @@ public void emitMetrics() throws Exception {
}
}

@Scheduled(fixedRate = 5000, initialDelay = 1500)
@Scheduled(fixedRate = 5000, initialDelay = 1000)
public void emitGlobalRequestMetrics() throws Exception {
try {
UaaMetrics metrics = metricsUtils.getUaaMetrics(server);
Expand Down Expand Up @@ -110,13 +115,9 @@ public void emitGlobalRequestMetrics(UaaMetrics metrics) {
statsDClient.gauge(prefix + "unhealthy.time", (long) totals.getAverageDatabaseFailedQueryTime());
}

@Scheduled(fixedRate = 5000, initialDelay = 3000)
public void emitVitals() throws Exception {
@Scheduled(fixedRate = 5000, initialDelay = 2000)
public void emitVmVitals() {
OperatingSystemMXBean mbean = ManagementFactory.getOperatingSystemMXBean();
emitVmVitals(mbean);
}

public void emitVmVitals(OperatingSystemMXBean mbean) {
String prefix = "vitals.vm.";
statsDClient.gauge(prefix + "cpu.count", mbean.getAvailableProcessors());
statsDClient.gauge(prefix + "cpu.load", (long)(mbean.getSystemLoadAverage()*100));
Expand All @@ -125,11 +126,34 @@ public void emitVmVitals(OperatingSystemMXBean mbean) {
invokeIfPresent(prefix + "memory.free", mbean, "getFreePhysicalMemorySize");
}

@Scheduled(fixedRate = 5000, initialDelay = 3000)
public void emitJvmVitals() {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
String prefix = "vitals.jvm.";
invokeIfPresent(prefix + "cpu.load", osBean, "getProcessCpuLoad", d -> (long)(d.doubleValue()*100));
statsDClient.gauge(prefix + "thread.count", threadBean.getThreadCount());
Map<String, MemoryUsage> memory = new HashMap<>();
memory.put("heap", memoryBean.getHeapMemoryUsage());
memory.put("non-heap", memoryBean.getHeapMemoryUsage());
memory.entrySet().stream().forEach(m -> {
statsDClient.gauge(prefix + m.getKey() + ".init", m.getValue().getInit());
statsDClient.gauge(prefix + m.getKey() + ".committed", m.getValue().getInit());
statsDClient.gauge(prefix + m.getKey() + ".used", m.getValue().getInit());
statsDClient.gauge(prefix + m.getKey() + ".max", m.getValue().getInit());
});

}

public void invokeIfPresent(String metric, Object mbean, String getter) {
Object value = getValueFromBean(mbean, getter);
long v = (long)ofNullable(value).orElse(-1l);;
if (v >= 0) {
statsDClient.gauge(metric, v);
invokeIfPresent(metric, mbean, getter, v -> (Long)v);
}
public void invokeIfPresent(String metric, Object mbean, String getter, Function<Number, Long> valueModifier) {
Number value = getValueFromBean(mbean, getter);
if (value.doubleValue() >= 0) {

statsDClient.gauge(metric, valueModifier.apply(value));
}
}

Expand All @@ -145,13 +169,13 @@ public void throwIfOtherThanNotFound(Exception x) throws Exception {
}
}

public Object getValueFromBean(Object mbean, String getter) {
public Number getValueFromBean(Object mbean, String getter) {
Method method = findMethod(mbean.getClass(), getter);
if (method != null) {
boolean original = method.isAccessible();
method.setAccessible(true);
try {
return ReflectionUtils.invokeMethod(method, mbean);
return (Number)ReflectionUtils.invokeMethod(method, mbean);
} catch (Exception e) {
logger.debug("Unable to invoke metric", e);
} finally {
Expand Down
Expand Up @@ -24,8 +24,10 @@
import java.util.HashMap;
import java.util.Map;

import static org.mockito.AdditionalMatchers.and;
import static org.mockito.AdditionalMatchers.geq;
import static org.mockito.AdditionalMatchers.gt;
import static org.mockito.AdditionalMatchers.leq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
Expand Down Expand Up @@ -121,15 +123,30 @@ public void requestCount_metrics_emitted() throws Exception {
}

@Test
public void vitals() throws Exception {
uaaMetricsEmitter.emitVitals();
public void vm_vitals() throws Exception {
uaaMetricsEmitter.emitVmVitals();
Mockito.verify(statsDClient).gauge(eq("vitals.vm.cpu.count"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.vm.cpu.load"), geq(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.vm.memory.total"), geq(134217728l));
Mockito.verify(statsDClient).gauge(eq("vitals.vm.memory.committed"), geq(1l));
Mockito.verify(statsDClient).gauge(eq("vitals.vm.memory.free"), geq(1l));
}

@Test
public void jvm_vitals() throws Exception {
uaaMetricsEmitter.emitJvmVitals();
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.cpu.load"), and(geq(0l), leq(100l)));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.thread.count"), and(gt(1l), leq(1000l)));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.heap.init"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.heap.committed"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.heap.used"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.heap.max"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.non-heap.init"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.non-heap.committed"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.non-heap.used"), gt(0l));
Mockito.verify(statsDClient).gauge(eq("vitals.jvm.non-heap.max"), gt(0l));
}

@Test
public void auditService_metricValues_areNull() throws Exception {
mBeanMap1.put("user_authentication_count", null);
Expand Down
Expand Up @@ -80,7 +80,17 @@ public class UaaMetricsEmitterIT {
"uaa.vitals.vm.cpu.load",
"uaa.vitals.vm.memory.total",
"uaa.vitals.vm.memory.committed",
"uaa.vitals.vm.memory.free"
"uaa.vitals.vm.memory.free",
"uaa.vitals.jvm.cpu.load",
"uaa.vitals.jvm.thread.count",
"uaa.vitals.jvm.heap.init",
"uaa.vitals.jvm.heap.committed",
"uaa.vitals.jvm.heap.used",
"uaa.vitals.jvm.heap.max",
"uaa.vitals.jvm.non-heap.init",
"uaa.vitals.jvm.non-heap.committed",
"uaa.vitals.jvm.non-heap.used",
"uaa.vitals.jvm.non-heap.max"
);
private static Map<String, String> secondBatch;

Expand Down

0 comments on commit 3a78488

Please sign in to comment.