All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.collectd.mx.MBeanCollector Maven / Gradle / Ivy

Go to download

The jcollectd package implements the collectd protocol in Java, making it possible for Java applications to push data into collectd over the wire.

The newest version!
/*
 * jcollectd
 * Copyright (C) 2009 Hyperic, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; only version 2 of the License is applicable.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

package org.collectd.mx;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.management.Descriptor;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;

import org.collectd.api.ValueList;
import org.collectd.protocol.Network;
import org.collectd.protocol.PropertyNames;
import org.collectd.protocol.TypesDB;

/**
 * Query MBeans and dispatch results upstream.
 */
public class MBeanCollector implements Runnable {

    private static final Logger _log =
        Logger.getLogger(MBeanCollector.class.getName());
    private static boolean _useDescriptors =
        "true".equals(Network.getProperty(PropertyNames.MX_DESCRIPTORS, "true"));
    private static Method _getDescriptor;
    private static final String _metricTypeField =
        Network.getProperty(PropertyNames.METRIC_TYPE_FIELD, "metricType");
    private MBeanSender _sender;
    private long _interval = 60;
    private Map _queries =
        new HashMap();

    static {
        if (_useDescriptors) {
            try {
                _getDescriptor = //1.6+
                    MBeanAttributeInfo.class.getMethod("getDescriptor",
                                                       (Class[])null);
            } catch (Exception e) {
                _useDescriptors = false;
            }
        }
    }
    public MBeanSender getSender() {
        return _sender;
    }

    public void setSender(MBeanSender sender) {
        _sender = sender;
    }

    public long getInterval() {
        return _interval;
    }

    public void setInterval(long interval) {
        _interval = interval;
    }

    public Map getQueries() {
        return _queries;
    }

    public MBeanQuery addMBean(String objectName) {
        MBeanQuery query = _queries.get(objectName);
        if (query == null) {
            try {
                query = new MBeanQuery(new ObjectName(objectName));
            } catch (Exception e) {
                throw new IllegalArgumentException(objectName);
            }
            _queries.put(objectName, query);
        }
        return query;
    }

    public MBeanAttribute addMBeanAttribute(String objectName,
                                            String attributeName) {
        MBeanQuery query = addMBean(objectName);
        if (attributeName != null) {
            MBeanAttribute attr = new MBeanAttribute(attributeName);
            query.addAttribute(attr);
            return attr;
        }
        else {
            return null;
        }
    }

    private boolean isNumber(Object obj) {
        if (obj == null) {
            return false;
        }
        return Number.class.isAssignableFrom(obj.getClass());
    }

    private String getBeanName(ObjectName query, ObjectName name) {
        Map skip;
        if (query == null) {
            skip = new HashMap();
        }
        else {
            skip = query.getKeyPropertyList();
        }
        StringBuffer iname = new StringBuffer();
        for (Object key : name.getKeyPropertyList().keySet()) {
            if (skip.get(key) != null) {
                continue;
            }
            if (iname.length() > 0) {
                iname.append(' ');
            }
            iname.append(name.getKeyProperty((String)key));
        }
        return iname.toString();
    }

    private void dispatch(MBeanQuery query, String plugin,
                          String typeInstance,
                          ObjectName name, MBeanAttribute attr,
                          Number val) {
        if (attr.getDataType() == Network.DS_TYPE_GAUGE) {
            val = new Double(val.doubleValue());
        }
        else {
            val = new Long(val.longValue());
        }

        String pluginInstance = query.getPluginInstance();
        if (pluginInstance == null) {
            pluginInstance = _sender.getInstanceName();
        }
        String beanName = query.getAlias();
        ValueList vl = new ValueList();
        vl.setInterval(getInterval());
        vl.setPlugin(plugin);
        if (beanName == null){
            beanName = getBeanName(null, name);
        }
        else if (query.getName().isPattern()) {
            String instName = getBeanName(query.getName(), name);
            if (instName != null) {
                beanName += " " + instName;
            }
        }
        vl.setPluginInstance(pluginInstance + "-" + beanName);
        vl.setType(attr.getTypeName());
        vl.setTypeInstance(typeInstance);
        vl.addValue(val);
        _sender.dispatch(vl);
    }

    public void collect(MBeanQuery query, ObjectName name) throws Exception {
        MBeanServerConnection conn = _sender.getMBeanServerConnection();
        if (_log.isLoggable(Level.FINE)) {
            _log.fine("[jcollectd] mbeans available:"+conn.getMBeanCount());
        }
        String plugin = query.getPlugin();
        if (plugin == null) {
            plugin = name.getDomain();
        }

        Map attrInfo = null;
        if (_useDescriptors) {
            MBeanInfo info = conn.getMBeanInfo(name);
            attrInfo = new HashMap();
            for (MBeanAttributeInfo ainfo : info.getAttributes()) {
                attrInfo.put(ainfo.getName(), ainfo);
            }
        }

        for (MBeanAttribute attr : query.getAttributes()) {
            String attrName = attr.getAttributeName();
            Object obj;

            try {
                obj = conn.getAttribute(name, attrName);
            } catch (Exception e) {
                //XXX remove attr for future collection e.g. UnsupportedOperation
                continue;
            }

            if (_useDescriptors) {
                //e.g. spring @ManagedMetric(metricType = MetricType.COUNTER)
                try {
                    Descriptor descriptor =
                        (Descriptor)_getDescriptor.invoke(attrInfo.get(attrName),
                                                          (Object[])null);
                    Object type = descriptor.getFieldValue(_metricTypeField);
                    if (TypesDB.NAME_COUNTER.equals(type)) {
                        if (attr.getTypeName().equals(TypesDB.NAME_GAUGE)) {
                            attr.setTypeName(TypesDB.NAME_COUNTER);
                        }
                        attr.setDataType(Network.DS_TYPE_COUNTER);
                    }
                } catch (Exception e) {
                }
            }

            if (obj instanceof CompositeData) {
                CompositeData data = (CompositeData)obj;
                String key = attr.getCompositeKey();                
                if (key == null) {
                    //no key specified; collect all
                    Set keys = data.getCompositeType().keySet();
                    for (String ckey : keys) {
                        obj = data.get(ckey);
                        if (!isNumber(obj)) {
                            continue;
                        }
                        dispatch(query, plugin,
                                 attrName + "." + ckey,
                                 name, attr, (Number)obj);
                    }
                    continue;
                }
                else {
                    obj = data.get(key);
                }
            }
            if (!isNumber(obj)) {
                continue;
            }
            dispatch(query, plugin,
                     attr.getName(),
                     name, attr, (Number)obj);
        }
        _sender.flush();
    }

    private void run(MBeanQuery query, ObjectName name) {
        try {
            if (query.getAttributes().size() == 0) {
                query = queryAll(name);
            }
            collect(query, name);
        } catch (Exception e) {
            //MBean might not be registered yet (or anymore)
            _log.log(Level.FINE, "[jcollectd] collect failed:" + name, e);
        }
    }

    private MBeanQuery queryAll(ObjectName name)
        throws Exception {
        MBeanQuery query = new MBeanQuery(name);
        MBeanInfo info = _sender.getMBeanServerConnection().getMBeanInfo(name);
        MBeanAttributeInfo[] attrs = info.getAttributes();
        for (int i=0; i beans;
                try {
                    beans = 
                        _sender.getMBeanServerConnection().queryNames(name, null);
                } catch (Exception e) {
                    _log.warning("queryNames(" + name + "): " + e);
                    return;
                }
                for (ObjectName oname : beans) {
                    // let the query decide to include/exclude
                    if (!query.isExcluded(oname.getCanonicalName())) {
                        run(query, oname);
                    } else {
                        if (_log.isLoggable(Level.FINE)) {
                            _log.fine("excluding:"+oname);
                        }
                    }
                }
            }
            else {
                run(query, name);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy