/** * Copyright (C) 2013 Arman Gal * * 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.clevermore.monitor.server.utils; import static java.lang.management.ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE; import static java.lang.management.ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE; import static java.lang.management.ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; import static java.lang.management.ManagementFactory.RUNTIME_MXBEAN_NAME; import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy; import java.io.IOException; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; import java.lang.management.RuntimeMXBean; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import org.clevermore.monitor.server.dao.entities.ServerStatsEntity; import org.clevermore.monitor.server.model.ServerStatus; import org.clevermore.monitor.server.services.alert.IAlertService; import org.clevermore.monitor.server.services.persistence.IPersistenceService; import org.clevermore.monitor.shared.alert.AlertType; import org.clevermore.monitor.shared.runtime.GCHistory; import org.clevermore.monitor.shared.runtime.MemoryState; import org.clevermore.monitor.shared.runtime.RuntimeInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.inject.Inject; import com.sun.management.OperatingSystemMXBean; /** * Using the java.lang.management API to monitor the memory usage and garbage collection statistics. */ @SuppressWarnings("restriction") public abstract class AbstractJMXGeneralStats<SS extends ServerStatus> implements IJMXGeneralStats<SS> { private static Logger logger = LoggerFactory.getLogger("JMXGeneralStats"); @Inject private IAlertService<SS> alertService; @Inject private IPersistenceService persistenceService; public AbstractJMXGeneralStats() {} private List<GCHistory> getGcHistory(List<GarbageCollectorMXBean> gcmbeans) { final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = DATE_FORMAT.format(new Date()); List<GCHistory> retList = new ArrayList<GCHistory>(0); for (GarbageCollectorMXBean gc : gcmbeans) { String name = gc.getName() + "," + Arrays.toString(gc.getMemoryPoolNames()); retList.add(new GCHistory(name, gc.getCollectionCount(), gc.getCollectionTime(), time)); } return retList; } private LinkedList<MemoryState> getMemoryState(List<MemoryPoolMXBean> pools) { LinkedList<MemoryState> list = new LinkedList<MemoryState>(); long div = 1024; // to store values in KBytes try { for (MemoryPoolMXBean p : pools) { MemoryUsage u = p.getUsage(); list.add(new MemoryState(p.getName(), u.getUsed() / div, u.getCommitted() / div, u.getMax() / div, p.getType().equals(MemoryType.HEAP))); } return list; } catch (Throwable e) { logger.error(e.getMessage(), e); return list; } } /* * (non-Javadoc) * @see * org.clevermore.monitor.server.utils.IJMXGeneralStats#getMemoryStats(org.clevermore.monitor.server.model * . ServerStatus, java.util.Date) */ @Override public void getMemoryStats(SS serverStataus, Date executionDate) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException, MalformedObjectNameException { final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###.##"); MBeanServerConnection mbsc = serverStataus.getConnector().getMBeanServerConnection(); RuntimeMXBean rmbean = newPlatformMXBeanProxy(mbsc, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); MemoryMXBean mxBean = newPlatformMXBeanProxy(mbsc, ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class); MemoryUsage heapMemoryUsage = mxBean.getHeapMemoryUsage(); ObjectName poolName = null; ObjectName gcName = null; List<GarbageCollectorMXBean> gcmbeans = new ArrayList<GarbageCollectorMXBean>(); List<MemoryPoolMXBean> pools = new ArrayList<MemoryPoolMXBean>(); try { poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // should not reach here assert (false); } Set<ObjectName> mbeans = mbsc.queryNames(poolName, null); if (mbeans != null) { Iterator<ObjectName> iterator = mbeans.iterator(); while (iterator.hasNext()) { ObjectName objName = iterator.next(); MemoryPoolMXBean p = newPlatformMXBeanProxy(mbsc, objName.getCanonicalName(), MemoryPoolMXBean.class); pools.add(p); } } mbeans = mbsc.queryNames(gcName, null); if (mbeans != null) { Iterator<ObjectName> iterator = mbeans.iterator(); while (iterator.hasNext()) { ObjectName objName = iterator.next(); GarbageCollectorMXBean gc = newPlatformMXBeanProxy(mbsc, objName.getCanonicalName(), GarbageCollectorMXBean.class); gcmbeans.add(gc); } } LinkedList<MemoryState> memoryState = getMemoryState(pools); serverStataus.setUptime(rmbean.getUptime()); org.clevermore.monitor.shared.runtime.MemoryUsage mu = serverStataus.updateMemoryUsage(heapMemoryUsage.getInit(), heapMemoryUsage.getUsed(), heapMemoryUsage.getCommitted(), heapMemoryUsage.getMax(), memoryState); for (MemoryState ms : memoryState) { double max = (double) ms.getMax(); double usage = (double) ms.getUsed() * 100d / max; if (max != 0 && ((usage > serverStataus.getServerGroup().getNotHeapMemorySpaceUsage() && !ms.isHeap()) || (usage > serverStataus.getServerGroup() .getHeapMemorySpaceUsage() && ms.isHeap()))) { alertService.createAndAddAlert("MemorySpace: " + ms.getName() + " usage:" + DECIMAL_FORMAT.format(usage) + "%", ms.toString(), serverStataus.getServerConfig().getServerCode(), serverStataus.getServerConfig().getName(), new Date().getTime(), AlertType.MEMORY_SPACE, serverStataus); } } // check the groups settings if (mu.getPercentage() > serverStataus.getServerGroup().getMemoryUsage()) { alertService.createAndAddAlert("Memory Usage: " + DECIMAL_FORMAT.format(mu.getPercentage()) + "%", mu.toString(), serverStataus.getServerConfig().getServerCode(), serverStataus.getServerConfig().getName(), new Date().getTime(), AlertType.MEMORY, serverStataus); } List<GCHistory> gcHistoryList = getGcHistory(gcmbeans); for (GCHistory gch : gcHistoryList) { long lastColleactionTime = serverStataus.updateGCHistory(gch); if (lastColleactionTime > serverStataus.getServerGroup().getGcTime()) { alertService.createAndAddAlert("GC too long: " + lastColleactionTime + " ms", "", serverStataus.getServerConfig().getServerCode(), serverStataus.getServerConfig().getName(), new Date().getTime(), AlertType.GC, serverStataus); } } OperatingSystemMXBean operatingSystemMXBean = newPlatformMXBeanProxy(mbsc, ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); double load = serverStataus.updateCPUutilization(operatingSystemMXBean.getProcessCpuTime(), operatingSystemMXBean.getAvailableProcessors(), System.nanoTime(), operatingSystemMXBean.getSystemLoadAverage()); // check the groups settings if (load > serverStataus.getServerGroup().getCpuLoad()) { alertService.createAndAddAlert("CPU Alert:" + DECIMAL_FORMAT.format(load) + "%", "", serverStataus.getServerConfig().getServerCode(), serverStataus.getServerConfig().getName(), new Date().getTime(), AlertType.CPU, serverStataus); } persistenceService.saveServerStat(new ServerStatsEntity(executionDate.getTime(), serverStataus.getUpTime(), serverStataus.getServerConfig().getServerCode(), serverStataus.getServerConfig().getName(), serverStataus.getCpuUtilization().getLastPercent().getUsage(), serverStataus.getCpuUtilization().getLastPercent().getSystemLoadAverage(), serverStataus.getLastMemoryUsage().getCommitted(), serverStataus.getLastMemoryUsage().getInit(), serverStataus.getLastMemoryUsage().getMax(), serverStataus.getLastMemoryUsage().getUsed(), serverStataus.getMemoryState(), serverStataus.isConnected())); } /* * (non-Javadoc) * @see * org.clevermore.monitor.server.utils.IJMXGeneralStats#getRuntimeInfo(org.clevermore.monitor.server.model * . ServerStatus) */ @Override public RuntimeInfo getRuntimeInfo(SS serverStataus) throws IOException { MBeanServerConnection mbsc = serverStataus.getConnector().getMBeanServerConnection(); RuntimeMXBean rmbean = newPlatformMXBeanProxy(mbsc, RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); OperatingSystemMXBean osbean = newPlatformMXBeanProxy(mbsc, OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); HashMap<String, String> map = new HashMap<String, String>(rmbean.getSystemProperties()); RuntimeInfo rti = new RuntimeInfo(rmbean.getBootClassPath(), rmbean.getClassPath(), rmbean.getInputArguments(), rmbean.getLibraryPath(), rmbean.getName(), map, osbean.getAvailableProcessors(), osbean.getSystemLoadAverage()); return rti; } }