Package netflix.adminresources.resources.jmx

Source Code of netflix.adminresources.resources.jmx.JMXResource

/*
* Copyright 2013 Netflix, Inc.
*
*      Licensed under the Apache License, Version 2.0 (the "License");
*      you may not use this file except in compliance with the License.
*      You may obtain a copy of the License at
*
*          http://www.apache.org/licenses/LICENSE-2.0
*
*      Unless required by applicable law or agreed to in writing, software
*      distributed under the License is distributed on an "AS IS" BASIS,
*      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*      See the License for the specific language governing permissions and
*      limitations under the License.
*/

package netflix.adminresources.resources.jmx;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.StringWriter;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;


/**
* Resource to expose JMX via JSON
*
* @author elandau
*
*/
@Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_HTML })
@Path("/webadmin/jmx")
public class JMXResource {
    private static final Logger LOG = LoggerFactory.getLogger(JMXResource.class);
    private static final String CURRENT_VALUE = "CurrentValue";

    private JmxService jmx;

    public JMXResource() {
        LOG.info("JMXResource created");
        jmx = JmxService.getInstance();
    }

    /**
     * Return JSON representing the entire tree of MBeans in DynaTree format.
     *
     * @param key
     * @param mode
     */
    @GET
    public Response getMBeans(
            @QueryParam("key") @DefaultValue("root") String key,
            @QueryParam("mode") @DefaultValue("") String mode,
            @QueryParam("jsonp") @DefaultValue("") String jsonp)
            throws Exception {

        LOG.info("key" + key);
        DynaTreeNode root = new DynaTreeNode();
        for (String domain : jmx.getDomainList()) {
            root.putChild(jmx.getDomainTree(domain).setTitle(domain)
                    .setMode("domain"));
        }

        StringWriter out = new StringWriter();
        if (jsonp.isEmpty()) {
            root.getChildrenJSONArray().write(out);
        } else {
            out.append(jsonp).append("(");
            root.getChildrenJSONArray().write(out);
            out.append(");");
        }

        return Response.ok(out.toString()).header("Pragma", "no-cache")
                .header("Cache-Control", "no-cache").header("Expires", "0")
                .build();
    }



    /**
     * Return all the attributes and operations for a single mbean
     *
     * @param key
     *            Exact object name of MBean in String form
     * @param jsonp
     */
    @GET
    @Path("{key}")
    public Response getMBean(@PathParam("key") String key,
                             @QueryParam("jsonp") @DefaultValue("") String jsonp)
            throws Exception {
        LOG.info("key: " + key);

        JSONObject json = new JSONObject();

        ObjectName name = new ObjectName(key);
        json.put("domain", name.getDomain());
        json.put("property", name.getKeyPropertyList());

        if (key.contains("*")) {
            JSONObject keys = new JSONObject();
            for (Entry<String, Map<String, String>> attrs : jmx
                    .getMBeanAttributesByRegex(key).entrySet()) {
                keys.put(attrs.getKey(), attrs.getValue());
            }
            json.put("attributes", keys);
            json.put("multikey", true);
        } else {
            json.put("attributes", jmx.getMBeanAttributes(key));
            json.put("multikey", false);

            MBeanOperationInfo[] operations = jmx.getMBeanOperations(key);
            JSONArray ar = new JSONArray();
            for (MBeanOperationInfo operation : operations) {
                JSONObject obj = new JSONObject();
                obj.put("name", operation.getName());
                obj.put("description", operation.getDescription());
                obj.put("returnType", operation.getReturnType());
                obj.put("impact", operation.getImpact());

                JSONArray params = new JSONArray();
                for (MBeanParameterInfo param : operation.getSignature()) {
                    JSONObject p = new JSONObject();
                    p.put("name", param.getName());
                    p.put("type", param.getType());
                    params.put(p);
                }
                obj.put("params", params);
                ar.put(obj);
            }
            json.put("operations", ar);
        }

        StringWriter out = new StringWriter();
        if (jsonp.isEmpty()) {
            json.write(out);
        } else {
            out.append(jsonp).append("(");
            json.write(out);
            out.append(");");
        }
        return Response.ok(out.toString()).type(MediaType.APPLICATION_JSON)
                .build();
    }

    /**
     * Execute an operation on an mbean.
     *
     * @param formParams
     * @param key
     * @param jsonp
     * @param name
     */
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Path("{key}/{op}")
    public Response invokeMbeanOperation(
            MultivaluedMap<String, String> formParams,
            @PathParam("key") String key, @QueryParam("jsonp") String jsonp,
            @PathParam("op") String name) throws Exception {

        LOG.info("invoke " + key + " op=" + name);
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        Map<String, String> params = new TreeMap<String, String>();
        for (Entry<String, List<String>> entry : formParams.entrySet()) {
            if (entry.getKey().equals("op"))
                continue;
            if (entry.getValue().size() > 0)
                params.put(entry.getKey(), entry.getValue().get(0));
            else
                params.put(entry.getKey(), "");
        }

        ObjectName objName = new ObjectName(key);
        MBeanInfo info = mBeanServer.getMBeanInfo(objName);
        for (MBeanOperationInfo op : info.getOperations()) {
            if (op.getName().equals(name)) {
                List<String> signature = new ArrayList<String>();
                for (MBeanParameterInfo s : op.getSignature()) {
                    signature.add(s.getType());
                }
                Object result = mBeanServer.invoke(objName, name, params
                        .values().toArray(new String[params.size()]), signature
                        .toArray(new String[signature.size()]));
                JSONObject json = new JSONObject();
                json.put("key", key);
                json.put("operation", name);
                if (result != null) {
                    json.put("response", result.toString());
                }
                json.put("type", op.getReturnType());

                StringWriter out = new StringWriter();
                if (jsonp.isEmpty()) {
                    json.write(out);
                } else {
                    out.append(jsonp).append("(");
                    json.write(out);
                    out.append(");");
                }
                return Response.ok(out.toString())
                        .type(MediaType.APPLICATION_JSON).build();
            }
        }

        return Response.serverError().build();
    }

    /**
     * Return all the attributes and operations for a MBeans whose
     * {@link ObjectName}s match the passed in regex.
     *
     * @param objNameRegex
     *            regex for {@link ObjectName} of MBean(s). The
     *            {@link ObjectName} documentation explains what kinds of regex
     *            expressions are valid
     * @param jsonp
     *            if non-empty, Jsonp output is returned instead of Json
     */
    @GET
    @Path("/mbeans")
    public Response getMBeansByRegex(
            @QueryParam("objNameRegex") String objNameRegex,
            @QueryParam("jsonp") @DefaultValue("") String jsonp) {
        try {
            ObjectName objNameForRegex = new ObjectName(objNameRegex);
            MBeanServer mBeanServer = ManagementFactory
                    .getPlatformMBeanServer();
            Set<ObjectName> objs = mBeanServer
                    .queryNames(objNameForRegex, null);
            JSONObject result = new JSONObject();
            for (ObjectName objName : objs) {
                JSONObject json = new JSONObject();
                try {
                    json.put("attributes", emitAttributes(objName));
                } catch (Exception e) {
                    json.put("attributes", emitAttributes(objName));
                }
                json.put("operations", emitOperations(objName));
                result.put(objName.getCanonicalName(), json);
            }
            StringWriter out = new StringWriter();
            if (jsonp.isEmpty()) {
                result.write(out);
            } else {
                out.append(jsonp).append("(");
                result.write(out);
                out.append(");");
            }
            return Response.ok(out.toString()).type(MediaType.APPLICATION_JSON)
                    .build();
        } catch (Exception e) {
            LOG.error(
                    "Error while retrieving mbeans for regex:" + objNameRegex,
                    e);
            return Response.serverError().entity(e.getMessage()).build();
        }
    }



    /**
     * Generate JSON for the MBean attributes
     *
     * @return
     * @throws Exception
     */
    private JSONObject emitAttributes(ObjectName objName) throws Exception {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objName);
        JSONObject resp = new JSONObject();
        if (mBeanInfo != null) {
            MBeanAttributeInfo[] attrs = mBeanInfo.getAttributes();
            if (attrs != null) {
                List<String> attrNames = new ArrayList<String>(attrs.length);
                for (MBeanAttributeInfo attr : attrs) {
                    attrNames.add(attr.getName());
                }
                AttributeList attrList = mBeanServer.getAttributes(objName,
                        attrNames.toArray(new String[0]));
                for (Attribute attr : attrList.asList()) {
                    Object value = attr.getValue();
                    String attrName = attr.getName();
                    if (attrName != null && value != null) {
                        String attrValue = null;

                        if (value instanceof CompositeDataSupport) {
                            CompositeDataSupport compositeValue = (CompositeDataSupport) value;
                            if (compositeValue != null) {
                                try {
                                    if (compositeValue.containsKey(CURRENT_VALUE)) {
                                        Object curValue = compositeValue
                                                .get(CURRENT_VALUE);
                                        attrValue = (curValue == null ? "null"
                                                : curValue.toString());
                                    }
                                }
                                catch (Exception e) {
                                    attrValue = compositeValue.toString();
                                }
                            }
                        }

                        if (attrValue == null) {
                            attrValue = value.toString();
                        }
                        resp.put(attrName, (attrValue == null ? "null"
                                : attrValue));
                    }
                }
            }
        }
        return resp;
    }

    /**
     * Generate JSON for the MBean operations
     *
     * @param objName
     * @return
     * @throws Exception
     */
    private JSONArray emitOperations(ObjectName objName) throws Exception {
        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
        MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objName);
        JSONArray ar = new JSONArray();

        MBeanOperationInfo[] operations = mBeanInfo.getOperations();
        for (MBeanOperationInfo operation : operations) {
            JSONObject obj = new JSONObject();
            obj.put("name", operation.getName());
            obj.put("description", operation.getDescription());
            obj.put("returnType", operation.getReturnType());
            obj.put("impact", operation.getImpact());

            JSONArray params = new JSONArray();
            for (MBeanParameterInfo param : operation.getSignature()) {
                JSONObject p = new JSONObject();
                p.put("name", param.getName());
                p.put("type", param.getType());
                params.put(p);
            }
            obj.put("params", params);
            ar.put(obj);
        }
        return ar;
    }

}
TOP

Related Classes of netflix.adminresources.resources.jmx.JMXResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.