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 private Integer interval; 020 021 public void setCategory(String category) { 022 this.category = category; 023 } 024 025 public void setInterval(int pInterval) { 026 this.interval = pInterval; 027 } 028 029 private Map<String, MeasurementConsumer> measurementConsumers = new HashMap<String, MeasurementConsumer>(); 030 031 private class JmxSliceImpl implements JmxSlice { 032 033 private String name; 034 private Slice data; 035 private long to; 036 private Slice accumulator; 037 038 public JmxSliceImpl(String name) { 039 this.name = name; 040 data = new SimpleSlice(name); 041 if (interval!=null) { 042 accumulator = new SimpleSlice(name); 043 to = System.currentTimeMillis(); 044 } 045 } 046 047 public double getAverage() { 048 return getData().getAvg(); 049 } 050 051 public double getDeviation() { 052 return getData().getDeviation(); 053 } 054 055 public Date getFrom() { 056 return new Date(getData().getFrom()); 057 } 058 059 public double getMax() { 060 return getData().getMax(); 061 } 062 063 public double getMin() { 064 return getData().getMin(); 065 } 066 067 public int getNumber() { 068 return getData().getNumber(); 069 } 070 071 public Date getTo() { 072 return new Date(getData().getTo()); 073 } 074 075 public double getTotal() { 076 return getData().getTotal(); 077 } 078 079 public void reset() { 080 data = new SimpleSlice(name); 081 } 082 083 Slice getData() { 084 checkTime(); 085 return data; 086 } 087 088 private void checkTime() { 089 if (interval!=null) { 090 long now = System.currentTimeMillis(); 091 if (now > to) { 092 data = accumulator; 093 accumulator = new SimpleSlice(name); 094 while (to<now) { 095 to += interval; 096 } 097 } 098 } 099 } 100 101 Slice getAccumulator() { 102 checkTime(); 103 return interval==null ? data : accumulator; 104 } 105 106 } 107 108 public synchronized MeasurementConsumer getMeasurementConsumer(final String categoryName) { 109 MBeanServer mBeanServer = getMBeanServer(); 110 if (mBeanServer!=null 111 && (category==null || category.equals(categoryName) || (categoryName!=null && categoryName.startsWith(category+".")))) { 112 MeasurementConsumer ret = (MeasurementConsumer) measurementConsumers.get(categoryName); 113 if (ret==null) { 114 ret = new MeasurementConsumer() { 115 private Map<String, JmxSliceImpl> sliceMap = new HashMap<String, JmxSliceImpl>(); 116 117 public synchronized void addMeasurement(String name, double value, long time) { 118 JmxSliceImpl slice = sliceMap.get(name); 119 if (slice==null) { 120 slice=new JmxSliceImpl(name); 121 sliceMap.put(name, slice); 122 123 try { 124 MBeanServer mbs = getMBeanServer(); 125 if (mbs!=null) { 126 mbs.registerMBean(new StandardMBean(slice, JmxSlice.class), objectName(categoryName, name)); 127 } 128 } catch (Exception e) { 129 System.err.println("[JmxMeasurementCategoryFactory] ERROR: "+e); 130 return; 131 } 132 } 133 slice.getAccumulator().add(value, time); 134 } 135 136 }; 137 } 138 return ret; 139 } 140 return null; 141 } 142 143 /** 144 * This implementation tries to use Java 5 management features. 145 * Returns null if JVM is not of version 5. 146 * @return MBean server to register MBeans with 147 */ 148 protected abstract MBeanServer getMBeanServer(); 149 150 /** 151 * Constructs MBean name from category name and measurement name. 152 * @param categoryName 153 * @param name 154 * @return 155 * @throws NullPointerException 156 * @throws MalformedObjectNameException 157 */ 158 protected ObjectName objectName(final String categoryName, String name) throws MalformedObjectNameException { 159 return new ObjectName("biz.hammurapi.metrics:category="+categoryName+",name="+name); 160 } 161 162 }