Skip to content
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
6 changes: 3 additions & 3 deletions src/main/java/org/datadog/jmxfetch/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private void registerTelemetryBean(AppTelemetry bean) {
| MBeanRegistrationException
| NotCompliantMBeanException e) {
log.warn("Could not register bean named '{}' for instance: ",
appTelemetryBeanName.toString(), e);
appTelemetryBeanName.getCanonicalName(), e);
}
}

Expand Down Expand Up @@ -189,7 +189,7 @@ private void initTelemetryBean() {
| MBeanRegistrationException
| NotCompliantMBeanException e) {
log.warn("Could not register bean named '{}' for instance: ",
appTelemetryBeanName.toString(), e);
appTelemetryBeanName.getCanonicalName(), e);
}

this.appTelemetry = bean;
Expand All @@ -208,7 +208,7 @@ private void teardownTelemetry() {
log.debug("Successfully unregistered app telemetry bean");
} catch (MBeanRegistrationException | InstanceNotFoundException e) {
log.warn("Could not unregister bean named '{}' for instance: ",
appTelemetryBeanName.toString(), e);
appTelemetryBeanName.getCanonicalName(), e);
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/datadog/jmxfetch/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ public List<String> getParameterValues(String parameterName) {
return toStringList(beanValues);
}

/**
* Per-filter override for canonical bean name matching.
* Null means defer to instance default.
*/
public Boolean getUseCanonicalBeanName() {
return (Boolean) filter.get("use_canonical_bean_name");
}

public boolean isEmptyBeanName() {
return (filter.get("bean") == null && filter.get("bean_name") == null);
}
Expand Down
75 changes: 44 additions & 31 deletions src/main/java/org/datadog/jmxfetch/Instance.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public Yaml initialValue() {
private ObjectName instanceTelemetryBeanName;
private MBeanServer mbs;
private Boolean normalizeBeanParamTags;
private Boolean useCanonicalBeanName;
private Map<String, Map.Entry<String, String>> dynamicTagsCache;

/** Constructor, instantiates Instance based of a previous instance and appConfig. */
Expand Down Expand Up @@ -202,6 +203,14 @@ public Instance(
this.normalizeBeanParamTags = false;
}

this.useCanonicalBeanName = (Boolean) instanceMap.get("use_canonical_bean_name");
if (this.useCanonicalBeanName == null && initConfig != null) {
this.useCanonicalBeanName = (Boolean) initConfig.get("use_canonical_bean_name");
}
if (this.useCanonicalBeanName == null) {
this.useCanonicalBeanName = false;
}


// Alternative aliasing for CASSANDRA-4009 metrics
// More information: https://issues.apache.org/jira/browse/CASSANDRA-4009
Expand Down Expand Up @@ -278,12 +287,12 @@ private InstanceTelemetry registerTelemetryBean(InstanceTelemetry bean) {
try {
mbs.registerMBean(bean,instanceTelemetryBeanName);
log.debug("Successfully registered jmx bean for instance {} with ObjectName = {}",
this.getName(), instanceTelemetryBeanName);
this.getName(), instanceTelemetryBeanName.getCanonicalName());
} catch (InstanceAlreadyExistsException
| MBeanRegistrationException
| NotCompliantMBeanException e) {
log.warn("Could not register bean named '{}' for instance: ",
instanceTelemetryBeanName.toString(), e);
instanceTelemetryBeanName.getCanonicalName(), e);
}

return bean;
Expand Down Expand Up @@ -448,40 +457,40 @@ public void init(boolean forceNewConnection)
throws IOException, FailedLoginException, SecurityException {
log.info("Trying to connect to JMX Server at " + this.toString());
connection = getConnection(instanceMap, forceNewConnection);

log.info(
"Trying to collect bean list for the first time for JMX Server at {}", this);
this.refreshBeansList();
this.initialRefreshTime = this.lastRefreshTime;
log.info("Connected to JMX Server at {} with {} beans", this, this.beans.size());

// Resolve configuration-level dynamic tags for all configurations
// Must be done after refreshBeansList() so the beans exist
resolveConfigurationDynamicTags();

this.getMatchingAttributes();
log.info("Done initializing JMX Server at {}", this);
}

private void resolveConfigurationDynamicTags() {
if (configurationList == null || configurationList.isEmpty()) {
return;
}

this.dynamicTagsCache = new HashMap<>();
List<DynamicTag> allDynamicTags = new ArrayList<>();

for (Configuration config : configurationList) {
List<DynamicTag> dynamicTags = config.getDynamicTags();
if (dynamicTags != null && !dynamicTags.isEmpty()) {
allDynamicTags.addAll(dynamicTags);
}
}

if (allDynamicTags.isEmpty()) {
return;
}

int successfulResolutions = 0;
for (DynamicTag dynamicTag : allDynamicTags) {
String cacheKey = dynamicTag.getBeanAttributeKey();
Expand All @@ -495,38 +504,38 @@ private void resolveConfigurationDynamicTags() {
successfulResolutions++;
}
}
log.info("Resolved {} unique dynamic tag(s) from {} total references for instance {}",

log.info("Resolved {} unique dynamic tag(s) from {} total references for instance {}",
successfulResolutions, allDynamicTags.size(), instanceName);
}

/**
* Get resolved dynamic tags for a specific configuration.
* This resolves the dynamic tags defined in the configuration using the cached values.
*
*
* @param config the configuration to get resolved tags for
* @return map of tag name to tag value
*/
private Map<String, String> getResolvedDynamicTagsForConfig(Configuration config) {
Map<String, String> resolvedTags = new HashMap<>();

if (this.dynamicTagsCache == null || this.dynamicTagsCache.isEmpty()) {
return resolvedTags;
}

List<DynamicTag> dynamicTags = config.getDynamicTags();
if (dynamicTags == null || dynamicTags.isEmpty()) {
return resolvedTags;
}

for (DynamicTag dynamicTag : dynamicTags) {
String cacheKey = dynamicTag.getBeanAttributeKey();
Map.Entry<String, String> cached = this.dynamicTagsCache.get(cacheKey);
if (cached != null) {
resolvedTags.put(cached.getKey(), cached.getValue());
}
}

return resolvedTags;
}

Expand Down Expand Up @@ -652,19 +661,20 @@ private void getMatchingAttributes() throws IOException {
}
String className;
MBeanAttributeInfo[] attributeInfos;
String beanNameStr = beanName.getCanonicalName();
try {
log.debug("Getting bean info for bean: {}", beanName);
log.debug("Getting bean info for bean: {}", beanNameStr);
MBeanInfo info = connection.getMBeanInfo(beanName);

log.debug("Getting class name for bean: {}", beanName);
log.debug("Getting class name for bean: {}", beanNameStr);
className = info.getClassName();
log.debug("Getting attributes for bean: {}", beanName);
log.debug("Getting attributes for bean: {}", beanNameStr);
attributeInfos = info.getAttributes();
} catch (IOException e) {
// we should not continue
throw e;
} catch (Exception e) {
log.warn("Cannot get attributes or class name for bean {}: ", beanName, e);
log.warn("Cannot get attributes or class name for bean {}: ", beanNameStr, e);
continue;
}

Expand All @@ -687,7 +697,7 @@ private void getMatchingAttributes() throws IOException {
if (JmxSimpleAttribute.matchAttributeType(attributeType)) {
log.debug(
ATTRIBUTE
+ beanName
+ beanNameStr
+ " : "
+ attributeInfo
+ " has attributeInfo simple type");
Expand All @@ -703,11 +713,12 @@ private void getMatchingAttributes() throws IOException {
tags,
cassandraAliasing,
emptyDefaultHostname,
normalizeBeanParamTags);
normalizeBeanParamTags,
useCanonicalBeanName);
} else if (JmxComplexAttribute.matchAttributeType(attributeType)) {
log.debug(
ATTRIBUTE
+ beanName
+ beanNameStr
+ " : "
+ attributeInfo
+ " has attributeInfo composite type");
Expand All @@ -722,11 +733,12 @@ private void getMatchingAttributes() throws IOException {
serviceNameProvider,
tags,
emptyDefaultHostname,
normalizeBeanParamTags);
normalizeBeanParamTags,
useCanonicalBeanName);
} else if (JmxTabularAttribute.matchAttributeType(attributeType)) {
log.debug(
ATTRIBUTE
+ beanName
+ beanNameStr
+ " : "
+ attributeInfo
+ " has attributeInfo tabular type");
Expand All @@ -741,12 +753,13 @@ private void getMatchingAttributes() throws IOException {
serviceNameProvider,
tags,
emptyDefaultHostname,
normalizeBeanParamTags);
normalizeBeanParamTags,
useCanonicalBeanName);
} else {
try {
log.debug(
ATTRIBUTE
+ beanName
+ beanNameStr
+ " : "
+ attributeInfo
+ " has an unsupported type: "
Expand All @@ -764,7 +777,7 @@ private void getMatchingAttributes() throws IOException {
for (Configuration conf : configurationList) {
try {
if (jmxAttribute.match(conf)) {
Map<String, String> resolvedDynamicTags =
Map<String, String> resolvedDynamicTags =
getResolvedDynamicTagsForConfig(conf);
jmxAttribute.setResolvedDynamicTags(resolvedDynamicTags);
jmxAttribute.setMatchingConf(conf);
Expand All @@ -786,7 +799,7 @@ private void getMatchingAttributes() throws IOException {
log.error(
"Error while trying to match attributeInfo configuration "
+ "with the Attribute: "
+ beanName
+ beanNameStr
+ " : "
+ attributeInfo,
e);
Expand Down
41 changes: 34 additions & 7 deletions src/main/java/org/datadog/jmxfetch/JmxAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public abstract class JmxAttribute {
"class_regex",
"attribute",
"exclude_tags",
"tags");
"tags",
"use_canonical_bean_name");
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]+)";
Expand All @@ -52,6 +53,8 @@ public abstract class JmxAttribute {
private String domain;
private String className;
private String beanStringName;
private String canonicalBeanStringName;
private String toStringBeanStringName;
private ServiceNameProvider serviceNameProvider;
private Map<String, String> beanParameters;
private String attributeName;
Expand All @@ -76,14 +79,19 @@ public abstract class JmxAttribute {
Map<String, String> instanceTags,
boolean cassandraAliasing,
boolean emptyDefaultHostname,
boolean normalizeBeanParamTags) {
boolean normalizeBeanParamTags,
boolean useCanonicalBeanName) {
this.attribute = attribute;
this.beanName = beanName;
this.className = className;
this.matchingConf = null;
this.connection = connection;
this.attributeName = attribute.getName();
this.beanStringName = beanName.toString();
this.canonicalBeanStringName = beanName.getCanonicalName();
this.toStringBeanStringName = beanName.toString();
this.beanStringName = useCanonicalBeanName
? canonicalBeanStringName
: toStringBeanStringName;
this.cassandraAliasing = cassandraAliasing;
this.checkName = checkName;
this.serviceNameProvider = serviceNameProvider;
Expand Down Expand Up @@ -140,7 +148,7 @@ private void addAdditionalTags() {
}
}
}

/** Add dynamic tags that were resolved at connection time. */
private void addDynamicTags() {
if (this.resolvedDynamicTags != null && !this.resolvedDynamicTags.isEmpty()) {
Expand Down Expand Up @@ -404,8 +412,9 @@ private boolean matchBeanRegex(Filter filter, boolean matchIfNoRegex) {
return matchIfNoRegex;
}

String nameToMatch = resolveBeanStringName(filter);
for (Pattern beanRegex : beanRegexes) {
Matcher matcher = beanRegex.matcher(beanStringName);
Matcher matcher = beanRegex.matcher(nameToMatch);

if (matcher.matches()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
Expand All @@ -419,8 +428,9 @@ private boolean matchBeanRegex(Filter filter, boolean matchIfNoRegex) {

private boolean matchBeanName(Configuration configuration) {
Filter include = configuration.getInclude();
String nameToMatch = resolveBeanStringName(include);

if (!include.isEmptyBeanName() && !include.getBeanNames().contains(beanStringName)) {
if (!include.isEmptyBeanName() && !include.getBeanNames().contains(nameToMatch)) {
return false;
}

Expand All @@ -442,8 +452,9 @@ private boolean matchBeanName(Configuration configuration) {
private boolean excludeMatchBeanName(Configuration conf) {
Filter exclude = conf.getExclude();
List<String> beanNames = exclude.getBeanNames();
String nameToMatch = resolveBeanStringName(exclude);

if (beanNames.contains(beanStringName)) {
if (beanNames.contains(nameToMatch)) {
return true;
}

Expand Down Expand Up @@ -667,6 +678,22 @@ String getBeanStringName() {
return beanStringName;
}

/**
* Resolve bean name string for matching against a specific filter.
* Filter-level use_canonical_bean_name overrides the instance-level default.
*/
private String resolveBeanStringName(Filter filter) {
Boolean filterUseCanonicalBeanNameFlag = filter.getUseCanonicalBeanName();
if (filterUseCanonicalBeanNameFlag != null) {
if (filterUseCanonicalBeanNameFlag) {
return canonicalBeanStringName;
} else {
return toStringBeanStringName;
}
}
return beanStringName;
}

String getAttributeName() {
return attributeName;
}
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/datadog/jmxfetch/JmxComplexAttribute.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public JmxComplexAttribute(
ServiceNameProvider serviceNameProvider,
Map<String, String> instanceTags,
boolean emptyDefaultHostname,
boolean normalizeBeanParamTags) {
boolean normalizeBeanParamTags,
boolean useCanonicalBeanName) {
super(
attribute,
beanName,
Expand All @@ -58,7 +59,8 @@ public JmxComplexAttribute(
instanceTags,
false,
emptyDefaultHostname,
normalizeBeanParamTags);
normalizeBeanParamTags,
useCanonicalBeanName);
}

private void populateSubAttributeList(Object attributeValue) {
Expand Down
Loading
Loading