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

[jmxattribute] generate alias from regexp match #97

Merged
merged 2 commits into from
Apr 29, 2016
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
110 changes: 108 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 @@ -351,6 +355,108 @@ MBeanAttributeInfo getAttribute() {
return attribute;
}

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());
alias = getUserAlias(attribute, fullAttributeName);
} 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();
}

/**
* Retrieve user defined alias. Substitute regular expression named groups.
*
* Example:
* ```
* bean: org.datadog.jmxfetch.test:foo=Bar,qux=Baz
* attribute:
* toto:
* alias: my.metric.$foo.$attribute
* ```
* returns a metric name `my.metric.bar.toto`
*/
private String getUserAlias(LinkedHashMap<String, LinkedHashMap<String, String>> attribute, String fullAttributeName){
String alias = attribute.get(fullAttributeName).get(ALIAS);

// Bean parameters
for (Map.Entry<String, String> param : beanParameters.entrySet()) {
alias = alias.replace("$" + param.getKey(), param.getValue());
}

// Attribute & domain
alias = alias.replace("$attribute", fullAttributeName);
alias = alias.replace("$domain", domain);

return alias;
}

/**
* 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
41 changes: 1 addition & 40 deletions src/main/java/org/datadog/jmxfetch/JMXSimpleAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,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 @@ -39,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 @@ -82,49 +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());
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
31 changes: 30 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,39 @@ 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.baz", tags, 4);
assertMetric("org.datadog.jmxfetch.test.baz.hashmap.thisis0", 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
15 changes: 15 additions & 0 deletions src/test/resources/jmx_alias_match.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_instance
conf:
- include:
domain: org.datadog.jmxfetch.test
attribute:
ShouldBe100:
metric_type: gauge
alias: this.is.100.$foo.$qux
Hashmap.thisis0:
metric_type: gauge
alias: $domain.$qux.$attribute