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

Add class name and class regex filters #277

Merged
merged 9 commits into from
Mar 3, 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
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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self: I was going to say these new log lines perhaps didn't add much value, but since we're calling methods on connection we can probably trigger an IOException with these, so it's probably justified.

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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍰

// 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$