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

Support the empty_default_hostname instance field #184

Merged
merged 7 commits into from
Nov 30, 2018
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jdk:
- openjdk7

install: mvn install -Dhttps.protocols=TLSv1.2 -DskipTests=true -Dmaven.javadoc.skip=true -B -V
script: mvn test -B -Dhttps.protocols=TLSv1.2
script: mvn test -B -Dhttps.protocols=TLSv1.2 -Dlog4j.configuration=log4j.travis.properties

addons:
hostname: dd-jmxfetch-testhost
8 changes: 8 additions & 0 deletions log4j.travis.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
log4j.rootLogger=INFO,stdout
log4j.logger.com.endeca=INFO
# Logger for crawl metrics
log4j.logger.com.endeca.itl.web.metrics=INFO

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n
20 changes: 16 additions & 4 deletions src/main/java/org/datadog/jmxfetch/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class Instance {
private Connection connection;
private AppConfig appConfig;
private Boolean cassandraAliasing;
private boolean emptyDefaultHostname;


public Instance(Instance instance, AppConfig appConfig) {
Expand Down Expand Up @@ -97,6 +98,13 @@ public Instance(LinkedHashMap<String, Object> instanceMap, LinkedHashMap<String,
if (this.minCollectionPeriod == null && initConfig != null) {
this.minCollectionPeriod = (Integer) initConfig.get("min_collection_interval");
}

try {
this.emptyDefaultHostname = (Boolean) this.instanceMap.get("empty_default_hostname");
} catch (NullPointerException e) {
this.emptyDefaultHostname = false;
}

this.lastCollectionTime = 0;
this.lastRefreshTime = 0;
this.limitReached = false;
Expand Down Expand Up @@ -304,7 +312,7 @@ public LinkedList<HashMap<String, Object>> getMetrics() throws IOException {
}
return metrics;
}

public boolean timeToCollect() {
if (this.minCollectionPeriod == null) {
return true;
Expand Down Expand Up @@ -365,13 +373,13 @@ private void getMatchingAttributes() {
String attributeType = attributeInfo.getType();
if (SIMPLE_TYPES.contains(attributeType)) {
LOGGER.debug(ATTRIBUTE + beanName + " : " + attributeInfo + " has attributeInfo simple type");
jmxAttribute = new JMXSimpleAttribute(attributeInfo, beanName, instanceName, connection, tags, cassandraAliasing);
jmxAttribute = new JMXSimpleAttribute(attributeInfo, beanName, instanceName, connection, tags, cassandraAliasing, emptyDefaultHostname);
} else if (COMPOSED_TYPES.contains(attributeType)) {
LOGGER.debug(ATTRIBUTE + beanName + " : " + attributeInfo + " has attributeInfo composite type");
jmxAttribute = new JMXComplexAttribute(attributeInfo, beanName, instanceName, connection, tags);
jmxAttribute = new JMXComplexAttribute(attributeInfo, beanName, instanceName, connection, tags, emptyDefaultHostname);
} else if (MULTI_TYPES.contains(attributeType)) {
LOGGER.debug(ATTRIBUTE + beanName + " : " + attributeInfo + " has attributeInfo tabular type");
jmxAttribute = new JMXTabularAttribute(attributeInfo, beanName, instanceName, connection, tags);
jmxAttribute = new JMXTabularAttribute(attributeInfo, beanName, instanceName, connection, tags, emptyDefaultHostname);
} else {
try {
LOGGER.debug(ATTRIBUTE + beanName + " : " + attributeInfo + " has an unsupported type: " + attributeType);
Expand Down Expand Up @@ -462,6 +470,10 @@ public String[] getServiceCheckTags() {
}
}
tags.add("instance:" + this.instanceName);

if (this.emptyDefaultHostname) {
tags.add("host:");
}
return tags.toArray(new String[tags.size()]);
}

Expand Down
8 changes: 6 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JMXAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ public abstract class JMXAttribute {
private Boolean cassandraAliasing;

JMXAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Connection connection, HashMap<String, String> instanceTags, Boolean cassandraAliasing) {
Connection connection, HashMap<String, String> instanceTags, Boolean cassandraAliasing,
Copy link
Member

Choose a reason for hiding this comment

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

How do you feel we should handle the case where the instanceTags host tag is set (for whatever reason), but emptyDefaultHostname is true. IMHO it might make sense to just evict it from the HashMap and make the boolean option take precedence.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For python/golang checks, we want to support an empty default hostname + check-provided hostname override (for kubernetes events node events / kube_state node metrics), so it's a legit use case.

It's currently not possible as an instance tag as it'll be sanitized to bean_host, but could it be added as a bean tag?

If so, do you think there's a better method to plug this logic into?

Copy link
Member

Choose a reason for hiding this comment

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

Let's leave as-is, I think its probably fine.

boolean emptyDefaultHostname) {
this.attribute = attribute;
this.beanName = beanName;
this.matchingConf = null;
Expand All @@ -73,6 +74,9 @@ public abstract class JMXAttribute {

this.beanParameters = beanParametersHash;
this.defaultTagsList = sanitizeParameters(beanParametersList);
if (emptyDefaultHostname) {
this.defaultTagsList.add("host:");
}
}

/**
Expand Down Expand Up @@ -303,7 +307,7 @@ private boolean matchBeanRegex(Filter filter, boolean matchIfNoRegex) {
Matcher m = beanRegex.matcher(beanStringName);

if(m.matches()) {
for (int i = 0; i<= m.groupCount(); i++) {
for (int i = 0; i<= m.groupCount(); i++) {
this.beanParameters.put(Integer.toString(i), m.group(i));
}
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JMXComplexAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public class JMXComplexAttribute extends JMXAttribute {
private HashMap<String, HashMap<String, Object>> subAttributeList;

public JMXComplexAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Connection connection, HashMap<String, String> instanceTags) {
super(attribute, beanName, instanceName, connection, instanceTags, false);
Connection connection, HashMap<String, String> instanceTags, boolean emptyDefaultHostname) {
super(attribute, beanName, instanceName, connection, instanceTags, false, emptyDefaultHostname);
this.subAttributeList = new HashMap<String, HashMap<String, Object>>();
}

Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JMXSimpleAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ public class JMXSimpleAttribute extends JMXAttribute {
private String metricType;

public JMXSimpleAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Connection connection, HashMap<String, String> instanceTags, Boolean cassandraAliasing) {
super(attribute, beanName, instanceName, connection, instanceTags, cassandraAliasing);
Connection connection, HashMap<String, String> instanceTags, boolean cassandraAliasing,
Boolean emptyDefaultHostname) {
super(attribute, beanName, instanceName, connection, instanceTags, cassandraAliasing, emptyDefaultHostname);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JMXTabularAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class JMXTabularAttribute extends JMXAttribute {
private HashMap<String, HashMap<String, HashMap<String, Object>>> subAttributeList;

public JMXTabularAttribute(MBeanAttributeInfo attribute, ObjectName beanName, String instanceName,
Connection connection, HashMap<String, String> instanceTags) {
super(attribute, beanName, instanceName, connection, instanceTags, false);
Connection connection, HashMap<String, String> instanceTags, boolean emptyDefaultHostname) {
super(attribute, beanName, instanceName, connection, instanceTags, false, emptyDefaultHostname);
subAttributeList = new HashMap<String, HashMap<String, HashMap<String, Object>>>();
}

Expand Down
47 changes: 44 additions & 3 deletions src/test/java/org/datadog/jmxfetch/TestInstance.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,75 @@
package org.datadog.jmxfetch;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.junit.Test;

public class TestInstance extends TestCommon {
private final static Logger LOGGER = Logger.getLogger("Test Instance");

@Test
public void testMinCollectionInterval() throws Exception {
registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz");
initApplication("jmx_min_collection_period.yml");

run();
LinkedList<HashMap<String, Object>> metrics = getMetrics();
assertEquals(15, metrics.size());

run();
metrics = getMetrics();
assertEquals(0, metrics.size());

LOGGER.info("sleeping before the next collection");
Thread.sleep(5000);
run();
metrics = getMetrics();
assertEquals(15, metrics.size());
}

// assertHostnameTags is used by testEmptyDefaultHostname
private void assertHostnameTags(List<String> tagList) throws Exception {
// Fixed instance tag
assertTrue(tagList.contains(new String("jmx:fetch")));

if (tagList.contains(new String("instance:jmx_test_default_hostname"))) {
// Nominal case
assertFalse(tagList.contains(new String("host:")));
} else if (tagList.contains(new String("instance:jmx_test_no_hostname"))) {
// empty_default_hostname case
assertTrue(tagList.contains(new String("host:")));
} else {
fail("unexpected instance tag");
}
}

@Test
public void testEmptyDefaultHostname() 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.

🍰

registerMBean(new SimpleTestJavaApp(), "org.datadog.jmxfetch.test:foo=Bar,qux=Baz");
initApplication("jmx_empty_default_hostname.yaml");
run();

LinkedList<HashMap<String, Object>> metrics = getMetrics();
assertEquals(28, metrics.size());
for (HashMap<String, Object> metric : metrics) {
String[] tags = (String[]) metric.get("tags");
this.assertHostnameTags(Arrays.asList(tags));
}

LinkedList<HashMap<String, Object>> serviceChecks = getServiceChecks();
assertEquals(2, serviceChecks.size());
for (HashMap<String, Object> sc : serviceChecks) {
String[] tags = (String[]) sc.get("tags");
this.assertHostnameTags(Arrays.asList(tags));
}
}
}
27 changes: 27 additions & 0 deletions src/test/resources/jmx_empty_default_hostname.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
init_config:

instances:
- process_name_regex: .*surefire.*
name: jmx_test_default_hostname
tags:
- jmx:fetch
conf:
- include:
domain: org.datadog.jmxfetch.test
attribute:
ShouldBe100:
metric_type: gauge
alias: this.is.100.$foo.$qux

- process_name_regex: .*surefire.*
empty_default_hostname: true
name: jmx_test_no_hostname
tags:
- jmx:fetch
conf:
- include:
domain: org.datadog.jmxfetch.test
attribute:
ShouldBe100:
metric_type: gauge
alias: this.is.100.$foo.$qux