diff --git a/collector/src/main/java/io/prometheus/jmx/JmxCollector.java b/collector/src/main/java/io/prometheus/jmx/JmxCollector.java index 1c7281bd..dd63bd92 100644 --- a/collector/src/main/java/io/prometheus/jmx/JmxCollector.java +++ b/collector/src/main/java/io/prometheus/jmx/JmxCollector.java @@ -71,7 +71,16 @@ static class Rule { String type = "UNKNOWN"; ArrayList labelNames; ArrayList labelValues; - ArrayList attributesAsLabels; + } + + public static class MetricCustomizer { + MBeanFilter mbeanFilter; + List attributesAsLabels; + } + + public static class MBeanFilter { + String domain; + Map properties; } private static class Config { @@ -87,7 +96,7 @@ private static class Config { ObjectNameAttributeFilter objectNameAttributeFilter; List rules = new ArrayList<>(); long lastUpdate = 0L; - + List metricCustomizers = new ArrayList<>(); MatchedRulesCache rulesCache; } @@ -297,6 +306,29 @@ private Config loadConfig(Map yamlConfig) throws MalformedObject } } + if (yamlConfig.containsKey("metricCustomizers")) { + List> metricCustomizersYaml = + (List>) yamlConfig.get("metricCustomizers"); + for (Map metricCustomizerYaml : metricCustomizersYaml) { + Map mbeanFilterYaml = + (Map) metricCustomizerYaml.get("mbeanFilter"); + MBeanFilter mbeanFilter = new MBeanFilter(); + mbeanFilter.domain = (String) mbeanFilterYaml.get("domain"); + mbeanFilter.properties = (Map) mbeanFilterYaml.get("properties"); + + List attributesAsLabels = + (List) metricCustomizerYaml.get("attributesAsLabels"); + if (attributesAsLabels == null) { + attributesAsLabels = new ArrayList<>(); + } + + MetricCustomizer metricCustomizer = new MetricCustomizer(); + metricCustomizer.mbeanFilter = mbeanFilter; + metricCustomizer.attributesAsLabels = attributesAsLabels; + cfg.metricCustomizers.add(metricCustomizer); + } + } + if (yamlConfig.containsKey("rules")) { List> configRules = (List>) yamlConfig.get("rules"); @@ -349,13 +381,6 @@ private Config loadConfig(Map yamlConfig) throws MalformedObject } } - if (yamlRule.containsKey("attributesAsLabels")) { - List attributes = (List) yamlRule.get("attributesAsLabels"); - rule.attributesAsLabels = new ArrayList<>(); - if (attributes != null) { - rule.attributesAsLabels.addAll(attributes); - } - } // Validation. if ((rule.labelNames != null || rule.help != null) && rule.name == null) { throw new IllegalArgumentException( @@ -750,7 +775,7 @@ public MetricSnapshots collect() { config.includeObjectNames, config.excludeObjectNames, config.objectNameAttributeFilter, - config.rules, + config.metricCustomizers, receiver, jmxMBeanPropertyCache); diff --git a/collector/src/main/java/io/prometheus/jmx/JmxScraper.java b/collector/src/main/java/io/prometheus/jmx/JmxScraper.java index f307d31d..45fb9ed3 100644 --- a/collector/src/main/java/io/prometheus/jmx/JmxScraper.java +++ b/collector/src/main/java/io/prometheus/jmx/JmxScraper.java @@ -31,7 +31,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import java.util.regex.Matcher; import java.util.stream.Collectors; import javax.management.Attribute; import javax.management.AttributeList; @@ -74,7 +73,7 @@ void recordBean( private final String password; private final boolean ssl; private final List includeObjectNames, excludeObjectNames; - private final List rules; + private final List metricCustomizers; private final ObjectNameAttributeFilter objectNameAttributeFilter; private final JmxMBeanPropertyCache jmxMBeanPropertyCache; @@ -86,7 +85,7 @@ public JmxScraper( List includeObjectNames, List excludeObjectNames, ObjectNameAttributeFilter objectNameAttributeFilter, - List rules, + List metricCustomizers, MBeanReceiver receiver, JmxMBeanPropertyCache jmxMBeanPropertyCache) { this.jmxUrl = jmxUrl; @@ -96,7 +95,7 @@ public JmxScraper( this.ssl = ssl; this.includeObjectNames = includeObjectNames; this.excludeObjectNames = excludeObjectNames; - this.rules = rules; + this.metricCustomizers = metricCustomizers; this.objectNameAttributeFilter = objectNameAttributeFilter; this.jmxMBeanPropertyCache = jmxMBeanPropertyCache; } @@ -225,7 +224,12 @@ private void scrapeBean(MBeanServerConnection beanConn, ObjectName mBeanName) { final String mBeanNameString = mBeanName.toString(); final String mBeanDomain = mBeanName.getDomain(); - Map attributeMap = attributes.asList().stream().collect(Collectors.toMap(Attribute::getName, Attribute::getValue)); + JmxCollector.MetricCustomizer metricCustomizer = getMetricCustomizer(mBeanName); + Map attributesAsLabelsWithValues = new HashMap<>(); + if (metricCustomizer != null) { + attributesAsLabelsWithValues = + getAttributesAsLabelsWithValues(metricCustomizer, attributes); + } for (Object object : attributes) { // The contents of an AttributeList should all be Attribute instances, but we'll verify @@ -246,8 +250,6 @@ private void scrapeBean(MBeanServerConnection beanConn, ObjectName mBeanName) { continue; } - Map attributesAsLabelsWithValues = getAttributesAsLabelsWithValues(mBeanName, attribute, attributeMap); - MBeanAttributeInfo mBeanAttributeInfo = name2MBeanAttributeInfo.get(attribute.getName()); LOGGER.log(FINE, "%s_%s process", mBeanName, mBeanAttributeInfo.getName()); @@ -276,46 +278,33 @@ private void scrapeBean(MBeanServerConnection beanConn, ObjectName mBeanName) { } } - private Map getAttributesAsLabelsWithValues(ObjectName mBeanName, Attribute attribute, Map attributeMap) { - JmxCollector.Rule matchedRule = null; - for (JmxCollector.Rule rule : rules) { - if (rule.attributesAsLabels != null && !rule.attributesAsLabels.isEmpty()) { - if (rule.pattern != null) { - Object matchBeanValue = rule.cache ? "" : attribute.getValue(); - List attrKeys = new LinkedList<>(); - if (attribute.getValue() instanceof TabularData || attribute.getValue() instanceof CompositeData) { - attrKeys.add(attribute.getName()); - } - String beanName = mBeanName.getDomain() - + angleBrackets(jmxMBeanPropertyCache.getKeyPropertyList(mBeanName).toString()) - + angleBrackets(attrKeys.toString()); - String matchName = beanName + attribute.getName() + ": " + matchBeanValue; - Matcher matcher = rule.pattern.matcher(matchName); - if (matcher.matches()) { - matchedRule = rule; - } - } else if (rule.name == null) { - matchedRule = rule; - } - } - } - + private Map getAttributesAsLabelsWithValues(JmxCollector.MetricCustomizer metricCustomizer, AttributeList attributes) { + Map attributeMap = + attributes.asList().stream() + .collect(Collectors.toMap(Attribute::getName, Attribute::getValue)); Map attributesAsLabelsWithValues = new HashMap<>(); - if (matchedRule != null) { - for (String attributeAsLabel : matchedRule.attributesAsLabels) { - Object attrValue = attributeMap.get(attributeAsLabel); - if (attrValue != null) { - attributesAsLabelsWithValues.put( - attributeAsLabel, - attrValue.toString()); - } + for (String attributeAsLabel : metricCustomizer.attributesAsLabels) { + Object attrValue = attributeMap.get(attributeAsLabel); + if (attrValue != null) { + attributesAsLabelsWithValues.put(attributeAsLabel, attrValue.toString()); } } return attributesAsLabelsWithValues; } - private String angleBrackets(String s) { - return "<" + s.substring(1, s.length() - 1) + ">"; + private JmxCollector.MetricCustomizer getMetricCustomizer(ObjectName mBeanName) { + if (!metricCustomizers.isEmpty()) { + for (JmxCollector.MetricCustomizer metricCustomizer : metricCustomizers) { + if (metricCustomizer.mbeanFilter.domain.equals(mBeanName.getDomain()) + && mBeanName + .getKeyPropertyList() + .entrySet() + .containsAll(metricCustomizer.mbeanFilter.properties.entrySet())) { + return metricCustomizer; + } + } + } + return null; } private void processAttributesOneByOne(