Skip to content

Commit

Permalink
[jmxattribute] unique getAlias method & test
Browse files Browse the repository at this point in the history
* Refactor `getAlias` logic from `JMXSimpleAttribute` &
  `JMXComplexAttribute` to `JMXAttribute`
  * Add `alias_match` support to `JMXComplexAttribute`(s)
* Test coverage `alias_match`
  • Loading branch information
yannmh committed Apr 27, 2016
1 parent 737050f commit 5e80d71
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 69 deletions.
87 changes: 85 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JMXAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.management.AttributeNotFoundException;
Expand All @@ -24,13 +25,16 @@

public abstract class JMXAttribute {

protected static final String ALIAS = "alias";
protected static final String METRIC_TYPE = "metric_type";
private final static Logger LOGGER = Logger.getLogger(JMXAttribute.class.getName());
private static final List<String> EXCLUDED_BEAN_PARAMS = Arrays.asList("domain", "domain_regex", "bean_name", "bean", "bean_regex", "attribute");
private static final String FIRST_CAP_PATTERN = "(.)([A-Z][a-z]+)";
private static final String ALL_CAP_PATTERN = "([a-z0-9])([A-Z])";
private static final String METRIC_REPLACEMENT = "([^a-zA-Z0-9_.]+)|(^[^a-zA-Z]+)";
private static final String DOT_UNDERSCORE = "_*\\._*";
protected static final String CASSANDRA_DOMAIN = "org.apache.cassandra.metrics";

private MBeanAttributeInfo attribute;
private Connection connection;
private ObjectName beanName;
Expand Down Expand Up @@ -355,6 +359,85 @@ public ObjectName getBeanName() {
return beanName;
}

/**
* Get attribute alias.
*
* In order, tries to:
* * Use `alias_match` to generate an alias with a regular expression
* * Use `alias` directly
* * Create an generic alias prefixed with user's `metric_prefix` preference or default to `jmx`
*
* Argument(s):
* * (Optional) `field`
* `Null` for `JMXSimpleAttribute`.
*/
protected String getAlias(String field) {
String alias = null;

Filter include = getMatchingConf().getInclude();
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();

String fullAttributeName =(field!=null)?(getAttribute().getName() + "." + field):(getAttribute().getName());

if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
if (attribute.get(fullAttributeName).get("alias_match") != null) {
Pattern p = Pattern.compile(attribute.get(fullAttributeName).get("alias_match"));
Matcher m = p.matcher(getBeanName().getCanonicalName() + "." + fullAttributeName);
if (m.find()) {
alias = m.replaceFirst(attribute.get(fullAttributeName).get(ALIAS));
}
} else {
alias = attribute.get(fullAttributeName).get(ALIAS);
}
} else if (conf.get("metric_prefix") != null) {
alias = conf.get("metric_prefix") + "." + getDomain() + "." + fullAttributeName;
} else if (getDomain().startsWith("org.apache.cassandra")) {
alias = getCassandraAlias();
}

//If still null - generate generic alias,
if (alias == null) {
alias = "jmx." + getDomain() + "." + fullAttributeName;
}
alias = convertMetricName(alias);
return alias;
}

/**
* Metric name aliasing specific to Cassandra.
*
* * (Default) `cassandra_aliasing` == False.
* Legacy aliasing: drop `org.apache` prefix.
* * `cassandra_aliasing` == True
* Comply with CASSANDRA-4009
*
* More information: https://issues.apache.org/jira/browse/CASSANDRA-4009
*/
private String getCassandraAlias() {
if (renameCassandraMetrics()) {
Map<String, String> beanParameters = getBeanParameters();
String metricName = beanParameters.get("name");
String attributeName = getAttributeName();
if (attributeName.equals("Value")) {
return "cassandra." + metricName;
}
return "cassandra." + metricName + "." + attributeName;
}
//Deprecated Cassandra metric. Remove domain prefix.
return getDomain().replace("org.apache.", "") + "." + getAttributeName();
}

/**
* Overload `getAlias` method.
*
* Note: used for `JMXSimpleAttribute` only, as `field` is null.
*/
protected String getAlias(){
return getAlias(null);
}


@SuppressWarnings("unchecked")
protected String[] getTags() {
if(tags != null) {
Expand Down
16 changes: 0 additions & 16 deletions src/main/java/org/datadog/jmxfetch/JMXComplexAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
@SuppressWarnings("unchecked")
public class JMXComplexAttribute extends JMXAttribute {

public static final String ALIAS = "alias";
public static final String METRIC_TYPE = "metric_type";
private HashMap<String, HashMap<String, Object>> subAttributeList;

public JMXComplexAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Expand Down Expand Up @@ -112,20 +110,6 @@ private Object getMetricType(String subAttribute) {
return metricType;
}

private String getAlias(String subAttribute) {
String subAttributeName = getAttribute().getName() + "." + subAttribute;

Filter include = getMatchingConf().getInclude();
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();
if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
return ((LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute())).get(subAttributeName).get(ALIAS);
} else if (conf.get("metric_prefix") != null) {
return conf.get("metric_prefix") + "." + getDomain() + "." + subAttributeName;
}
return "jmx." + getDomain() + "." + subAttributeName;
}


@Override
public boolean match(Configuration configuration) {
if (!matchDomain(configuration)
Expand Down
51 changes: 1 addition & 50 deletions src/main/java/org/datadog/jmxfetch/JMXSimpleAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
Expand All @@ -18,8 +16,6 @@

@SuppressWarnings("unchecked")
public class JMXSimpleAttribute extends JMXAttribute {

private String alias;
private String metricType;

public JMXSimpleAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Expand All @@ -41,7 +37,6 @@ public LinkedList<HashMap<String, Object>> getMetrics() throws AttributeNotFound
return metrics;
}


public boolean match(Configuration configuration) {
return matchDomain(configuration)
&& matchBean(configuration)
Expand Down Expand Up @@ -84,57 +79,13 @@ private boolean matchAttribute(Configuration configuration) {
return false;
}

private String getAlias() {
Filter include = getMatchingConf().getInclude();
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();
if (alias != null) {
return alias;
} else if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
if (attribute.get(getAttribute().getName()).get("alias_match") != null) {
Pattern p = Pattern.compile(attribute.get(getAttribute().getName()).get("alias_match"));
Matcher m = p.matcher(getBeanName().getCanonicalName() + "." + getAttribute().getName());
if (m.find()) {
alias = m.replaceFirst(attribute.get(getAttribute().getName()).get("alias"));
}
} else {
alias = attribute.get(getAttribute().getName()).get("alias");
}
} else if (conf.get("metric_prefix") != null) {
alias = conf.get("metric_prefix") + "." + getDomain() + "." + getAttributeName();
} else if (getDomain().startsWith("org.apache.cassandra")) {
alias = getCassandraAlias();
}

//If still null - generate generic alias,
if (alias == null) {
alias = "jmx." + getDomain() + "." + getAttributeName();
}
alias = convertMetricName(alias);
return alias;
}

private String getCassandraAlias() {
if (renameCassandraMetrics()) {
Map<String, String> beanParameters = getBeanParameters();
String metricName = beanParameters.get("name");
String attributeName = getAttributeName();
if (attributeName.equals("Value")) {
return "cassandra." + metricName;
}
return "cassandra." + metricName + "." + attributeName;
}
//Deprecated Cassandra metric. Remove domain prefix.
return getDomain().replace("org.apache.", "") + "." + getAttributeName();
}

private String getMetricType() {
Filter include = getMatchingConf().getInclude();
if (metricType != null) {
return metricType;
} else if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
metricType = attribute.get(getAttributeName()).get("metric_type");
metricType = attribute.get(getAttributeName()).get(METRIC_TYPE);
if (metricType == null) {
metricType = attribute.get(getAttributeName()).get("type");
}
Expand Down
32 changes: 31 additions & 1 deletion src/test/java/org/datadog/jmxfetch/TestApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,40 @@ public void testBeanTags() throws Exception {

assertMetric("this.is.100", tags, 6);
}
/**
* Generate metric aliases from a `alias_match` regular expression.
*/
@Test
public void testRegexpAliasing() throws Exception {
// Expose MBeans
registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz");
initApplication("jmx_alias_match.yaml");

// Collect metrics
run();
LinkedList<HashMap<String, Object>> metrics = getMetrics();

// Assertions

// 15 metrics = 13 from `java.lang` + 2 from the user configuration file
assertEquals(15, metrics.size());

// Metric aliases are generated from `alias_match`
List<String> tags = Arrays.asList(
"jmx_domain:org.datadog.jmxfetch.test",
"instance:jmx_test_instance",
"foo:Bar",
"qux:Baz"
);

assertMetric("this.is.100.bar", tags, 4);
assertMetric("baz.this.is.0", tags, 4);

}

/**
* Check JMXFetch Cassandra metric aliasing logic, i.e. compliant with CASSANDRA-4009
* when `cassandra4009` flag is enabled, or default.
* when `cassandra_aliasing` flag is enabled, or default.
*
* More information: https://issues.apache.org/jira/browse/CASSANDRA-4009
*/
Expand Down
17 changes: 17 additions & 0 deletions src/test/resources/jmx_alias_match.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_instance
conf:
- include:
domain: org.datadog.jmxfetch.test
attribute:
ShouldBe100:
metric_type: gauge
alias_match: '[a-z.]*:foo=([a-zA-Z]*).*'
alias: this.is.100.$1
Hashmap.thisis0:
metric_type: gauge
alias_match: '.*qux=([a-zA-Z]*).*'
alias: $1.this.is.0

0 comments on commit 5e80d71

Please sign in to comment.