Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.netflix.servo.publish.JvmMetricPoller Maven / Gradle / Ivy
/*
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.servo.publish;
import com.netflix.servo.Metric;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.monitor.MonitorConfig;
import com.netflix.servo.tag.BasicTagList;
import com.netflix.servo.tag.Tag;
import com.netflix.servo.tag.TagList;
import com.netflix.servo.tag.Tags;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Poller for standard JVM metrics.
*/
public class JvmMetricPoller implements MetricPoller {
private static final String CLASS = "class";
private static final Thread.State[] VALID_STATES = Thread.State.values();
private static final MonitorConfig LOADED_CLASS_COUNT =
MonitorConfig.builder("loadedClassCount")
.withTag(CLASS, ClassLoadingMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig TOTAL_LOADED_CLASS_COUNT =
MonitorConfig.builder("totalLoadedClassCount")
.withTag(CLASS, ClassLoadingMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig UNLOADED_CLASS_COUNT =
MonitorConfig.builder("unloadedClassCount")
.withTag(CLASS, ClassLoadingMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig TOTAL_COMPILATION_TIME =
MonitorConfig.builder("totalCompilationTime")
.withTag(CLASS, CompilationMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig COLLECTION_COUNT =
MonitorConfig.builder("collectionCount")
.withTag(CLASS, GarbageCollectorMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig COLLECTION_TIME =
MonitorConfig.builder("collectionTime")
.withTag(CLASS, GarbageCollectorMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig COMMITTED_USAGE =
MonitorConfig.builder("committedUsage")
.withTag(CLASS, MemoryPoolMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig INIT_USAGE =
MonitorConfig.builder("initUsage")
.withTag(CLASS, MemoryPoolMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig MAX_USAGE =
MonitorConfig.builder("maxUsage")
.withTag(CLASS, MemoryPoolMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig ACTUAL_USAGE =
MonitorConfig.builder("actualUsage")
.withTag(CLASS, MemoryPoolMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig AVAILABLE_PROCESSORS =
MonitorConfig.builder("availableProcessors")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig LOAD_AVERAGE =
MonitorConfig.builder("systemLoadAverage")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig MAX_FILE_DESCRIPTOR_COUNT =
MonitorConfig.builder("maxFileDescriptorCount")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig OPEN_FILE_DESCRIPTOR_COUNT =
MonitorConfig.builder("openFileDescriptorCount")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig COMMITTED_VIRTUAL_MEMORY_SIZE =
MonitorConfig.builder("committedVirtualMemorySize")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig TOTAL_PHYSICAL_MEMORY_SIZE =
MonitorConfig.builder("totalPhysicalMemorySize")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig FREE_PHYSICAL_MEMORY_SIZE =
MonitorConfig.builder("freePhysicalMemorySize")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig TOTAL_SWAP_SPACE_SIZE =
MonitorConfig.builder("totalSwapSpaceSize")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig FREE_SWAP_SPACE_SIZE =
MonitorConfig.builder("freeSwapSpaceSize")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig PROCESS_CPU_LOAD =
MonitorConfig.builder("processCpuLoad")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig SYSTEM_CPU_LOAD =
MonitorConfig.builder("systemCpuLoad")
.withTag(CLASS, OperatingSystemMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig DAEMON_THREAD_COUNT =
MonitorConfig.builder("daemonThreadCount")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.GAUGE)
.build();
private static final MonitorConfig[] THREAD_COUNTS = new MonitorConfig[VALID_STATES.length];
private static final MonitorConfig TOTAL_STARTED_THREAD_COUNT =
MonitorConfig.builder("totalStartedThreadCount")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig THREAD_BLOCKED_COUNT =
MonitorConfig.builder("threadBlockedCount")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig THREAD_BLOCKED_TIME =
MonitorConfig.builder("threadBlockedTime")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig THREAD_WAITED_COUNT =
MonitorConfig.builder("threadWaitedCount")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final MonitorConfig THREAD_WAITED_TIME =
MonitorConfig.builder("threadWaitedTime")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag(DataSourceType.COUNTER)
.build();
private static final Logger LOGGER = LoggerFactory.getLogger(JvmMetricPoller.class);
private static final int IDX_BLOCKED_COUNT = 0;
private static final int IDX_BLOCKED_TIME = 1;
private static final int IDX_WAITED_COUNT = 2;
private static final int IDX_WAITED_TIME = 3;
private static final long[] BASE_THREAD_COUNTS = new long[]{0L, 0L, 0L, 0L};
private static final Map STATE_LOOKUP =
new HashMap<>();
static {
for (int i = 0; i < VALID_STATES.length; ++i) {
Thread.State state = VALID_STATES[i];
STATE_LOOKUP.put(state, i);
THREAD_COUNTS[i] =
MonitorConfig.builder("threadCount")
.withTag(CLASS, ThreadMXBean.class.getSimpleName())
.withTag("state", state.toString())
.withTag(DataSourceType.GAUGE)
.build();
}
}
private ThreadInfo[] lastThreadInfos = new ThreadInfo[0];
/**
* {@inheritDoc}
*/
@Override
public final List poll(MetricFilter filter) {
return poll(filter, false);
}
/**
* {@inheritDoc}
*/
@Override
public final List poll(MetricFilter filter, boolean reset) {
long now = System.currentTimeMillis();
MetricList metrics = new MetricList(filter);
addClassLoadingMetrics(now, metrics);
addCompilationMetrics(now, metrics);
addGarbageCollectorMetrics(now, metrics);
addMemoryPoolMetrics(now, metrics);
addOperatingSystemMetrics(now, metrics);
addThreadMetrics(now, metrics);
return metrics.getList();
}
private void addClassLoadingMetrics(long timestamp, MetricList metrics) {
ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
metrics.add(new Metric(LOADED_CLASS_COUNT,
timestamp, bean.getLoadedClassCount()));
metrics.add(new Metric(TOTAL_LOADED_CLASS_COUNT,
timestamp, bean.getTotalLoadedClassCount()));
metrics.add(new Metric(UNLOADED_CLASS_COUNT,
timestamp, bean.getUnloadedClassCount()));
}
private void addCompilationMetrics(long timestamp, MetricList metrics) {
CompilationMXBean bean = ManagementFactory.getCompilationMXBean();
metrics.add(new Metric(TOTAL_COMPILATION_TIME, timestamp, bean.getTotalCompilationTime()));
}
private void addGarbageCollectorMetrics(long timestamp, MetricList metrics) {
final List beans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean bean : beans) {
final Tag id = Tags.newTag("id", bean.getName());
metrics.add(new Metric(COLLECTION_COUNT.withAdditionalTag(id),
timestamp, bean.getCollectionCount()));
metrics.add(new Metric(COLLECTION_TIME.withAdditionalTag(id),
timestamp, bean.getCollectionTime()));
}
}
private void addMemoryPoolMetrics(long timestamp, MetricList metrics) {
final List beans = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean bean : beans) {
final TagList tags = BasicTagList.of("id", bean.getName(),
"memtype", bean.getType().name());
addMemoryUsageMetrics(tags, timestamp, bean.getUsage(), metrics);
}
}
private void addMemoryUsageMetrics(
TagList tags, long timestamp, MemoryUsage usage, MetricList metrics) {
metrics.add(new Metric(COMMITTED_USAGE.withAdditionalTags(tags),
timestamp, usage.getCommitted()));
metrics.add(new Metric(INIT_USAGE.withAdditionalTags(tags), timestamp, usage.getInit()));
metrics.add(new Metric(ACTUAL_USAGE.withAdditionalTags(tags), timestamp, usage.getUsed()));
metrics.add(new Metric(MAX_USAGE.withAdditionalTags(tags), timestamp, usage.getMax()));
}
private void addOperatingSystemMetrics(long timestamp, MetricList metrics) {
OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean();
metrics.add(new Metric(AVAILABLE_PROCESSORS, timestamp, bean.getAvailableProcessors()));
metrics.add(new Metric(LOAD_AVERAGE, timestamp, bean.getSystemLoadAverage()));
addOptionalMetric(MAX_FILE_DESCRIPTOR_COUNT,
timestamp, bean, "getMaxFileDescriptorCount", metrics);
addOptionalMetric(OPEN_FILE_DESCRIPTOR_COUNT,
timestamp, bean, "getOpenFileDescriptorCount", metrics);
addOptionalMetric(COMMITTED_VIRTUAL_MEMORY_SIZE,
timestamp, bean, "getCommittedVirtualMemorySize", metrics);
addOptionalMetric(TOTAL_PHYSICAL_MEMORY_SIZE,
timestamp, bean, "getTotalPhysicalMemorySize", metrics);
addOptionalMetric(FREE_PHYSICAL_MEMORY_SIZE,
timestamp, bean, "getFreePhysicalMemorySize", metrics);
addOptionalMetric(TOTAL_SWAP_SPACE_SIZE,
timestamp, bean, "getTotalSwapSpaceSize", metrics);
addOptionalMetric(FREE_SWAP_SPACE_SIZE,
timestamp, bean, "getFreeSwapSpaceSize", metrics);
addOptionalMetric(PROCESS_CPU_LOAD,
timestamp, bean, "getProcessCpuLoad", metrics);
addOptionalMetric(SYSTEM_CPU_LOAD,
timestamp, bean, "getSystemCpuLoad", metrics);
}
private void addThreadMetrics(long timestamp, MetricList metrics) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
metrics.add(new Metric(DAEMON_THREAD_COUNT, timestamp, bean.getDaemonThreadCount()));
metrics.add(new Metric(TOTAL_STARTED_THREAD_COUNT,
timestamp, bean.getTotalStartedThreadCount()));
addDetailedThreadMetrics(timestamp, metrics);
}
private void addDetailedThreadMetrics(long timestamp, MetricList metrics) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
if (!bean.isThreadContentionMonitoringSupported()) {
return;
}
if (!bean.isThreadContentionMonitoringEnabled()) {
bean.setThreadContentionMonitoringEnabled(true);
}
ThreadInfo[] threadInfo = bean.dumpAllThreads(false, false);
Arrays.sort(
threadInfo,
(a, b) -> {
long diff = b.getThreadId() - a.getThreadId();
return ((diff == 0L) ? 0 : (diff < 0L) ? -1 : 1);
}
);
long[] stateCounts = new long[VALID_STATES.length];
for (int i = 0; i < stateCounts.length; i++) {
stateCounts[i] = 0L;
}
long blockedCount = 0L;
long blockedTime = 0L;
long waitedCount = 0L;
long waitedTime = 0L;
int l = lastThreadInfos.length - 1;
for (int i = threadInfo.length - 1; i >= 0; i--) {
long currId = threadInfo[i].getThreadId();
while (l >= 0 && lastThreadInfos[l].getThreadId() < currId) {
--l;
}
if (l >= 0 && lastThreadInfos[l].getThreadId() > currId) {
BASE_THREAD_COUNTS[IDX_BLOCKED_COUNT] += lastThreadInfos[l].getBlockedCount();
BASE_THREAD_COUNTS[IDX_BLOCKED_TIME] += lastThreadInfos[l].getBlockedTime();
BASE_THREAD_COUNTS[IDX_WAITED_COUNT] += lastThreadInfos[l].getWaitedCount();
BASE_THREAD_COUNTS[IDX_WAITED_TIME] += lastThreadInfos[l].getWaitedTime();
}
stateCounts[STATE_LOOKUP.get(threadInfo[i].getThreadState())]++;
blockedCount += threadInfo[i].getBlockedCount();
blockedTime += threadInfo[i].getBlockedTime();
waitedCount += threadInfo[i].getWaitedCount();
waitedTime += threadInfo[i].getWaitedTime();
}
metrics.add(new Metric(THREAD_BLOCKED_COUNT,
timestamp, blockedCount + BASE_THREAD_COUNTS[IDX_BLOCKED_COUNT]));
metrics.add(new Metric(THREAD_BLOCKED_TIME,
timestamp, (blockedTime + BASE_THREAD_COUNTS[IDX_BLOCKED_TIME]) / 1000));
metrics.add(new Metric(THREAD_WAITED_COUNT,
timestamp, waitedCount + BASE_THREAD_COUNTS[IDX_WAITED_COUNT]));
metrics.add(new Metric(THREAD_WAITED_TIME,
timestamp, (waitedTime + BASE_THREAD_COUNTS[IDX_WAITED_TIME]) / 1000));
for (int i = 0; i < stateCounts.length; i++) {
metrics.add(new Metric(THREAD_COUNTS[i], timestamp, stateCounts[i]));
}
lastThreadInfos = threadInfo;
}
private void addOptionalMetric(
MonitorConfig config,
long timestamp,
Object obj,
String methodName,
MetricList metrics) {
try {
Method method = obj.getClass().getMethod(methodName);
method.setAccessible(true);
Number value = (Number) method.invoke(obj);
metrics.add(new Metric(config, timestamp, value));
} catch (Exception e) {
final String msg = String.format("failed to get value for %s.%s",
obj.getClass().getName(), methodName);
LOGGER.debug(msg, e);
}
}
private static class MetricList {
private final MetricFilter filter;
private final List list;
MetricList(MetricFilter filter) {
this.filter = filter;
list = new ArrayList<>();
}
public void add(Metric m) {
if (filter.matches(m.getConfig())) {
list.add(m);
}
}
public List getList() {
return list;
}
}
}