Skip to content

Commit 8719979

Browse files
committed
[jmxattribute] generate alias from regexp match
[jmxattribute] generate alias from regexp match
2 parents 8689358 + a4a7f91 commit 8719979

File tree

5 files changed

+154
-59
lines changed

5 files changed

+154
-59
lines changed

src/main/java/org/datadog/jmxfetch/JMXAttribute.java

+108-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
import java.util.ArrayList;
55
import java.util.Arrays;
66
import java.util.Collection;
7+
import java.util.concurrent.atomic.AtomicInteger;
8+
import java.util.concurrent.atomic.AtomicLong;
79
import java.util.HashMap;
810
import java.util.LinkedHashMap;
911
import java.util.LinkedList;
1012
import java.util.List;
1113
import java.util.Map;
12-
import java.util.concurrent.atomic.AtomicInteger;
13-
import java.util.concurrent.atomic.AtomicLong;
14+
import java.util.regex.Matcher;
1415
import java.util.regex.Pattern;
1516

1617
import javax.management.AttributeNotFoundException;
@@ -24,13 +25,16 @@
2425

2526
public abstract class JMXAttribute {
2627

28+
protected static final String ALIAS = "alias";
29+
protected static final String METRIC_TYPE = "metric_type";
2730
private final static Logger LOGGER = Logger.getLogger(JMXAttribute.class.getName());
2831
private static final List<String> EXCLUDED_BEAN_PARAMS = Arrays.asList("domain", "domain_regex", "bean_name", "bean", "bean_regex", "attribute");
2932
private static final String FIRST_CAP_PATTERN = "(.)([A-Z][a-z]+)";
3033
private static final String ALL_CAP_PATTERN = "([a-z0-9])([A-Z])";
3134
private static final String METRIC_REPLACEMENT = "([^a-zA-Z0-9_.]+)|(^[^a-zA-Z]+)";
3235
private static final String DOT_UNDERSCORE = "_*\\._*";
3336
protected static final String CASSANDRA_DOMAIN = "org.apache.cassandra.metrics";
37+
3438
private MBeanAttributeInfo attribute;
3539
private Connection connection;
3640
private ObjectName beanName;
@@ -351,6 +355,108 @@ MBeanAttributeInfo getAttribute() {
351355
return attribute;
352356
}
353357

358+
public ObjectName getBeanName() {
359+
return beanName;
360+
}
361+
362+
/**
363+
* Get attribute alias.
364+
*
365+
* In order, tries to:
366+
* * Use `alias_match` to generate an alias with a regular expression
367+
* * Use `alias` directly
368+
* * Create an generic alias prefixed with user's `metric_prefix` preference or default to `jmx`
369+
*
370+
* Argument(s):
371+
* * (Optional) `field`
372+
* `Null` for `JMXSimpleAttribute`.
373+
*/
374+
protected String getAlias(String field) {
375+
String alias = null;
376+
377+
Filter include = getMatchingConf().getInclude();
378+
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();
379+
380+
String fullAttributeName =(field!=null)?(getAttribute().getName() + "." + field):(getAttribute().getName());
381+
382+
if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
383+
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
384+
alias = getUserAlias(attribute, fullAttributeName);
385+
} else if (conf.get("metric_prefix") != null) {
386+
alias = conf.get("metric_prefix") + "." + getDomain() + "." + fullAttributeName;
387+
} else if (getDomain().startsWith("org.apache.cassandra")) {
388+
alias = getCassandraAlias();
389+
}
390+
391+
//If still null - generate generic alias,
392+
if (alias == null) {
393+
alias = "jmx." + getDomain() + "." + fullAttributeName;
394+
}
395+
alias = convertMetricName(alias);
396+
return alias;
397+
}
398+
399+
/**
400+
* Metric name aliasing specific to Cassandra.
401+
*
402+
* * (Default) `cassandra_aliasing` == False.
403+
* Legacy aliasing: drop `org.apache` prefix.
404+
* * `cassandra_aliasing` == True
405+
* Comply with CASSANDRA-4009
406+
*
407+
* More information: https://issues.apache.org/jira/browse/CASSANDRA-4009
408+
*/
409+
private String getCassandraAlias() {
410+
if (renameCassandraMetrics()) {
411+
Map<String, String> beanParameters = getBeanParameters();
412+
String metricName = beanParameters.get("name");
413+
String attributeName = getAttributeName();
414+
if (attributeName.equals("Value")) {
415+
return "cassandra." + metricName;
416+
}
417+
return "cassandra." + metricName + "." + attributeName;
418+
}
419+
//Deprecated Cassandra metric. Remove domain prefix.
420+
return getDomain().replace("org.apache.", "") + "." + getAttributeName();
421+
}
422+
423+
/**
424+
* Retrieve user defined alias. Substitute regular expression named groups.
425+
*
426+
* Example:
427+
* ```
428+
* bean: org.datadog.jmxfetch.test:foo=Bar,qux=Baz
429+
* attribute:
430+
* toto:
431+
* alias: my.metric.$foo.$attribute
432+
* ```
433+
* returns a metric name `my.metric.bar.toto`
434+
*/
435+
private String getUserAlias(LinkedHashMap<String, LinkedHashMap<String, String>> attribute, String fullAttributeName){
436+
String alias = attribute.get(fullAttributeName).get(ALIAS);
437+
438+
// Bean parameters
439+
for (Map.Entry<String, String> param : beanParameters.entrySet()) {
440+
alias = alias.replace("$" + param.getKey(), param.getValue());
441+
}
442+
443+
// Attribute & domain
444+
alias = alias.replace("$attribute", fullAttributeName);
445+
alias = alias.replace("$domain", domain);
446+
447+
return alias;
448+
}
449+
450+
/**
451+
* Overload `getAlias` method.
452+
*
453+
* Note: used for `JMXSimpleAttribute` only, as `field` is null.
454+
*/
455+
protected String getAlias(){
456+
return getAlias(null);
457+
}
458+
459+
354460
@SuppressWarnings("unchecked")
355461
protected String[] getTags() {
356462
if(tags != null) {

src/main/java/org/datadog/jmxfetch/JMXComplexAttribute.java

-16
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
@SuppressWarnings("unchecked")
2020
public class JMXComplexAttribute extends JMXAttribute {
2121

22-
public static final String ALIAS = "alias";
23-
public static final String METRIC_TYPE = "metric_type";
2422
private HashMap<String, HashMap<String, Object>> subAttributeList;
2523

2624
public JMXComplexAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
@@ -112,20 +110,6 @@ private Object getMetricType(String subAttribute) {
112110
return metricType;
113111
}
114112

115-
private String getAlias(String subAttribute) {
116-
String subAttributeName = getAttribute().getName() + "." + subAttribute;
117-
118-
Filter include = getMatchingConf().getInclude();
119-
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();
120-
if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
121-
return ((LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute())).get(subAttributeName).get(ALIAS);
122-
} else if (conf.get("metric_prefix") != null) {
123-
return conf.get("metric_prefix") + "." + getDomain() + "." + subAttributeName;
124-
}
125-
return "jmx." + getDomain() + "." + subAttributeName;
126-
}
127-
128-
129113
@Override
130114
public boolean match(Configuration configuration) {
131115
if (!matchDomain(configuration)

src/main/java/org/datadog/jmxfetch/JMXSimpleAttribute.java

+1-40
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
@SuppressWarnings("unchecked")
1818
public class JMXSimpleAttribute extends JMXAttribute {
19-
20-
private String alias;
2119
private String metricType;
2220

2321
public JMXSimpleAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
@@ -39,7 +37,6 @@ public LinkedList<HashMap<String, Object>> getMetrics() throws AttributeNotFound
3937
return metrics;
4038
}
4139

42-
4340
public boolean match(Configuration configuration) {
4441
return matchDomain(configuration)
4542
&& matchBean(configuration)
@@ -82,49 +79,13 @@ private boolean matchAttribute(Configuration configuration) {
8279
return false;
8380
}
8481

85-
private String getAlias() {
86-
Filter include = getMatchingConf().getInclude();
87-
LinkedHashMap<String, Object> conf = getMatchingConf().getConf();
88-
if (alias != null) {
89-
return alias;
90-
} else if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
91-
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
92-
alias = attribute.get(getAttribute().getName()).get("alias");
93-
} else if (conf.get("metric_prefix") != null) {
94-
alias = conf.get("metric_prefix") + "." + getDomain() + "." + getAttributeName();
95-
} else if (getDomain().startsWith("org.apache.cassandra")) {
96-
alias = getCassandraAlias();
97-
}
98-
99-
//If still null - generate generic alias,
100-
if (alias == null) {
101-
alias = "jmx." + getDomain() + "." + getAttributeName();
102-
}
103-
alias = convertMetricName(alias);
104-
return alias;
105-
}
106-
107-
private String getCassandraAlias() {
108-
if (renameCassandraMetrics()) {
109-
Map<String, String> beanParameters = getBeanParameters();
110-
String metricName = beanParameters.get("name");
111-
String attributeName = getAttributeName();
112-
if (attributeName.equals("Value")) {
113-
return "cassandra." + metricName;
114-
}
115-
return "cassandra." + metricName + "." + attributeName;
116-
}
117-
//Deprecated Cassandra metric. Remove domain prefix.
118-
return getDomain().replace("org.apache.", "") + "." + getAttributeName();
119-
}
120-
12182
private String getMetricType() {
12283
Filter include = getMatchingConf().getInclude();
12384
if (metricType != null) {
12485
return metricType;
12586
} else if (include.getAttribute() instanceof LinkedHashMap<?, ?>) {
12687
LinkedHashMap<String, LinkedHashMap<String, String>> attribute = (LinkedHashMap<String, LinkedHashMap<String, String>>) (include.getAttribute());
127-
metricType = attribute.get(getAttributeName()).get("metric_type");
88+
metricType = attribute.get(getAttributeName()).get(METRIC_TYPE);
12889
if (metricType == null) {
12990
metricType = attribute.get(getAttributeName()).get("type");
13091
}

src/test/java/org/datadog/jmxfetch/TestApp.java

+30-1
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,39 @@ public void testBeanTags() throws Exception {
4646

4747
assertMetric("this.is.100", tags, 6);
4848
}
49+
/**
50+
* Generate metric aliases from a `alias_match` regular expression.
51+
*/
52+
@Test
53+
public void testRegexpAliasing() throws Exception {
54+
// Expose MBeans
55+
registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz");
56+
initApplication("jmx_alias_match.yaml");
57+
58+
// Collect metrics
59+
run();
60+
LinkedList<HashMap<String, Object>> metrics = getMetrics();
61+
62+
// Assertions
63+
64+
// 15 metrics = 13 from `java.lang` + 2 from the user configuration file
65+
assertEquals(15, metrics.size());
66+
67+
// Metric aliases are generated from `alias_match`
68+
List<String> tags = Arrays.asList(
69+
"jmx_domain:org.datadog.jmxfetch.test",
70+
"instance:jmx_test_instance",
71+
"foo:Bar",
72+
"qux:Baz"
73+
);
74+
75+
assertMetric("this.is.100.bar.baz", tags, 4);
76+
assertMetric("org.datadog.jmxfetch.test.baz.hashmap.thisis0", tags, 4);
77+
}
4978

5079
/**
5180
* Check JMXFetch Cassandra metric aliasing logic, i.e. compliant with CASSANDRA-4009
52-
* when `cassandra4009` flag is enabled, or default.
81+
* when `cassandra_aliasing` flag is enabled, or default.
5382
*
5483
* More information: https://issues.apache.org/jira/browse/CASSANDRA-4009
5584
*/
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
init_config:
2+
3+
instances:
4+
- process_name_regex: .*surefire.*
5+
name: jmx_test_instance
6+
conf:
7+
- include:
8+
domain: org.datadog.jmxfetch.test
9+
attribute:
10+
ShouldBe100:
11+
metric_type: gauge
12+
alias: this.is.100.$foo.$qux
13+
Hashmap.thisis0:
14+
metric_type: gauge
15+
alias: $domain.$qux.$attribute

0 commit comments

Comments
 (0)