Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HBASE-25002 Create simple pattern matching query for retrieving metri… #2398

Merged
merged 1 commit into from
Sep 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@
* </code> will return the cluster id of the namenode mxbean.
* </p>
* <p>
* If we are not sure on the exact attribute and we want to get all the attributes that match one or
* more given pattern then the format is
* <code>http://.../jmx?get=MXBeanName::*[RegExp1],*[RegExp2]</code>
* </p>
* <p>
* For example
* <code>
* <p>
* http://../jmx?get=Hadoop:service=HBase,name=RegionServer,sub=Tables::[a-zA-z_0-9]*memStoreSize
* </p>
* <p>
* http://../jmx?get=Hadoop:service=HBase,name=RegionServer,sub=Tables::[a-zA-z_0-9]*memStoreSize,[a-zA-z_0-9]*storeFileSize
* </p>
* </code>
* </p>
* If the <code>qry</code> or the <code>get</code> parameter is not formatted
* correctly then a 400 BAD REQUEST http response code will be returned.
* </p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Pattern;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
Expand All @@ -40,18 +42,20 @@
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.TabularData;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.hbase.thirdparty.com.google.gson.Gson;
import org.apache.hbase.thirdparty.com.google.gson.stream.JsonWriter;
import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Utility for doing JSON and MBeans.
*/
@InterfaceAudience.Private
public class JSONBean {
private static final String COMMA = ",";
private static final String ASTERICK = "*";
private static final Logger LOG = LoggerFactory.getLogger(JSONBean.class);
private static final Gson GSON = GsonUtil.createGson().create();

Expand Down Expand Up @@ -125,11 +129,12 @@ public int write(MBeanServer mBeanServer, ObjectName qry, String attribute,
*/
private static int write(JsonWriter writer, MBeanServer mBeanServer, ObjectName qry,
String attribute, boolean description) throws IOException {
LOG.trace("Listing beans for " + qry);
LOG.debug("Listing beans for {}", qry);
Set<ObjectName> names = null;
names = mBeanServer.queryNames(qry, null);
writer.name("beans").beginArray();
Iterator<ObjectName> it = names.iterator();
Pattern[] matchingPattern = null;
while (it.hasNext()) {
ObjectName oname = it.next();
MBeanInfo minfo;
Expand All @@ -149,8 +154,24 @@ private static int write(JsonWriter writer, MBeanServer mBeanServer, ObjectName
code = (String) mBeanServer.getAttribute(oname, prs);
}
if (attribute != null) {
prs = attribute;
attributeinfo = mBeanServer.getAttribute(oname, prs);
String[] patternAttr = null;
if (attribute.contains(ASTERICK)) {
if (attribute.contains(COMMA)) {
patternAttr = attribute.split(COMMA);
} else {
patternAttr = new String[1];
patternAttr[0] = attribute;
}
matchingPattern = new Pattern[patternAttr.length];
for (int i = 0; i < patternAttr.length; i++) {
matchingPattern[i] = Pattern.compile(patternAttr[i]);
}
// nullify the attribute
attribute = null;
} else {
prs = attribute;
attributeinfo = mBeanServer.getAttribute(oname, prs);
}
}
} catch (RuntimeMBeanException e) {
// UnsupportedOperationExceptions happen in the normal course of business,
Expand Down Expand Up @@ -216,7 +237,7 @@ private static int write(JsonWriter writer, MBeanServer mBeanServer, ObjectName
} else {
MBeanAttributeInfo[] attrs = minfo.getAttributes();
for (int i = 0; i < attrs.length; i++) {
writeAttribute(writer, mBeanServer, oname, description, attrs[i]);
writeAttribute(writer, mBeanServer, oname, description, matchingPattern, attrs[i]);
}
}
writer.endObject();
Expand All @@ -226,7 +247,7 @@ private static int write(JsonWriter writer, MBeanServer mBeanServer, ObjectName
}

private static void writeAttribute(JsonWriter writer, MBeanServer mBeanServer, ObjectName oname,
boolean description, MBeanAttributeInfo attr) throws IOException {
boolean description, Pattern pattern[], MBeanAttributeInfo attr) throws IOException {
if (!attr.isReadable()) {
return;
}
Expand All @@ -237,6 +258,21 @@ private static void writeAttribute(JsonWriter writer, MBeanServer mBeanServer, O
if (attName.indexOf("=") >= 0 || attName.indexOf(":") >= 0 || attName.indexOf(" ") >= 0) {
return;
}

if (pattern != null) {
boolean matchFound = false;
for (Pattern compile : pattern) {
// check if we have any match
if (compile.matcher(attName).find()) {
matchFound = true;
break;
}
}
if (!matchFound) {
return;
}
}

String descriptionStr = description ? attr.getDescription() : null;
Object value = null;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ public static void assertReFind(String re, String value) {
assertTrue("'"+p+"' does not match "+value, m.find());
}

public static void assertNotFind(String re, String value) {
Pattern p = Pattern.compile(re);
Matcher m = p.matcher(value);
assertFalse("'"+p+"' should not match "+value, m.find());
}

@Test public void testQuery() throws Exception {
String result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Runtime"));
LOG.info("/jmx?qry=java.lang:type=Runtime RESULT: "+result);
Expand Down Expand Up @@ -116,7 +122,39 @@ public static void assertReFind(String re, String value) {
assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
assertReFind("\"committed\"\\s*:", result);
assertReFind("\\}\\);$", result);
}

@Test
public void testGetPattern() throws Exception {
// test to get an attribute of a mbean as JSONP
String result = readOutput(
new URL(baseUrl, "/jmx?get=java.lang:type=Memory::[a-zA-z_]*NonHeapMemoryUsage"));
LOG.info("/jmx RESULT: " + result);
assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
assertReFind("\"committed\"\\s*:", result);
assertReFind("\"NonHeapMemoryUsage\"\\s*:", result);
assertNotFind("\"HeapMemoryUsage\"\\s*:", result);

result =
readOutput(new URL(baseUrl, "/jmx?get=java.lang:type=Memory::[^Non]*HeapMemoryUsage"));
LOG.info("/jmx RESULT: " + result);
assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
assertReFind("\"committed\"\\s*:", result);
assertReFind("\"HeapMemoryUsage\"\\s*:", result);
assertNotFind("\"NonHeapHeapMemoryUsage\"\\s*:", result);

result = readOutput(new URL(baseUrl,
"/jmx?get=java.lang:type=Memory::[a-zA-z_]*HeapMemoryUsage,[a-zA-z_]*NonHeapMemoryUsage"));
LOG.info("/jmx RESULT: " + result);
assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
assertReFind("\"committed\"\\s*:", result);
}

@Test
public void testPatternMatching() throws Exception {
assertReFind("[a-zA-z_]*Table1[a-zA-z_]*memStoreSize",
"Namespace_default_table_Table1_metric_memStoreSize");
assertReFind("[a-zA-z_]*memStoreSize", "Namespace_default_table_Table1_metric_memStoreSize");
}

@Test
Expand Down