diff --git a/collector/src/main/java/io/prometheus/jmx/ObjectNameAttributeFilter.java b/collector/src/main/java/io/prometheus/jmx/ObjectNameAttributeFilter.java index dc6f311a..c9b35580 100644 --- a/collector/src/main/java/io/prometheus/jmx/ObjectNameAttributeFilter.java +++ b/collector/src/main/java/io/prometheus/jmx/ObjectNameAttributeFilter.java @@ -129,10 +129,15 @@ public void add(ObjectName objectName, String attributeName) { public boolean exclude(ObjectName objectName, String attributeName) { boolean result = false; - if (excludeObjectNameAttributesMap.size() > 0) { - Set attributeNameSet = excludeObjectNameAttributesMap.get(objectName); - if (attributeNameSet != null) { - result = attributeNameSet.contains(attributeName); + for (Map.Entry> objectNameSetEntry : + excludeObjectNameAttributesMap.entrySet()) { + if (objectNameSetEntry.getKey().apply(objectName)) { + // if exclusion found - return + // otherwise keep searching as checked object may match multiple patterns + // and checked attribute may be defined only under one of them + if (objectNameSetEntry.getValue().contains(attributeName)) { + return true; + } } } diff --git a/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest.java b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest.java new file mode 100644 index 00000000..37c138dc --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2023 The Prometheus jmx_exporter Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.prometheus.jmx.test; + +import static org.assertj.core.api.Assertions.*; + +import io.prometheus.jmx.test.support.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import org.antublue.test.engine.api.TestEngine; + +public class ExcludeObjectNameAttributesPatternTest extends BaseTest implements ContentConsumer { + + @TestEngine.Test + public void testHealthy() { + RequestResponseAssertions.assertThatResponseForRequest( + new HealthyRequest(testState.httpClient())) + .isSuperset(HealthyResponse.RESULT_200); + } + + @TestEngine.Test + public void testMetrics() { + RequestResponseAssertions.assertThatResponseForRequest( + new MetricsRequest(testState.httpClient())) + .isSuperset(MetricsResponse.RESULT_200) + .dispatch(this); + } + + @TestEngine.Test + public void testMetricsOpenMetricsFormat() { + RequestResponseAssertions.assertThatResponseForRequest( + new OpenMetricsRequest(testState.httpClient())) + .isSuperset(OpenMetricsResponse.RESULT_200) + .dispatch(this); + } + + @TestEngine.Test + public void testMetricsPrometheusFormat() { + RequestResponseAssertions.assertThatResponseForRequest( + new PrometheusMetricsRequest(testState.httpClient())) + .isSuperset(PrometheusMetricsResponse.RESULT_200) + .dispatch(this); + } + + @Override + public void accept(String content) { + Collection metricCollection = MetricsParser.parse(content); + + Set excludeAttributeNameSet = new HashSet<>(); + excludeAttributeNameSet.add("_ClassPath"); + excludeAttributeNameSet.add("_SystemProperties"); + excludeAttributeNameSet.add("_UsageThreshold"); + excludeAttributeNameSet.add("_UsageThresholdCount"); + /* + * Assert that we don't have any metrics that start with ... + * + * name = java_lang* + */ + Set validAttributesFound = new HashSet<>(); + metricCollection.forEach( + metric -> { + String name = metric.getName(); + // test global exclusion filter + if (name.contains("_ObjectName")) fail("metric found: " + name); + // test exclusion by object name patterns + if (name.contains("java_lang")) { + for (String attributeName : excludeAttributeNameSet) { + if (name.endsWith(attributeName)) { + fail("metric found: " + name); + } + } + // test exclusion accuracy + if (name.contains("_Valid")) { + // Valid should not exist inside MemoryPool + if (name.contains("MemoryPool")) { + fail("metric found: " + name); + } else { // Valid should exist inside other branches + validAttributesFound.add(name); + } + } + } + }); + assertThat(!validAttributesFound.isEmpty()).as("metric should exist").isTrue(); + } +} diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/application.sh new file mode 100644 index 00000000..268f821e --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/application.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java \ + -Xmx128M \ + -javaagent:jmx_prometheus_javaagent.jar=8888:exporter.yaml \ + -jar jmx_example_application.jar \ No newline at end of file diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/exporter.yaml new file mode 100644 index 00000000..7340ca91 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/JavaAgent/exporter.yaml @@ -0,0 +1,13 @@ +excludeObjectNames: ["java.lang:type=ObjectName"] +excludeObjectNameAttributes: + "*:*": + - "ObjectName" + "java.lang:type=Runtime": + - "ClassPath" + - "SystemProperties" + "java.lang:type=MemoryPool,*": + - "UsageThreshold" + - "UsageThresholdCount" + - "Valid" +rules: + - pattern: ".*" \ No newline at end of file diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/application.sh new file mode 100644 index 00000000..c0fa948c --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/application.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +java \ + -Xmx128M \ + -Dcom.sun.management.jmxremote=true \ + -Dcom.sun.management.jmxremote.authenticate=false \ + -Dcom.sun.management.jmxremote.local.only=false \ + -Dcom.sun.management.jmxremote.port=9999 \ + -Dcom.sun.management.jmxremote.registry.ssl=false \ + -Dcom.sun.management.jmxremote.rmi.port=9999 \ + -Dcom.sun.management.jmxremote.ssl.need.client.auth=false \ + -Dcom.sun.management.jmxremote.ssl=false \ + -jar jmx_example_application.jar \ No newline at end of file diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.sh new file mode 100644 index 00000000..c35f1652 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +java \ + -Xmx128M \ + -jar jmx_prometheus_httpserver.jar 8888 exporter.yaml \ No newline at end of file diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.yaml new file mode 100644 index 00000000..ec079e85 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/ExcludeObjectNameAttributesPatternTest/Standalone/exporter.yaml @@ -0,0 +1,14 @@ +hostPort: application:9999 +excludeObjectNames: ["java.lang:type=ObjectName"] +excludeObjectNameAttributes: + "*:*": + - "ObjectName" + "java.lang:type=Runtime": + - "ClassPath" + - "SystemProperties" + "java.lang:type=MemoryPool,*": + - "UsageThreshold" + - "UsageThresholdCount" + - "Valid" +rules: + - pattern: ".*" \ No newline at end of file