/*- * << * UAVStack * == * Copyright (C) 2016 - 2017 UAVStack * == * 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.creditease.monitor.handlers; import java.lang.management.ClassLoadingMXBean; 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.ThreadMXBean; import java.text.DecimalFormat; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import com.creditease.agent.helpers.JVMToolHelper; import com.creditease.agent.helpers.NetworkHelper; import com.creditease.agent.helpers.ReflectionHelper; import com.creditease.monitor.UAVServer; import com.creditease.monitor.captureframework.spi.CaptureConstants; import com.creditease.monitor.captureframework.spi.CaptureContext; import com.creditease.monitor.captureframework.spi.MonitorElemCapHandler; import com.creditease.monitor.captureframework.spi.MonitorElement; import com.creditease.monitor.captureframework.spi.MonitorElementInstance; public class JVMStateCapHandler implements MonitorElemCapHandler { private static final Set<String> minorGC = new HashSet<String>(); private static final Set<String> fullGC = new HashSet<String>(); static { // Oracle (Sun) HotSpot // -XX:+UseSerialGC minorGC.add("Copy"); // -XX:+UseParNewGC minorGC.add("ParNew"); // -XX:+UseParallelGC minorGC.add("PS Scavenge"); // Oracle (BEA) JRockit // -XgcPrio:pausetime minorGC.add("Garbage collection optimized for short pausetimes Young Collector"); // -XgcPrio:throughput minorGC.add("Garbage collection optimized for throughput Young Collector"); // -XgcPrio:deterministic minorGC.add("Garbage collection optimized for deterministic pausetimes Young Collector"); // -XX:+UseG1GC minorGC.add("G1 Young Generation"); // Oracle (Sun) HotSpot // -XX:+UseSerialGC fullGC.add("MarkSweepCompact"); // -XX:+UseParallelGC and (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting) fullGC.add("PS MarkSweep"); // -XX:+UseConcMarkSweepGC fullGC.add("ConcurrentMarkSweep"); // -XX:+UseG1GC fullGC.add("G1 Old Generation"); // Oracle (BEA) JRockit // -XgcPrio:pausetime fullGC.add("Garbage collection optimized for short pausetimes Old Collector"); // -XgcPrio:throughput fullGC.add("Garbage collection optimized for throughput Old Collector"); // -XgcPrio:deterministic fullGC.add("Garbage collection optimized for deterministic pausetimes Old Collector"); } private DecimalFormat formatter = new DecimalFormat("00.0"); @Override public void preCap(MonitorElement elem, CaptureContext context) { // Do nothing but must pass sonar check } @Override public void doCap(MonitorElement elem, CaptureContext context) { if (CaptureConstants.MOELEM_JVMSTATE.equals(elem.getMonitorElemId())) { Integer port = (Integer) UAVServer.instance().getServerInfo(CaptureConstants.INFO_APPSERVER_LISTEN_PORT); String serverJVMid = "http://" + NetworkHelper.getLocalIP() + ":" + port; MonitorElementInstance instance = elem.getInstance(serverJVMid); // heap readHeapUsage(instance); // no heap readNonHeapUsage(instance); // thread readThreadUsage(instance); // heap & code mem pool readHeapPoolUsage(instance); // gc readGCUsage(instance); // classes usage readClassLoadUsage(instance); // cpu readCPUUsage(instance); // read customized metrics readCustomizedMetrics(instance); } } /** * read Customized Metrics * * @param instance */ private void readCustomizedMetrics(MonitorElementInstance instance) { Enumeration<?> enumeration = System.getProperties().propertyNames(); while (enumeration.hasMoreElements()) { String name = (String) enumeration.nextElement(); int moIndex = name.indexOf("[email protected]"); if (moIndex != 0) { continue; } String[] metrics = name.split("@"); // add monitor data String metricValStr = System.getProperties().getProperty(name); try { Double d = Double.parseDouble(metricValStr); instance.setValue(metrics[1], d); } catch (Exception e) { // ignore } } } private void readGCUsage(MonitorElementInstance instance) { List<GarbageCollectorMXBean> gcmbList = ManagementFactory.getGarbageCollectorMXBeans(); for (GarbageCollectorMXBean gcmb : gcmbList) { String name = gcmb.getName(); String gcName = null; if (minorGC.contains(name)) { gcName = "mgc"; } else if (fullGC.contains(name)) { gcName = "fgc"; } if (gcName == null) { continue; } instance.setValue(gcName + "_count", gcmb.getCollectionCount()); instance.setValue(gcName + "_time", gcmb.getCollectionTime()); } } private void readHeapPoolUsage(MonitorElementInstance instance) { List<MemoryPoolMXBean> pmbList = ManagementFactory.getMemoryPoolMXBeans(); /*for (MemoryPoolMXBean mpmb : pmbList) { String jvmMemPoolName = getHeapPoolName(mpmb.getName().trim()); MemoryUsage mu = mpmb.getUsage(); instance.setValue(jvmMemPoolName + "_use", mu.getUsed()); instance.setValue(jvmMemPoolName + "_commit", mu.getCommitted()); instance.setValue(jvmMemPoolName + "_max", mu.getMax()); instance.setValue(jvmMemPoolName + "_init", mu.getInit()); }*/ Set<String> addedSet = new HashSet<String>(); for (MemoryPoolMXBean mpmb : pmbList) { String jvmMemPoolName = getHeapPoolName(mpmb.getName().trim()); MemoryUsage mu = mpmb.getUsage(); if(addedSet.contains(jvmMemPoolName)) { instance.setValue(jvmMemPoolName + "_use", (Long)instance.getValue(jvmMemPoolName + "_use") + mu.getUsed()); instance.setValue(jvmMemPoolName + "_commit", (Long)instance.getValue(jvmMemPoolName + "_commit") + mu.getCommitted()); instance.setValue(jvmMemPoolName + "_max", (Long)instance.getValue(jvmMemPoolName + "_max") + mu.getMax()); instance.setValue(jvmMemPoolName + "_init", (Long)instance.getValue(jvmMemPoolName + "_init") + mu.getInit()); }else { addedSet.add(jvmMemPoolName); instance.setValue(jvmMemPoolName + "_use", mu.getUsed()); instance.setValue(jvmMemPoolName + "_commit", mu.getCommitted()); instance.setValue(jvmMemPoolName + "_max", mu.getMax()); instance.setValue(jvmMemPoolName + "_init", mu.getInit()); } } } private String getHeapPoolName(String poolName) { String jvmMemPoolName = poolName.toLowerCase(); if (jvmMemPoolName.indexOf("code") > -1) { return "code"; } else if (jvmMemPoolName.indexOf("old") > -1 || jvmMemPoolName.indexOf("tenured") > -1) { return "old"; } else if (jvmMemPoolName.indexOf("eden") > -1) { return "eden"; } else if (jvmMemPoolName.indexOf("survivor") > -1) { return "surv"; } else if (jvmMemPoolName.indexOf("perm") > -1 || jvmMemPoolName.indexOf("metaspace") > -1) { return "perm"; } else if (jvmMemPoolName.indexOf("compressed") > -1 && jvmMemPoolName.indexOf("class") > -1) { return "compressed"; } return jvmMemPoolName; } private void readClassLoadUsage(MonitorElementInstance instance) { ClassLoadingMXBean clmb = ManagementFactory.getClassLoadingMXBean(); instance.setValue("class_total", clmb.getTotalLoadedClassCount()); instance.setValue("class_load", clmb.getLoadedClassCount()); instance.setValue("class_unload", clmb.getUnloadedClassCount()); } protected void readHeapUsage(MonitorElementInstance instance) { MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); instance.setValue("heap_use", mu.getUsed()); instance.setValue("heap_commit", mu.getCommitted()); instance.setValue("heap_max", mu.getMax()); instance.setValue("heap_init", mu.getInit()); } protected void readNonHeapUsage(MonitorElementInstance instance) { MemoryUsage mu = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); instance.setValue("noheap_use", mu.getUsed()); instance.setValue("noheap_commit", mu.getCommitted()); instance.setValue("noheap_max", mu.getMax()); instance.setValue("noheap_init", mu.getInit()); } protected void readThreadUsage(MonitorElementInstance inst) { ThreadMXBean tmb = ManagementFactory.getThreadMXBean(); inst.setValue("thread_live", tmb.getThreadCount()); inst.setValue("thread_daemon", tmb.getDaemonThreadCount()); inst.setValue("thread_peak", tmb.getPeakThreadCount()); inst.setValue("thread_started", tmb.getTotalStartedThreadCount()); } protected void readCPUUsage(MonitorElementInstance inst) { OperatingSystemMXBean osMBean = ManagementFactory.getOperatingSystemMXBean(); Double procCPU = (Double) ReflectionHelper.invoke("com.sun.management.OperatingSystemMXBean", osMBean, "getProcessCpuLoad", null, null); Double systemCPU = (Double) ReflectionHelper.invoke("com.sun.management.OperatingSystemMXBean", osMBean, "getSystemCpuLoad", null, null); if (procCPU == null) { procCPU = JVMToolHelper.getProcessCpuUtilization(); systemCPU = -1D; } inst.setValue("cpu_p", Double.valueOf(formatter.format(procCPU * 100))); inst.setValue("cpu_s", Double.valueOf(formatter.format(systemCPU * 100))); } @Override public void preStore(MonitorElementInstance instance) { // Do nothing but must pass sonar check } }