blob: cc1af537bdfe97bc9c6ffe936d353893bb244c05 [file] [log] [blame]
/**
* 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 org.apache.aurora.common.stats;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadMXBean;
import java.util.Map;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import org.apache.aurora.common.quantity.Amount;
import org.apache.aurora.common.quantity.Data;
import org.apache.aurora.common.quantity.Time;
/**
* Convenience class to export statistics about the JVM.
*/
public class JvmStats {
private static final long BYTES_PER_MB = Amount.of(1L, Data.MB).as(Data.BYTES);
private static final double SECS_PER_NANO =
((double) 1) / Amount.of(1L, Time.SECONDS).as(Time.NANOSECONDS);
private JvmStats() {
// Utility class.
}
/**
* Exports stats related to the JVM and runtime environment.
*/
public static void export() {
final OperatingSystemMXBean osMbean = ManagementFactory.getOperatingSystemMXBean();
if (osMbean instanceof com.sun.management.OperatingSystemMXBean) {
final com.sun.management.OperatingSystemMXBean sunOsMbean =
(com.sun.management.OperatingSystemMXBean) osMbean;
Stats.exportAll(
ImmutableList.<Stat<? extends Number>>builder()
.add(new StatImpl<Long>("system_free_physical_memory_mb") {
@Override public Long read() {
return sunOsMbean.getFreePhysicalMemorySize() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("system_free_swap_mb") {
@Override public Long read() {
return sunOsMbean.getFreeSwapSpaceSize() / BYTES_PER_MB;
}
})
.add(
Rate.of(
new StatImpl<Long>("process_cpu_time_nanos") {
@Override public Long read() {
return sunOsMbean.getProcessCpuTime();
}
}).withName("process_cpu_cores_utilized").withScaleFactor(SECS_PER_NANO).build())
.build());
}
if (osMbean instanceof com.sun.management.UnixOperatingSystemMXBean) {
final com.sun.management.UnixOperatingSystemMXBean unixOsMbean =
(com.sun.management.UnixOperatingSystemMXBean) osMbean;
Stats.exportAll(ImmutableList.<Stat<? extends Number>>builder()
.add(new StatImpl<Long>("process_max_fd_count") {
@Override public Long read() { return unixOsMbean.getMaxFileDescriptorCount(); }
}).add(new StatImpl<Long>("process_open_fd_count") {
@Override public Long read() { return unixOsMbean.getOpenFileDescriptorCount(); }
}).build());
}
final Runtime runtime = Runtime.getRuntime();
final ClassLoadingMXBean classLoadingBean = ManagementFactory.getClassLoadingMXBean();
final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
final ThreadMXBean threads = ManagementFactory.getThreadMXBean();
final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
Stats.exportAll(ImmutableList.<Stat<? extends Number>>builder()
.add(new StatImpl<Long>("jvm_time_ms") {
@Override public Long read() { return System.currentTimeMillis(); }
})
.add(new StatImpl<Integer>("jvm_available_processors") {
@Override public Integer read() { return runtime.availableProcessors(); }
})
.add(new StatImpl<Long>("jvm_memory_free_mb") {
@Override public Long read() { return runtime.freeMemory() / BYTES_PER_MB; }
})
.add(new StatImpl<Long>("jvm_memory_max_mb") {
@Override public Long read() { return runtime.maxMemory() / BYTES_PER_MB; }
})
.add(new StatImpl<Long>("jvm_memory_mb_total") {
@Override public Long read() { return runtime.totalMemory() / BYTES_PER_MB; }
})
.add(new StatImpl<Integer>("jvm_class_loaded_count") {
@Override public Integer read() { return classLoadingBean.getLoadedClassCount(); }
})
.add(new StatImpl<Long>("jvm_class_total_loaded_count") {
@Override public Long read() { return classLoadingBean.getTotalLoadedClassCount(); }
})
.add(new StatImpl<Long>("jvm_class_unloaded_count") {
@Override public Long read() { return classLoadingBean.getUnloadedClassCount(); }
})
.add(new StatImpl<Long>("jvm_gc_collection_time_ms") {
@Override public Long read() {
long collectionTimeMs = 0;
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
collectionTimeMs += bean.getCollectionTime();
}
return collectionTimeMs;
}
})
.add(new StatImpl<Long>("jvm_gc_collection_count") {
@Override public Long read() {
long collections = 0;
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
collections += bean.getCollectionCount();
}
return collections;
}
})
.add(new StatImpl<Long>("jvm_memory_heap_mb_used") {
@Override public Long read() {
return memoryBean.getHeapMemoryUsage().getUsed() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_memory_heap_mb_committed") {
@Override public Long read() {
return memoryBean.getHeapMemoryUsage().getCommitted() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_memory_heap_mb_max") {
@Override public Long read() {
return memoryBean.getHeapMemoryUsage().getMax() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_memory_non_heap_mb_used") {
@Override public Long read() {
return memoryBean.getNonHeapMemoryUsage().getUsed() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_memory_non_heap_mb_committed") {
@Override public Long read() {
return memoryBean.getNonHeapMemoryUsage().getCommitted() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_memory_non_heap_mb_max") {
@Override public Long read() {
return memoryBean.getNonHeapMemoryUsage().getMax() / BYTES_PER_MB;
}
})
.add(new StatImpl<Long>("jvm_uptime_secs") {
@Override public Long read() { return runtimeMXBean.getUptime() / 1000; }
})
.add(new StatImpl<Double>("system_load_avg") {
@Override public Double read() { return osMbean.getSystemLoadAverage(); }
})
.add(new StatImpl<Integer>("jvm_threads_peak") {
@Override public Integer read() { return threads.getPeakThreadCount(); }
})
.add(new StatImpl<Long>("jvm_threads_started") {
@Override public Long read() { return threads.getTotalStartedThreadCount(); }
})
.add(new StatImpl<Integer>("jvm_threads_daemon") {
@Override public Integer read() { return threads.getDaemonThreadCount(); }
})
.add(new StatImpl<Integer>("jvm_threads_active") {
@Override public Integer read() { return threads.getThreadCount(); }
})
.build());
// Export per memory pool gc time and cycle count like Ostrich
// This is based on code in Bridcage: https://cgit.twitter.biz/birdcage/tree/ \
// ostrich/src/main/scala/com/twitter/ostrich/stats/StatsCollection.scala
Stats.exportAll(Iterables.transform(ManagementFactory.getGarbageCollectorMXBeans(),
gcMXBean -> new StatImpl<Long>(
"jvm_gc_" + Stats.normalizeName(gcMXBean.getName()) + "_collection_count") {
@Override public Long read() {
return gcMXBean.getCollectionCount();
}
}
));
Stats.exportAll(Iterables.transform(ManagementFactory.getGarbageCollectorMXBeans(),
gcMXBean -> new StatImpl<Long>(
"jvm_gc_" + Stats.normalizeName(gcMXBean.getName()) + "_collection_time_ms") {
@Override public Long read() {
return gcMXBean.getCollectionTime();
}
}
));
Stats.exportString(
new StatImpl<String>("jvm_input_arguments") {
@Override public String read() {
return runtimeMXBean.getInputArguments().toString();
}
}
);
for (final String property : System.getProperties().stringPropertyNames()) {
Stats.exportString(
new StatImpl<String>("jvm_prop_" + Stats.normalizeName(property)) {
@Override public String read() { return System.getProperty(property); }
});
}
for (final Map.Entry<String, String> environmentVariable : System.getenv().entrySet()) {
Stats.exportString(
new StatImpl<String>("system_env_" + Stats.normalizeName(environmentVariable.getKey())) {
@Override public String read() { return environmentVariable.getValue(); }
});
}
}
}