    001    package com.hammurapi.eventbus.monitoring;
    002
    003    import java.util.ArrayList;
    004    import java.util.Collection;
    005    import java.util.Map;
    006    import java.util.concurrent.ConcurrentHashMap;
    007
    008    import javax.management.MBeanServer;
    009    import javax.management.ObjectName;
    010    import javax.management.StandardMBean;
    011
    012    import com.hammurapi.eventbus.EventBusException;
    013
    014    /**
    015     * Statistics collector which exposes statistics as MBeans.
    016     * @author Pavel Vlasov
    017     *
    018     */
    019    public class JmxStatsCollector implements StatsCollector {
    020
    021            private static volatile long keyCounter;
    022
    023            private MBeanServer mBeanServer;
    024            private String objectNamePrefix;
    025
    026            private Map<Stats, Iterable<ObjectName>> regInfo = new ConcurrentHashMap<Stats, Iterable<ObjectName>>();
    027
    028            /**
    029             * @param mBeanServer MBean server to register statistics MBeans.
    030             * @param objectNamePrefix Object name prefix for statistics MBeans without trailing comma.
    031             * E.g. <code>mycategory:mykey=myvalue</code>.
    032             */
    033            public JmxStatsCollector(MBeanServer mBeanServer, String objectNamePrefix) {
    034                    this.mBeanServer = mBeanServer;
    035                    this.objectNamePrefix = objectNamePrefix;
    036            }
    037
    038            @Override
    039            public void add(Stats root) {
    040                    Collection<ObjectName> reg = new ArrayList<ObjectName>();
    041                    add(root, objectNamePrefix, reg);
    042            }
    043
    044            private void add(Stats stats, String prefix, Collection<ObjectName> reg) {
    045                    @SuppressWarnings("unchecked")
    046                    Class<Stats> mBeanInterface = (Class<Stats>) stats.getClass().getInterfaces()[0];
    047                    int idx = mBeanInterface.getName().lastIndexOf('.');
    048                    String key = mBeanInterface.getName().substring(idx+1)+"("+(++keyCounter)+")";
    049                    String name = prefix+","+key+"="+stats.getName();
    050                    try {
    051                            ObjectName oName = new ObjectName(name);
    052                            reg.add(oName);
    053                            mBeanServer.registerMBean(new StandardMBean(stats, mBeanInterface), oName);
    054                    } catch (Exception e) {
    055                            throw new EventBusException(e);
    056                    }
    057                    for (Stats child: stats.children()) {
    058                            add(child, name, reg);
    059                    }
    060            }
    061
    062            public void remove(Stats root) {
    063                    for (ObjectName oName: regInfo.get(root)) {
    064                            try {
    065                                    mBeanServer.unregisterMBean(oName);
    066                            } catch (Exception e) {
    067                                    throw new EventBusException(e);
    068                            }
    069                    }
    070            }
    071
    072    }