001 package biz.hammurapi.metrics.jmx; 002 003 import java.util.Date; 004 import java.util.HashMap; 005 import java.util.Map; 006 007 import javax.management.MBeanServer; 008 import javax.management.MalformedObjectNameException; 009 import javax.management.ObjectName; 010 import javax.management.StandardMBean; 011 012 import biz.hammurapi.metrics.MeasurementCategoryFactory; 013 import biz.hammurapi.metrics.MeasurementConsumer; 014 import biz.hammurapi.metrics.SimpleSlice; 015 import biz.hammurapi.metrics.Slice; 016 017 public abstract class JmxMeasurementCategoryFactory extends MeasurementCategoryFactory { 018 private String category; 019 020 public void setCategory(String category) { 021 this.category = category; 022 } 023 024 private Map measurementConsumers = new HashMap(); 025 026 private static class JmxSliceImpl implements JmxSlice { 027 028 private String name; 029 private Slice master; 030 031 public JmxSliceImpl(String name) { 032 this.name = name; 033 reset(); 034 } 035 036 public double getAverage() { 037 return master.getAvg(); 038 } 039 040 public double getDeviation() { 041 return master.getDeviation(); 042 } 043 044 public Date getFrom() { 045 return new Date(master.getFrom()); 046 } 047 048 public double getMax() { 049 return master.getMax(); 050 } 051 052 public double getMin() { 053 return master.getMin(); 054 } 055 056 public int getNumber() { 057 return master.getNumber(); 058 } 059 060 public Date getTo() { 061 return new Date(master.getTo()); 062 } 063 064 public double getTotal() { 065 return master.getTotal(); 066 } 067 068 public void reset() { 069 master = new SimpleSlice(name); 070 } 071 072 public Slice getMaster() { 073 return master; 074 } 075 076 } 077 078 public synchronized MeasurementConsumer getMeasurementConsumer(final String categoryName) { 079 MBeanServer mBeanServer = getMBeanServer(); 080 if (mBeanServer!=null 081 && (category==null || category.equals(categoryName) || (categoryName!=null && categoryName.startsWith(category+".")))) { 082 MeasurementConsumer ret = (MeasurementConsumer) measurementConsumers.get(categoryName); 083 if (ret==null) { 084 ret = new MeasurementConsumer() { 085 private Map sliceMap = new HashMap(); 086 087 public synchronized void addMeasurement(String name, double value, long time) { 088 JmxSliceImpl slice = (JmxSliceImpl) sliceMap.get(name); 089 if (slice==null) { 090 slice=new JmxSliceImpl(name); 091 sliceMap.put(name, slice); 092 093 try { 094 MBeanServer mbs = getMBeanServer(); 095 if (mbs!=null) { 096 mbs.registerMBean(new StandardMBean(slice, JmxSlice.class), objectName(categoryName, name)); 097 } 098 } catch (Exception e) { 099 System.err.println("[JmxMeasurementCategoryFactory] ERROR: "+e); 100 return; 101 } 102 } 103 slice.getMaster().add(value, time); 104 } 105 106 }; 107 } 108 return ret; 109 } 110 return null; 111 } 112 113 /** 114 * This implementation tries to use Java 5 management features. 115 * Returns null if JVM is not of version 5. 116 * @return MBean server to register MBeans with 117 */ 118 protected abstract MBeanServer getMBeanServer(); 119 120 /** 121 * Constructs MBean name from category name and measurement name. 122 * @param categoryName 123 * @param name 124 * @return 125 * @throws NullPointerException 126 * @throws MalformedObjectNameException 127 */ 128 protected ObjectName objectName(final String categoryName, String name) throws MalformedObjectNameException { 129 return new ObjectName("biz.hammurapi.metrics:category="+categoryName+",name="+name); 130 } 131 132 }