Skip to content

Commit

Permalink
Add class name and class regex filters (#277)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreYang authored Mar 3, 2020
1 parent e7f4cfb commit 3485cb3
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 16 deletions.
7 changes: 7 additions & 0 deletions src/main/java/org/datadog/jmxfetch/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ public MBeanAttributeInfo[] getAttributesForBean(ObjectName beanName)
return mbs.getMBeanInfo(beanName).getAttributes();
}

/** Gets class name for matching bean name. */
public String getClassNameForBean(ObjectName beanName)
throws InstanceNotFoundException, IntrospectionException, ReflectionException,
IOException {
return mbs.getMBeanInfo(beanName).getClassName();
}

/** Queries beans on specific scope. Returns set of matching query names.. */
public Set<ObjectName> queryNames(ObjectName name) throws IOException {
String scope = (name != null) ? name.toString() : "*:*";
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/datadog/jmxfetch/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class Filter {
Map<String, Object> filter;
Pattern domainRegex;
Pattern classNameRegex;
List<Pattern> beanRegexes = null;
List<String> excludeTags = null;
Map<String, String> additionalTags = null;
Expand Down Expand Up @@ -148,6 +149,23 @@ public Pattern getDomainRegex() {
return this.domainRegex;
}

public String getClassName() {
return (String) filter.get("class");
}

public Pattern getClassNameRegex() {
if (this.filter.get("class_regex") == null) {
return null;
}

if (this.classNameRegex == null) {
this.classNameRegex = Pattern.compile((String) this.filter.get("class_regex"));
}

return this.classNameRegex;
}


public Object getAttribute() {
return filter.get("attribute");
}
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/org/datadog/jmxfetch/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -478,21 +478,24 @@ private void getMatchingAttributes() throws IOException {
break;
}
}
String className;
MBeanAttributeInfo[] attributeInfos;

try {
log.debug("Getting class name for bean: " + beanName);
className = connection.getClassNameForBean(beanName);

// Get all the attributes for bean_name
log.debug("Getting attributes for bean: " + beanName);
attributeInfos = connection.getAttributesForBean(beanName);
} catch (IOException e) {
// we should not continue
log.warn("Cannot get bean attributes " + e.getMessage());
log.warn("Cannot get bean attributes or class name: " + e.getMessage());
if (e.getMessage() == connection.CLOSED_CLIENT_CAUSE) {
throw e;
}
continue;
} catch (Exception e) {
log.warn("Cannot get bean attributes " + e.getMessage());
log.warn("Cannot get bean attributes or class name: " + e.getMessage());
continue;
}

Expand Down Expand Up @@ -523,6 +526,7 @@ private void getMatchingAttributes() throws IOException {
new JmxSimpleAttribute(
attributeInfo,
beanName,
className,
instanceName,
checkName,
connection,
Expand All @@ -540,6 +544,7 @@ private void getMatchingAttributes() throws IOException {
new JmxComplexAttribute(
attributeInfo,
beanName,
className,
instanceName,
checkName,
connection,
Expand All @@ -556,6 +561,7 @@ private void getMatchingAttributes() throws IOException {
new JmxTabularAttribute(
attributeInfo,
beanName,
className,
instanceName,
checkName,
connection,
Expand Down
43 changes: 34 additions & 9 deletions src/main/java/org/datadog/jmxfetch/JmxAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public abstract class JmxAttribute {
"bean_name",
"bean",
"bean_regex",
"class",
"class_regex",
"attribute",
"exclude_tags",
"tags");
Expand All @@ -47,6 +49,7 @@ public abstract class JmxAttribute {
private Connection connection;
private ObjectName beanName;
private String domain;
private String className;
private String beanStringName;
private Map<String, String> beanParameters;
private String attributeName;
Expand All @@ -61,6 +64,7 @@ public abstract class JmxAttribute {
JmxAttribute(
MBeanAttributeInfo attribute,
ObjectName beanName,
String className,
String instanceName,
String checkName,
Connection connection,
Expand All @@ -69,6 +73,7 @@ public abstract class JmxAttribute {
boolean emptyDefaultHostname) {
this.attribute = attribute;
this.beanName = beanName;
this.className = className;
this.matchingConf = null;
this.connection = connection;
this.attributeName = attribute.getName();
Expand Down Expand Up @@ -268,19 +273,39 @@ Object getJmxValue()
}

boolean matchDomain(Configuration conf) {
String includeDomain = conf.getInclude().getDomain();
Pattern includeDomainRegex = conf.getInclude().getDomainRegex();

return (includeDomain == null || includeDomain.equals(domain))
&& (includeDomainRegex == null || includeDomainRegex.matcher(domain).matches());
return includeMatchName(domain,
conf.getInclude().getDomain(),
conf.getInclude().getDomainRegex());
}

boolean excludeMatchDomain(Configuration conf) {
String excludeDomain = conf.getExclude().getDomain();
Pattern excludeDomainRegex = conf.getExclude().getDomainRegex();
return excludeMatchName(domain,
conf.getExclude().getDomain(),
conf.getExclude().getDomainRegex());
}


boolean matchClassName(Configuration conf) {
return includeMatchName(className,
conf.getInclude().getClassName(),
conf.getInclude().getClassNameRegex());
}


boolean excludeMatchClassName(Configuration conf) {
return excludeMatchName(className,
conf.getExclude().getClassName(),
conf.getExclude().getClassNameRegex());
}

private boolean includeMatchName(String name, String includeName, Pattern includeNameRegex) {
return (includeName == null || includeName.equals(name))
&& (includeNameRegex == null || includeNameRegex.matcher(name).matches());
}

return excludeDomain != null && excludeDomain.equals(domain)
|| excludeDomainRegex != null && excludeDomainRegex.matcher(domain).matches();
private boolean excludeMatchName(String name, String excludeName, Pattern excludeNameRegex) {
return (excludeName != null && excludeName.equals(name))
|| (excludeNameRegex != null && excludeNameRegex.matcher(name).matches());
}

Object convertMetricValue(Object metricValue, String field) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/datadog/jmxfetch/JmxComplexAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class JmxComplexAttribute extends JmxSubAttribute {
public JmxComplexAttribute(
MBeanAttributeInfo attribute,
ObjectName beanName,
String className,
String instanceName,
String checkName,
Connection connection,
Expand All @@ -30,6 +31,7 @@ public JmxComplexAttribute(
super(
attribute,
beanName,
className,
instanceName,
checkName,
connection,
Expand Down Expand Up @@ -88,8 +90,10 @@ private Object getValue(String subAttribute)
@Override
public boolean match(Configuration configuration) {
if (!matchDomain(configuration)
|| !matchClassName(configuration)
|| !matchBean(configuration)
|| excludeMatchDomain(configuration)
|| excludeMatchClassName(configuration)
|| excludeMatchBean(configuration)) {
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/datadog/jmxfetch/JmxSimpleAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class JmxSimpleAttribute extends JmxAttribute {
public JmxSimpleAttribute(
MBeanAttributeInfo attribute,
ObjectName beanName,
String className,
String instanceName,
String checkName,
Connection connection,
Expand All @@ -28,6 +29,7 @@ public JmxSimpleAttribute(
super(
attribute,
beanName,
className,
instanceName,
checkName,
connection,
Expand All @@ -54,9 +56,11 @@ public List<Metric> getMetrics()
/** Returns whether an attribute matches in a configuration spec. */
public boolean match(Configuration configuration) {
return matchDomain(configuration)
&& matchClassName(configuration)
&& matchBean(configuration)
&& matchAttribute(configuration)
&& !(excludeMatchDomain(configuration)
|| excludeMatchClassName(configuration)
|| excludeMatchBean(configuration)
|| excludeMatchAttribute(configuration));
}
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/org/datadog/jmxfetch/JmxSubAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
abstract class JmxSubAttribute extends JmxAttribute {
private Map<String, Metric> cachedMetrics = new HashMap<String, Metric>();

public JmxSubAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
String checkName, Connection connection, Map<String, String> instanceTags,
boolean cassandraAliasing, boolean emptyDefaultHostname) {
super(attribute, beanName, instanceName, checkName, connection, instanceTags,
public JmxSubAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String className,
String instanceName, String checkName, Connection connection,
Map<String, String> instanceTags, boolean cassandraAliasing,
boolean emptyDefaultHostname) {
super(attribute, beanName, className, instanceName, checkName, connection, instanceTags,
cassandraAliasing, emptyDefaultHostname);
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/org/datadog/jmxfetch/JmxTabularAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class JmxTabularAttribute extends JmxSubAttribute {
public JmxTabularAttribute(
MBeanAttributeInfo attribute,
ObjectName beanName,
String className,
String instanceName,
String checkName,
Connection connection,
Expand All @@ -39,6 +40,7 @@ public JmxTabularAttribute(
super(
attribute,
beanName,
className,
instanceName,
checkName,
connection,
Expand Down Expand Up @@ -233,8 +235,10 @@ private Object getValue(String key, String subAttribute)
@Override
public boolean match(Configuration configuration) {
if (!matchDomain(configuration)
|| !matchClassName(configuration)
|| !matchBean(configuration)
|| excludeMatchDomain(configuration)
|| excludeMatchClassName(configuration)
|| excludeMatchBean(configuration)) {
return false;
}
Expand Down
59 changes: 59 additions & 0 deletions src/test/java/org/datadog/jmxfetch/TestApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,65 @@ public void testDomainRegex() throws Exception {
assertEquals(15, metrics.size());
}

@Test
public void testClassInclude() throws Exception {
// We expose a few metrics through JMX
registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.includeme:type=AType");
initApplication("jmx_class_include.yaml");

// Collecting metrics
run();
List<Map<String, Object>> metrics = getMetrics();

// First filter 29 = 13 metrics from java.lang + 16 metrics implicitly defined
assertEquals(29, metrics.size());
}

@Test
public void testClassExclude() throws Exception {
class SimpleTestJavaAnotherApp extends SimpleTestJavaApp {

}

// We expose a few metrics through JMX
registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.includeme:type=AType");
registerMBean(new SimpleTestJavaAnotherApp(), "org.datadog.jmxfetch.includeme2:type=AnotherType");

// Initializing application
initApplication("jmx_class_exclude.yaml");

// Collecting metrics
run();
List<Map<String, Object>> metrics = getMetrics();

// First filter 14 = 13 metrics from java.lang + 2 metrics explicitly define- 1 implicitly
// defined in the exclude section
assertEquals(14, metrics.size());
}

@Test
public void testClassRegex() throws Exception {
class SimpleTestJavaAppIncludeMe extends SimpleTestJavaApp { }
class SimpleTestJavaAppIncludeMeToo extends SimpleTestJavaApp { }
class SimpleTestJavaAppIncludeMeNotMeX extends SimpleTestJavaApp { }

// We expose a few metrics through JMX
registerMBean(new SimpleTestJavaAppIncludeMe(), "org.datadog.jmxfetch.includeme:type=AType");
registerMBean(new SimpleTestJavaAppIncludeMeToo(), "org.datadog.jmxfetch.includeme.too:type=AType");
registerMBean(new SimpleTestJavaAppIncludeMeNotMeX(), "org.datadog.jmxfetch.includeme.not.me:type=AType");

// Initializing application
initApplication("jmx_class_regex.yaml");

// Collecting metrics
run();
List<Map<String, Object>> metrics = getMetrics();

// First filter 15 = 13 metrics from java.lang + 3 metrics explicitly defined - 1 implicitly
// defined in exclude section
assertEquals(15, metrics.size());
}

@Test
public void testParameterMatch() throws Exception {
// Do not match beans which do not contain types specified in the conf
Expand Down
13 changes: 13 additions & 0 deletions src/test/resources/jmx_class_exclude.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_instance
conf:
- include:
attribute:
ShouldBe100:
metric_type: gauge
alias: this.is.100
exclude:
class: org.datadog.jmxfetch.TestApp$1SimpleTestJavaAnotherApp
8 changes: 8 additions & 0 deletions src/test/resources/jmx_class_include.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_instance
conf:
- include:
class: org.datadog.jmxfetch.SimpleTestJavaApp
14 changes: 14 additions & 0 deletions src/test/resources/jmx_class_regex.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_instance
conf:
- include:
class_regex: .*IncludeMe.*
attribute:
ShouldBe100:
metric_type: gauge
alias: this.is.100
exclude:
class_regex: .*Me$

0 comments on commit 3485cb3

Please sign in to comment.