HBASE-12665 When aborting, dump metrics
Add some fixup of checkstyle fails
This commit is contained in:
parent
9b808155e3
commit
df22270756
|
@ -85,7 +85,8 @@ public class HColumnDescriptor implements Comparable<HColumnDescriptor> {
|
|||
/**
|
||||
* Key for cache data into L1 if cache is set up with more than one tier.
|
||||
* To set in the shell, do something like this:
|
||||
* <code>hbase(main):003:0> create 't', {NAME => 't', CONFIGURATION => {CACHE_DATA_IN_L1 => 'true'}}</code>
|
||||
* <code>hbase(main):003:0> create 't',
|
||||
* {NAME => 't', CONFIGURATION => {CACHE_DATA_IN_L1 => 'true'}}</code>
|
||||
*/
|
||||
public static final String CACHE_DATA_IN_L1 = "CACHE_DATA_IN_L1";
|
||||
|
||||
|
|
|
@ -39,6 +39,11 @@ import org.apache.hadoop.security.UserGroupInformation;
|
|||
@InterfaceStability.Evolving
|
||||
public class AuthUtil {
|
||||
private static final Log LOG = LogFactory.getLog(AuthUtil.class);
|
||||
|
||||
private AuthUtil() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if security is enabled and if so, launches chore for refreshing kerberos ticket.
|
||||
*/
|
||||
|
|
|
@ -171,7 +171,7 @@ public final class CellUtil {
|
|||
return new KeyValue(row, family, qualifier, timestamp, KeyValue.Type.codeToType(type), value);
|
||||
}
|
||||
|
||||
public static Cell createCell (final byte [] rowArray, final int rowOffset, final int rowLength,
|
||||
public static Cell createCell(final byte [] rowArray, final int rowOffset, final int rowLength,
|
||||
final byte [] familyArray, final int familyOffset, final int familyLength,
|
||||
final byte [] qualifierArray, final int qualifierOffset, final int qualifierLength) {
|
||||
// See createCell(final byte [] row, final byte [] value) for why we default Maximum type.
|
||||
|
@ -567,7 +567,7 @@ public final class CellUtil {
|
|||
/********************* tags *************************************/
|
||||
/**
|
||||
* Util method to iterate through the tags
|
||||
*
|
||||
*
|
||||
* @param tags
|
||||
* @param offset
|
||||
* @param length
|
||||
|
@ -883,4 +883,4 @@ public final class CellUtil {
|
|||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,24 +20,11 @@ package org.apache.hadoop.hbase.http.jmx;
|
|||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.RuntimeMBeanException;
|
||||
import javax.management.RuntimeErrorException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.TabularData;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -47,8 +34,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.hbase.http.HttpServer;
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.apache.hadoop.hbase.util.JSONBean;
|
||||
|
||||
/*
|
||||
* This servlet is based off of the JMXProxyServlet from Tomcat 7.0.14. It has
|
||||
|
@ -135,10 +121,8 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
*/
|
||||
protected transient MBeanServer mBeanServer;
|
||||
|
||||
/**
|
||||
* Json Factory to create Json generators for write objects in json format
|
||||
*/
|
||||
protected transient JsonFactory jsonFactory;
|
||||
protected transient JSONBean jsonBeanWriter;
|
||||
|
||||
/**
|
||||
* Initialize this servlet.
|
||||
*/
|
||||
|
@ -146,7 +130,7 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
public void init() throws ServletException {
|
||||
// Retrieve the MBean server
|
||||
mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
jsonFactory = new JsonFactory();
|
||||
this.jsonBeanWriter = new JSONBean();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,11 +147,12 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
if (!HttpServer.isInstrumentationAccessAllowed(getServletContext(), request, response)) {
|
||||
return;
|
||||
}
|
||||
JsonGenerator jg = null;
|
||||
String jsonpcb = null;
|
||||
PrintWriter writer = null;
|
||||
JSONBean.Writer beanWriter = null;
|
||||
try {
|
||||
writer = response.getWriter();
|
||||
beanWriter = this.jsonBeanWriter.open(writer);
|
||||
|
||||
// "callback" parameter implies JSONP outpout
|
||||
jsonpcb = request.getParameter(CALLBACK_PARAM);
|
||||
|
@ -181,23 +166,22 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
String tmpStr = request.getParameter(INCLUDE_DESCRIPTION);
|
||||
boolean description = tmpStr != null && tmpStr.length() > 0;
|
||||
|
||||
jg = jsonFactory.createJsonGenerator(writer);
|
||||
jg.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
jg.useDefaultPrettyPrinter();
|
||||
jg.writeStartObject();
|
||||
|
||||
// query per mbean attribute
|
||||
String getmethod = request.getParameter("get");
|
||||
if (getmethod != null) {
|
||||
String[] splitStrings = getmethod.split("\\:\\:");
|
||||
if (splitStrings.length != 2) {
|
||||
jg.writeStringField("result", "ERROR");
|
||||
jg.writeStringField("message", "query format is not as expected.");
|
||||
jg.flush();
|
||||
beanWriter.write("result", "ERROR");
|
||||
beanWriter.write("message", "query format is not as expected.");
|
||||
beanWriter.flush();
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
listBeans(jg, new ObjectName(splitStrings[0]), splitStrings[1], description, response);
|
||||
if (beanWriter.write(this.mBeanServer, new ObjectName(splitStrings[0]),
|
||||
splitStrings[1], description) != 0) {
|
||||
beanWriter.flush();
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,11 +190,12 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
if (qry == null) {
|
||||
qry = "*:*";
|
||||
}
|
||||
listBeans(jg, new ObjectName(qry), null, description, response);
|
||||
} finally {
|
||||
if (jg != null) {
|
||||
jg.close();
|
||||
if (beanWriter.write(this.mBeanServer, new ObjectName(qry), null, description) != 0) {
|
||||
beanWriter.flush();
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
} finally {
|
||||
if (beanWriter != null) beanWriter.close();
|
||||
if (jsonpcb != null) {
|
||||
writer.write(");");
|
||||
}
|
||||
|
@ -226,237 +211,4 @@ public class JMXJsonServlet extends HttpServlet {
|
|||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- Private Methods
|
||||
private void listBeans(JsonGenerator jg, ObjectName qry, String attribute,
|
||||
final boolean description, final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOG.trace("Listing beans for "+qry);
|
||||
Set<ObjectName> names = null;
|
||||
names = mBeanServer.queryNames(qry, null);
|
||||
jg.writeArrayFieldStart("beans");
|
||||
Iterator<ObjectName> it = names.iterator();
|
||||
while (it.hasNext()) {
|
||||
ObjectName oname = it.next();
|
||||
MBeanInfo minfo;
|
||||
String code = "";
|
||||
String descriptionStr = null;
|
||||
Object attributeinfo = null;
|
||||
try {
|
||||
minfo = mBeanServer.getMBeanInfo(oname);
|
||||
code = minfo.getClassName();
|
||||
if (description) descriptionStr = minfo.getDescription();
|
||||
String prs = "";
|
||||
try {
|
||||
if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) {
|
||||
prs = "modelerType";
|
||||
code = (String) mBeanServer.getAttribute(oname, prs);
|
||||
}
|
||||
if (attribute != null) {
|
||||
prs = attribute;
|
||||
attributeinfo = mBeanServer.getAttribute(oname, prs);
|
||||
}
|
||||
} catch (RuntimeMBeanException e) {
|
||||
// UnsupportedOperationExceptions happen in the normal course of business,
|
||||
// so no need to log them as errors all the time.
|
||||
if (e.getCause() instanceof UnsupportedOperationException) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Getting attribute " + prs + " of " + oname + " threw " + e);
|
||||
}
|
||||
} else {
|
||||
LOG.error("Getting attribute " + prs + " of " + oname + " threw an exception", e);
|
||||
}
|
||||
return;
|
||||
} catch (AttributeNotFoundException e) {
|
||||
// If the modelerType attribute was not found, the class name is used
|
||||
// instead.
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch (MBeanException e) {
|
||||
// The code inside the attribute getter threw an exception so log it,
|
||||
// and fall back on the class name
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch (RuntimeException e) {
|
||||
// For some reason even with an MBeanException available to them
|
||||
// Runtime exceptionscan still find their way through, so treat them
|
||||
// the same as MBeanException
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch ( ReflectionException e ) {
|
||||
// This happens when the code inside the JMX bean (setter?? from the
|
||||
// java docs) threw an exception, so log it and fall back on the
|
||||
// class name
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
}
|
||||
} catch (InstanceNotFoundException e) {
|
||||
//Ignored for some reason the bean was not found so don't output it
|
||||
continue;
|
||||
} catch ( IntrospectionException e ) {
|
||||
// This is an internal error, something odd happened with reflection so
|
||||
// log it and don't output the bean.
|
||||
LOG.error("Problem while trying to process JMX query: " + qry
|
||||
+ " with MBean " + oname, e);
|
||||
continue;
|
||||
} catch ( ReflectionException e ) {
|
||||
// This happens when the code inside the JMX bean threw an exception, so
|
||||
// log it and don't output the bean.
|
||||
LOG.error("Problem while trying to process JMX query: " + qry
|
||||
+ " with MBean " + oname, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
jg.writeStartObject();
|
||||
jg.writeStringField("name", oname.toString());
|
||||
if (description && descriptionStr != null && descriptionStr.length() > 0) {
|
||||
jg.writeStringField("description", descriptionStr);
|
||||
}
|
||||
jg.writeStringField("modelerType", code);
|
||||
if (attribute != null && attributeinfo == null) {
|
||||
jg.writeStringField("result", "ERROR");
|
||||
jg.writeStringField("message", "No attribute with name " + attribute + " was found.");
|
||||
jg.writeEndObject();
|
||||
jg.writeEndArray();
|
||||
jg.close();
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attribute != null) {
|
||||
writeAttribute(jg, attribute, descriptionStr, attributeinfo);
|
||||
} else {
|
||||
MBeanAttributeInfo attrs[] = minfo.getAttributes();
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
writeAttribute(jg, oname, description, attrs[i]);
|
||||
}
|
||||
}
|
||||
jg.writeEndObject();
|
||||
}
|
||||
jg.writeEndArray();
|
||||
}
|
||||
|
||||
private void writeAttribute(JsonGenerator jg, ObjectName oname, final boolean description,
|
||||
MBeanAttributeInfo attr)
|
||||
throws IOException {
|
||||
if (!attr.isReadable()) {
|
||||
return;
|
||||
}
|
||||
String attName = attr.getName();
|
||||
if ("modelerType".equals(attName)) {
|
||||
return;
|
||||
}
|
||||
if (attName.indexOf("=") >= 0 || attName.indexOf(":") >= 0 || attName.indexOf(" ") >= 0) {
|
||||
return;
|
||||
}
|
||||
String descriptionStr = description? attr.getDescription(): null;
|
||||
Object value = null;
|
||||
try {
|
||||
value = mBeanServer.getAttribute(oname, attName);
|
||||
} catch (RuntimeMBeanException e) {
|
||||
// UnsupportedOperationExceptions happen in the normal course of business,
|
||||
// so no need to log them as errors all the time.
|
||||
if (e.getCause() instanceof UnsupportedOperationException) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Getting attribute " + attName + " of " + oname + " threw " + e);
|
||||
}
|
||||
} else {
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
}
|
||||
return;
|
||||
} catch (RuntimeErrorException e) {
|
||||
// RuntimeErrorException happens when an unexpected failure occurs in getAttribute
|
||||
// for example https://issues.apache.org/jira/browse/DAEMON-120
|
||||
LOG.debug("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (AttributeNotFoundException e) {
|
||||
//Ignored the attribute was not found, which should never happen because the bean
|
||||
//just told us that it has this attribute, but if this happens just don't output
|
||||
//the attribute.
|
||||
return;
|
||||
} catch (MBeanException e) {
|
||||
//The code inside the attribute getter threw an exception so log it, and
|
||||
// skip outputting the attribute
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (RuntimeException e) {
|
||||
//For some reason even with an MBeanException available to them Runtime exceptions
|
||||
//can still find their way through, so treat them the same as MBeanException
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (ReflectionException e) {
|
||||
//This happens when the code inside the JMX bean (setter?? from the java docs)
|
||||
//threw an exception, so log it and skip outputting the attribute
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (InstanceNotFoundException e) {
|
||||
//Ignored the mbean itself was not found, which should never happen because we
|
||||
//just accessed it (perhaps something unregistered in-between) but if this
|
||||
//happens just don't output the attribute.
|
||||
return;
|
||||
}
|
||||
|
||||
writeAttribute(jg, attName, descriptionStr, value);
|
||||
}
|
||||
|
||||
private void writeAttribute(JsonGenerator jg, String attName, final String descriptionStr,
|
||||
Object value)
|
||||
throws IOException {
|
||||
boolean description = false;
|
||||
if (descriptionStr != null && descriptionStr.length() > 0 && !attName.equals(descriptionStr)) {
|
||||
description = true;
|
||||
jg.writeFieldName(attName);
|
||||
jg.writeStartObject();
|
||||
jg.writeFieldName("description");
|
||||
jg.writeString(descriptionStr);
|
||||
jg.writeFieldName("value");
|
||||
writeObject(jg, description, value);
|
||||
jg.writeEndObject();
|
||||
} else {
|
||||
jg.writeFieldName(attName);
|
||||
writeObject(jg, description, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeObject(JsonGenerator jg, final boolean description, Object value)
|
||||
throws IOException {
|
||||
if(value == null) {
|
||||
jg.writeNull();
|
||||
} else {
|
||||
Class<?> c = value.getClass();
|
||||
if (c.isArray()) {
|
||||
jg.writeStartArray();
|
||||
int len = Array.getLength(value);
|
||||
for (int j = 0; j < len; j++) {
|
||||
Object item = Array.get(value, j);
|
||||
writeObject(jg, description, item);
|
||||
}
|
||||
jg.writeEndArray();
|
||||
} else if(value instanceof Number) {
|
||||
Number n = (Number)value;
|
||||
jg.writeNumber(n.toString());
|
||||
} else if(value instanceof Boolean) {
|
||||
Boolean b = (Boolean)value;
|
||||
jg.writeBoolean(b);
|
||||
} else if(value instanceof CompositeData) {
|
||||
CompositeData cds = (CompositeData)value;
|
||||
CompositeType comp = cds.getCompositeType();
|
||||
Set<String> keys = comp.keySet();
|
||||
jg.writeStartObject();
|
||||
for (String key: keys) {
|
||||
writeAttribute(jg, key, null, cds.get(key));
|
||||
}
|
||||
jg.writeEndObject();
|
||||
} else if(value instanceof TabularData) {
|
||||
TabularData tds = (TabularData)value;
|
||||
jg.writeStartArray();
|
||||
for(Object entry : tds.values()) {
|
||||
writeObject(jg, description, entry);
|
||||
}
|
||||
jg.writeEndArray();
|
||||
} else {
|
||||
jg.writeString(value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
||||
|
@ -140,6 +141,7 @@ import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
|
|||
import org.apache.hadoop.hbase.util.FSTableDescriptors;
|
||||
import org.apache.hadoop.hbase.util.FSUtils;
|
||||
import org.apache.hadoop.hbase.util.HasThread;
|
||||
import org.apache.hadoop.hbase.util.JSONBean;
|
||||
import org.apache.hadoop.hbase.util.JvmPauseMonitor;
|
||||
import org.apache.hadoop.hbase.util.Sleeper;
|
||||
import org.apache.hadoop.hbase.util.Threads;
|
||||
|
@ -1924,6 +1926,13 @@ public class HRegionServer extends HasThread implements
|
|||
// java.util.HashSet's toString() method to print the coprocessor names.
|
||||
LOG.fatal("RegionServer abort: loaded coprocessors are: " +
|
||||
CoprocessorHost.getLoadedCoprocessors());
|
||||
// Try and dump metrics if abort -- might give clue as to how fatal came about....
|
||||
try {
|
||||
LOG.info("Dump of metrics as JSON on abort: " + JSONBean.dumpRegionServerMetrics());
|
||||
} catch (MalformedObjectNameException | IOException e) {
|
||||
LOG.warn("Failed dumping metrics", e);
|
||||
}
|
||||
|
||||
// Do our best to report our abort to the master, but this may not work
|
||||
try {
|
||||
if (cause != null) {
|
||||
|
|
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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 org.apache.hadoop.hbase.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.RuntimeErrorException;
|
||||
import javax.management.RuntimeMBeanException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.TabularData;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
|
||||
/**
|
||||
* Utility for doing JSON and MBeans.
|
||||
*/
|
||||
public class JSONBean {
|
||||
private static final Log LOG = LogFactory.getLog(JSONBean.class);
|
||||
private final JsonFactory jsonFactory;
|
||||
|
||||
public JSONBean() {
|
||||
this.jsonFactory = new JsonFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use dumping out mbeans as JSON.
|
||||
*/
|
||||
public interface Writer extends Closeable {
|
||||
void write(final String key, final String value) throws JsonGenerationException, IOException;
|
||||
int write(final MBeanServer mBeanServer, ObjectName qry, String attribute,
|
||||
final boolean description) throws IOException;
|
||||
void flush() throws IOException;
|
||||
}
|
||||
|
||||
public Writer open(final PrintWriter writer) throws IOException {
|
||||
final JsonGenerator jg = jsonFactory.createJsonGenerator(writer);
|
||||
jg.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
jg.useDefaultPrettyPrinter();
|
||||
jg.writeStartObject();
|
||||
return new Writer() {
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
jg.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
jg.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String key, String value) throws JsonGenerationException, IOException {
|
||||
jg.writeStringField(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(MBeanServer mBeanServer, ObjectName qry, String attribute,
|
||||
boolean description)
|
||||
throws IOException {
|
||||
return JSONBean.write(jg, mBeanServer, qry, attribute, description);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mBeanServer
|
||||
* @param qry
|
||||
* @param attribute
|
||||
* @param description
|
||||
* @return Return non-zero if failed to find bean. 0
|
||||
* @throws IOException
|
||||
*/
|
||||
private static int write(final JsonGenerator jg,
|
||||
final MBeanServer mBeanServer, ObjectName qry, String attribute,
|
||||
final boolean description)
|
||||
throws IOException {
|
||||
LOG.trace("Listing beans for "+qry);
|
||||
Set<ObjectName> names = null;
|
||||
names = mBeanServer.queryNames(qry, null);
|
||||
jg.writeArrayFieldStart("beans");
|
||||
Iterator<ObjectName> it = names.iterator();
|
||||
while (it.hasNext()) {
|
||||
ObjectName oname = it.next();
|
||||
MBeanInfo minfo;
|
||||
String code = "";
|
||||
String descriptionStr = null;
|
||||
Object attributeinfo = null;
|
||||
try {
|
||||
minfo = mBeanServer.getMBeanInfo(oname);
|
||||
code = minfo.getClassName();
|
||||
if (description) descriptionStr = minfo.getDescription();
|
||||
String prs = "";
|
||||
try {
|
||||
if ("org.apache.commons.modeler.BaseModelMBean".equals(code)) {
|
||||
prs = "modelerType";
|
||||
code = (String) mBeanServer.getAttribute(oname, prs);
|
||||
}
|
||||
if (attribute != null) {
|
||||
prs = attribute;
|
||||
attributeinfo = mBeanServer.getAttribute(oname, prs);
|
||||
}
|
||||
} catch (RuntimeMBeanException e) {
|
||||
// UnsupportedOperationExceptions happen in the normal course of business,
|
||||
// so no need to log them as errors all the time.
|
||||
if (e.getCause() instanceof UnsupportedOperationException) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Getting attribute " + prs + " of " + oname + " threw " + e);
|
||||
}
|
||||
} else {
|
||||
LOG.error("Getting attribute " + prs + " of " + oname + " threw an exception", e);
|
||||
}
|
||||
return 0;
|
||||
} catch (AttributeNotFoundException e) {
|
||||
// If the modelerType attribute was not found, the class name is used
|
||||
// instead.
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch (MBeanException e) {
|
||||
// The code inside the attribute getter threw an exception so log it,
|
||||
// and fall back on the class name
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch (RuntimeException e) {
|
||||
// For some reason even with an MBeanException available to them
|
||||
// Runtime exceptionscan still find their way through, so treat them
|
||||
// the same as MBeanException
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
} catch (ReflectionException e) {
|
||||
// This happens when the code inside the JMX bean (setter?? from the
|
||||
// java docs) threw an exception, so log it and fall back on the
|
||||
// class name
|
||||
LOG.error("getting attribute " + prs + " of " + oname
|
||||
+ " threw an exception", e);
|
||||
}
|
||||
} catch (InstanceNotFoundException e) {
|
||||
//Ignored for some reason the bean was not found so don't output it
|
||||
continue;
|
||||
} catch (IntrospectionException e) {
|
||||
// This is an internal error, something odd happened with reflection so
|
||||
// log it and don't output the bean.
|
||||
LOG.error("Problem while trying to process JMX query: " + qry
|
||||
+ " with MBean " + oname, e);
|
||||
continue;
|
||||
} catch (ReflectionException e) {
|
||||
// This happens when the code inside the JMX bean threw an exception, so
|
||||
// log it and don't output the bean.
|
||||
LOG.error("Problem while trying to process JMX query: " + qry
|
||||
+ " with MBean " + oname, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
jg.writeStartObject();
|
||||
jg.writeStringField("name", oname.toString());
|
||||
if (description && descriptionStr != null && descriptionStr.length() > 0) {
|
||||
jg.writeStringField("description", descriptionStr);
|
||||
}
|
||||
jg.writeStringField("modelerType", code);
|
||||
if (attribute != null && attributeinfo == null) {
|
||||
jg.writeStringField("result", "ERROR");
|
||||
jg.writeStringField("message", "No attribute with name " + attribute + " was found.");
|
||||
jg.writeEndObject();
|
||||
jg.writeEndArray();
|
||||
jg.close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (attribute != null) {
|
||||
writeAttribute(jg, attribute, descriptionStr, attributeinfo);
|
||||
} else {
|
||||
MBeanAttributeInfo[] attrs = minfo.getAttributes();
|
||||
for (int i = 0; i < attrs.length; i++) {
|
||||
writeAttribute(jg, mBeanServer, oname, description, attrs[i]);
|
||||
}
|
||||
}
|
||||
jg.writeEndObject();
|
||||
}
|
||||
jg.writeEndArray();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void writeAttribute(final JsonGenerator jg,
|
||||
final MBeanServer mBeanServer, ObjectName oname,
|
||||
final boolean description, final MBeanAttributeInfo attr)
|
||||
throws IOException {
|
||||
if (!attr.isReadable()) {
|
||||
return;
|
||||
}
|
||||
String attName = attr.getName();
|
||||
if ("modelerType".equals(attName)) {
|
||||
return;
|
||||
}
|
||||
if (attName.indexOf("=") >= 0 || attName.indexOf(":") >= 0 || attName.indexOf(" ") >= 0) {
|
||||
return;
|
||||
}
|
||||
String descriptionStr = description? attr.getDescription(): null;
|
||||
Object value = null;
|
||||
try {
|
||||
value = mBeanServer.getAttribute(oname, attName);
|
||||
} catch (RuntimeMBeanException e) {
|
||||
// UnsupportedOperationExceptions happen in the normal course of business,
|
||||
// so no need to log them as errors all the time.
|
||||
if (e.getCause() instanceof UnsupportedOperationException) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Getting attribute " + attName + " of " + oname + " threw " + e);
|
||||
}
|
||||
} else {
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
}
|
||||
return;
|
||||
} catch (RuntimeErrorException e) {
|
||||
// RuntimeErrorException happens when an unexpected failure occurs in getAttribute
|
||||
// for example https://issues.apache.org/jira/browse/DAEMON-120
|
||||
LOG.debug("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (AttributeNotFoundException e) {
|
||||
//Ignored the attribute was not found, which should never happen because the bean
|
||||
//just told us that it has this attribute, but if this happens just don't output
|
||||
//the attribute.
|
||||
return;
|
||||
} catch (MBeanException e) {
|
||||
//The code inside the attribute getter threw an exception so log it, and
|
||||
// skip outputting the attribute
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (RuntimeException e) {
|
||||
//For some reason even with an MBeanException available to them Runtime exceptions
|
||||
//can still find their way through, so treat them the same as MBeanException
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (ReflectionException e) {
|
||||
//This happens when the code inside the JMX bean (setter?? from the java docs)
|
||||
//threw an exception, so log it and skip outputting the attribute
|
||||
LOG.error("getting attribute "+attName+" of "+oname+" threw an exception", e);
|
||||
return;
|
||||
} catch (InstanceNotFoundException e) {
|
||||
//Ignored the mbean itself was not found, which should never happen because we
|
||||
//just accessed it (perhaps something unregistered in-between) but if this
|
||||
//happens just don't output the attribute.
|
||||
return;
|
||||
}
|
||||
|
||||
writeAttribute(jg, attName, descriptionStr, value);
|
||||
}
|
||||
|
||||
private static void writeAttribute(JsonGenerator jg, String attName, final String descriptionStr,
|
||||
Object value)
|
||||
throws IOException {
|
||||
boolean description = false;
|
||||
if (descriptionStr != null && descriptionStr.length() > 0 && !attName.equals(descriptionStr)) {
|
||||
description = true;
|
||||
jg.writeFieldName(attName);
|
||||
jg.writeStartObject();
|
||||
jg.writeFieldName("description");
|
||||
jg.writeString(descriptionStr);
|
||||
jg.writeFieldName("value");
|
||||
writeObject(jg, description, value);
|
||||
jg.writeEndObject();
|
||||
} else {
|
||||
jg.writeFieldName(attName);
|
||||
writeObject(jg, description, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeObject(final JsonGenerator jg, final boolean description, Object value)
|
||||
throws IOException {
|
||||
if(value == null) {
|
||||
jg.writeNull();
|
||||
} else {
|
||||
Class<?> c = value.getClass();
|
||||
if (c.isArray()) {
|
||||
jg.writeStartArray();
|
||||
int len = Array.getLength(value);
|
||||
for (int j = 0; j < len; j++) {
|
||||
Object item = Array.get(value, j);
|
||||
writeObject(jg, description, item);
|
||||
}
|
||||
jg.writeEndArray();
|
||||
} else if(value instanceof Number) {
|
||||
Number n = (Number)value;
|
||||
jg.writeNumber(n.toString());
|
||||
} else if(value instanceof Boolean) {
|
||||
Boolean b = (Boolean)value;
|
||||
jg.writeBoolean(b);
|
||||
} else if(value instanceof CompositeData) {
|
||||
CompositeData cds = (CompositeData)value;
|
||||
CompositeType comp = cds.getCompositeType();
|
||||
Set<String> keys = comp.keySet();
|
||||
jg.writeStartObject();
|
||||
for (String key: keys) {
|
||||
writeAttribute(jg, key, null, cds.get(key));
|
||||
}
|
||||
jg.writeEndObject();
|
||||
} else if(value instanceof TabularData) {
|
||||
TabularData tds = (TabularData)value;
|
||||
jg.writeStartArray();
|
||||
for(Object entry : tds.values()) {
|
||||
writeObject(jg, description, entry);
|
||||
}
|
||||
jg.writeEndArray();
|
||||
} else {
|
||||
jg.writeString(value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump out a subset of regionserver mbeans only, not all of them, as json on System.out.
|
||||
* @throws MalformedObjectNameException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static String dumpRegionServerMetrics() throws MalformedObjectNameException, IOException {
|
||||
StringWriter sw = new StringWriter(1024 * 100); // Guess this size
|
||||
try (PrintWriter writer = new PrintWriter(sw)) {
|
||||
JSONBean dumper = new JSONBean();
|
||||
try (JSONBean.Writer jsonBeanWriter = dumper.open(writer)) {
|
||||
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
jsonBeanWriter.write(mbeanServer,
|
||||
new ObjectName("java.lang:type=Memory"), null, false);
|
||||
jsonBeanWriter.write(mbeanServer,
|
||||
new ObjectName("Hadoop:service=HBase,name=RegionServer,sub=IPC"), null, false);
|
||||
jsonBeanWriter.write(mbeanServer,
|
||||
new ObjectName("Hadoop:service=HBase,name=RegionServer,sub=Replication"), null, false);
|
||||
jsonBeanWriter.write(mbeanServer,
|
||||
new ObjectName("Hadoop:service=HBase,name=RegionServer,sub=Server"), null, false);
|
||||
}
|
||||
}
|
||||
sw.close();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump out all registered mbeans as json on System.out.
|
||||
* @throws IOException
|
||||
* @throws MalformedObjectNameException
|
||||
*/
|
||||
public static void dumpAllBeans() throws IOException, MalformedObjectNameException {
|
||||
try (PrintWriter writer = new PrintWriter(System.out)) {
|
||||
JSONBean dumper = new JSONBean();
|
||||
try (JSONBean.Writer jsonBeanWriter = dumper.open(writer)) {
|
||||
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
jsonBeanWriter.write(mbeanServer, new ObjectName("*:*"), null, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, MalformedObjectNameException {
|
||||
String str = dumpRegionServerMetrics();
|
||||
System.out.println(str);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue