JmxMon.java 8.94 KB
package se.lil.jm;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.management.JMX;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;

public class JmxMon {
	String conUser = "system";
	String conPass = "passw0rd";
	String domainName = null;
	String serverName = null;
	String runtimeName = null;
	
	JMXServiceURL url = null;
	JMXConnector jmxc = null;
	MBeanServerConnection mbsc = null;
	
	Thread myThread = null;
	ClassLoader myCL = null;
	
	int getDataCalls = 0;
	int getDataSucess = 0;
	
	HashMap<String, LongDelta> longDeltaMap = new HashMap<String, LongDelta>();
	HashMap<String, DoubleDelta> doubleDeltaMap = new HashMap<String, DoubleDelta>();
	
	private void updateLongDelta (Long timestamp, String name, Long value) {
		LongDelta ld = longDeltaMap.get(name);
		if(ld == null) {
			ld = new LongDelta();
			longDeltaMap.put(name, ld);	
		}
		ld.update(timestamp, value);
	}
	
	private LongDelta getAttributeLongDelta(String name, String attribute) {
		return longDeltaMap.get(name + ":" + attribute);
	}
	
	private void updateDoubleDelta (Long timestamp, String name, Double value) {
		DoubleDelta dd = doubleDeltaMap.get(name);
		if(dd == null) {
			dd = new DoubleDelta();
			doubleDeltaMap.put(name, dd);
		}
		dd.update(timestamp, value);
	}
	
	private DoubleDelta getAttributeDoubleDelta(String name, String attribute) {
		return doubleDeltaMap.get(name + ":" + attribute);
	}
	
	private Object getAttributeValue(String name, String attribute) {
		Object ro = null;
		if(mbsc != null) {
			try {
				ro = mbsc.getAttribute(new ObjectName(name), attribute);
			} catch (Exception e) {
				ro = e;
			}
		}
		return ro;
	}
	
	private void fetchUpdateAttribute(String name, String attribute) {
		String fullName = name + ":" + attribute;
		Object obj = getAttributeValue(name, attribute);
		Long ts = (Long)getAttributeValue("java.lang:type=Runtime", "Uptime");
		if(obj != null) {
			if(obj.getClass().equals(java.lang.Long.class)) {
				updateLongDelta(ts, fullName, (Long)obj);
			}
			if(obj.getClass().equals(java.lang.Integer.class)) {
				Integer i = (Integer)obj;
				updateLongDelta(ts, fullName, i.longValue());
			}
			if(obj.getClass().equals(java.lang.Double.class)) {
				updateDoubleDelta(ts, fullName, (Double)obj);
			}
			if(obj.getClass().equals(java.lang.Float.class)) {
				Float f = (Float)obj;
				updateDoubleDelta(ts, fullName, f.doubleValue());
			}
		}
	}
	
	public int getDataCalled() {
		return getDataCalls;
	}
	
	public int getDataSucceeded() {
		return getDataSucess;
	}
	
	public int getDataFailed() {
		return getDataCalls - getDataSucess;
	}
	
	public String getConString() {
		if(this.url != null) return this.url.toString();
		else return null;
	}
	
	public String getServerName() {
		return serverName;
	}
	
	public String getDomainName() {
		return domainName;
	}
	
	public String getRuntimeName() {
		return runtimeName;
	}
	
	public void open() throws IOException {
		if(url != null) {
			jmxc = JMXConnectorFactory.connect(url);
			mbsc = jmxc.getMBeanServerConnection();
			domainName = mbsc.getDefaultDomain();
			Object obj = getAttributeValue("java.lang:type=Runtime", "Name");
			if(obj.getClass().equals(java.lang.String.class)) {
				runtimeName = (String)obj;
			}
			obj = getAttributeValue("java.lang:type=Runtime", "SystemProperties");
			TabularData td = (TabularData)obj;
			for (Object o : td.values()) {
				CompositeData d = (CompositeData)o;
				if(d.get("key").toString().equals("weblogic.Name")) serverName = d.get("value").toString();
			}
		}
	}
	
	public void open(String serviceURL) throws IOException, MalformedURLException {
		url = new JMXServiceURL(serviceURL);
		open();
	}
	
	public void close() throws IOException {
		if(jmxc != null) jmxc.close();
		jmxc = null;
		mbsc = null;
	}
	
	long lastRTns = 0;
	public long getLastRTms() {
		return lastRTns / (1000 * 1000);
	}
	
	long lastFetchTSns = 0;
	public boolean getData(long ageTs) throws Throwable {
		if (getAgeTs() > ageTs ) return getData();
		else return false;
	}
	
	public long getAgeTs() {
		if(lastFetchTSns > 0) return (System.nanoTime() - lastFetchTSns)/(1000*1000*1000);
		else return 0;
	}
	
	Lock lock = new ReentrantLock();
	
	public boolean getData() throws Throwable {
		// Start thread safe
 		// Try to get a lock
 		boolean haveLock = lock.tryLock();
		if( haveLock == false) {
			// We could not get the lock, someone else is updating. Wait for it to complete by waiting for a lock, then unlock and return.
			try {
				lock.lock();
			} finally {
				lock.unlock();
			}
			return false;
		}
		// We do have the lock. Do the rest in a try catch everything and if we catch anything, re throw the catch but always release the lock.
		try {
			long startTSns = System.nanoTime();
	 		getDataCalls++;
	 		// Do the update of data
	 		numCpus = (Integer)getAttributeValue("java.lang:type=OperatingSystem", "AvailableProcessors");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "ProcessCpuTime");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "OpenFileDescriptorCount");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "MaxFileDescriptorCount");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "TotalSwapSpaceSize");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "FreeSwapSpaceSize");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "FreePhysicalMemorySize");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "TotalPhysicalMemorySize");
	 		fetchUpdateAttribute("java.lang:type=OperatingSystem", "SystemLoadAverage");
	 		fetchUpdateAttribute("java.lang:type=Threading", "ThreadCount");
	 		fetchUpdateAttribute("java.lang:type=ClassLoading", "LoadedClassCount");
	 		// Finished updating data
	 		getDataSucess++;
			lastFetchTSns = System.nanoTime();
			lastRTns = lastFetchTSns - startTSns;
			return true;
		} catch (Throwable e) {
			throw (e);
		} finally {
			lock.unlock();
		}
		// End thread safe
	}
	
	//NUM_CPUS
	int numCpus = 0;
	public long getNumberOfCPUs() {
		return numCpus;
	}
	
	public long getLoadedClassCount() {
		LongDelta ld = getAttributeLongDelta("java.lang:type=ClassLoading", "LoadedClassCount");
		return ld.getCurrentValue();
	}
	
	public double getCPUPercent() {
		LongDelta ld = getAttributeLongDelta("java.lang:type=OperatingSystem", "ProcessCpuTime");
		double cpuDeltaMS = (double)ld.getDelta() / (1000D*1000D);
		double spentMS = ld.getMilliSeconds();
		double perCPUMS = cpuDeltaMS / (double)numCpus;
		double cpuPct = (perCPUMS / spentMS) * 100D;
		return cpuPct;
	}
	
	public double getAverageLoad() {
		DoubleDelta dd = getAttributeDoubleDelta("java.lang:type=OperatingSystem", "SystemLoadAverage");
		return dd.getCurrentValue();
	}
	
	public double getAverageLoadPerCpu() {
		DoubleDelta dd = getAttributeDoubleDelta("java.lang:type=OperatingSystem", "SystemLoadAverage");
		return dd.getCurrentValue()/(double)numCpus;
	}
	
	public long getThreads() {
		LongDelta ld = getAttributeLongDelta("java.lang:type=Threading", "ThreadCount");
		return ld.getCurrentValue();
	}
	
	public double getSystemMemoryPercentUsed() {
		LongDelta ldf = getAttributeLongDelta("java.lang:type=OperatingSystem", "FreePhysicalMemorySize");
		LongDelta ldt = getAttributeLongDelta("java.lang:type=OperatingSystem", "TotalPhysicalMemorySize");
		double free = ldf.getCurrentValue();
		double total = ldt.getCurrentValue();
		return ((total - free)/(total)) * 100D;
	}
	
	public double getSystemSwapPercentUsed() {
		LongDelta ldf = getAttributeLongDelta("java.lang:type=OperatingSystem", "FreeSwapSpaceSize");
		LongDelta ldt = getAttributeLongDelta("java.lang:type=OperatingSystem", "TotalSwapSpaceSize");
		double free = ldf.getCurrentValue();
		double total = ldt.getCurrentValue();
		return ((total - free)/(total)) * 100D;
	}
	
	public double getSystemFileDescriptorsPercentUsed() {
		LongDelta ldo = getAttributeLongDelta("java.lang:type=OperatingSystem", "OpenFileDescriptorCount");
		LongDelta ldm = getAttributeLongDelta("java.lang:type=OperatingSystem", "MaxFileDescriptorCount");
		double open = ldo.getCurrentValue();
		double max = ldm.getCurrentValue();
		return (open/max) * 100D;
	}
	
	public JmxMon() {
	}
	
	public JmxMon(String serviceURL) throws MalformedURLException {
		this.url = new JMXServiceURL(serviceURL);
	}
}