/** * Copyright 2008 the original author or authors. * * 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 net.sf.katta.node.monitor; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.lang.management.OperatingSystemMXBean; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; import net.sf.katta.protocol.InteractionProtocol; import org.I0Itec.zkclient.ExceptionUtil; import org.apache.log4j.Logger; public class JmxMonitor implements IMonitor { protected final static Logger LOG = Logger.getLogger(JmxMonitor.class); protected InteractionProtocol _protocol; protected JmxMonitorThread _thread; protected String _serverId; @Override public void startMonitoring(String serverId, InteractionProtocol protocol) { _protocol = protocol; if (serverId == null || _protocol == null) { throw new IllegalArgumentException("parameters can't be null"); } _serverId = serverId; _thread = new JmxMonitorThread(); _thread.start(); } @Override public void stopMonitoring() { _thread.interrupt(); try { _thread.join(); } catch (InterruptedException e) { ExceptionUtil.retainInterruptFlag(e); } } class JmxMonitorThread extends Thread { public void run() { // create the node for the first time... try { while (true) { MetricsRecord metrics = new MetricsRecord(_serverId); gatherMetrics(metrics); _protocol.setMetric(_serverId, metrics); sleep(1000); } } catch (InterruptedException e) { ExceptionUtil.retainInterruptFlag(e); } LOG.info("jmx monitor stopped"); } private void gatherMetrics(MetricsRecord metrics) { // there is no good way to get underlaying system matrics . Only // com.sun.management.OperatingSystemMXBean provides some basic // information. See: // http://nadeausoftware.com/articles/2008/03/java%5Ftip%5Fhow%5Fget%5Fcpu%5Fand%5Fuser%5Ftime%5Fbenchmarking#UsingaSuninternalclasstogetJVMCPUtime try { // operation system OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); Long processCpuTime = getValue(operatingSystemMXBean, "getProcessCpuTime"); metrics.addValue("ProcessCpuTime", processCpuTime, System.currentTimeMillis()); Long totalSwapSpaceSize = getValue(operatingSystemMXBean, "getTotalSwapSpaceSize"); metrics.addValue("TotalSwapSpaceSize", totalSwapSpaceSize, System.currentTimeMillis()); Long freeSwapSpaceSize = getValue(operatingSystemMXBean, "getFreeSwapSpaceSize"); metrics.addValue("FreeSwapSpaceSize", freeSwapSpaceSize, System.currentTimeMillis()); Long freePhysicalMemorySize = getValue(operatingSystemMXBean, "getFreePhysicalMemorySize"); metrics.addValue("FreePhysicalMemorySize", freePhysicalMemorySize, System.currentTimeMillis()); Long totalPhysicalMemorySize = getValue(operatingSystemMXBean, "getTotalPhysicalMemorySize"); metrics.addValue("TotalPhysicalMemorySize", totalPhysicalMemorySize, System.currentTimeMillis()); Long committedVirtualMemorySize = getValue(operatingSystemMXBean, "getCommittedVirtualMemorySize"); metrics.addValue("CommittedVirtualMemorySize", committedVirtualMemorySize, System.currentTimeMillis()); // memory MemoryUsage heapMemoryUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); metrics.addValue("heapMemoryUsageMax", heapMemoryUsage.getMax(), System.currentTimeMillis()); metrics.addValue("heapMemoryUsageUsed", heapMemoryUsage.getUsed(), System.currentTimeMillis()); metrics.addValue("heapMemoryUsageInit", heapMemoryUsage.getInit(), System.currentTimeMillis()); metrics.addValue("heapMemoryUsageCommited", heapMemoryUsage.getCommitted(), System.currentTimeMillis()); MemoryUsage nonHeapMemoryUsage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); metrics.addValue("nonHeapMemoryUsageMax", nonHeapMemoryUsage.getMax(), System.currentTimeMillis()); metrics.addValue("nonHeapMemoryUsageUsed", nonHeapMemoryUsage.getUsed(), System.currentTimeMillis()); metrics.addValue("nonHeapMemoryUsageInit", nonHeapMemoryUsage.getInit(), System.currentTimeMillis()); metrics.addValue("nonHeapMemoryUsageCommited", nonHeapMemoryUsage.getCommitted(), System.currentTimeMillis()); // Garbage collection List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans(); for (GarbageCollectorMXBean bean : garbageCollectorMXBeans) { String gcName = bean.getName(); long collectionCount = bean.getCollectionCount(); metrics.addValue("collectionCount_" + gcName, collectionCount, System.currentTimeMillis()); long collectionTime = bean.getCollectionTime(); metrics.addValue("collectionTime_" + gcName, collectionTime, System.currentTimeMillis()); } // File System // TODO sg 10/03/09 We should add diskfree as well, but we need to // know which // disks we talk about. This brings in the problem that currently we // can only use one not multiple disks for the shards. So lets fix // this as soon we fix this other problem :/ } catch (Exception e) { LOG.error("Unable to retrieve metrics values:", e); } } private Long getValue(OperatingSystemMXBean operatingSystemMXBean, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method method = operatingSystemMXBean.getClass().getMethod(methodName, new Class[0]); method.setAccessible(true); return (Long) method.invoke(operatingSystemMXBean); } } }