diff --git a/collector/src/main/java/io/prometheus/jmx/JmxCollector.java b/collector/src/main/java/io/prometheus/jmx/JmxCollector.java index d13f2cdd5..3b53733e3 100644 --- a/collector/src/main/java/io/prometheus/jmx/JmxCollector.java +++ b/collector/src/main/java/io/prometheus/jmx/JmxCollector.java @@ -64,6 +64,12 @@ public enum Mode { private final Mode mode; + static class ExtraMetric { + String name; + Object value; + String description; + } + static class Rule { Pattern pattern; String name; @@ -80,6 +86,7 @@ static class Rule { public static class MetricCustomizer { MBeanFilter mbeanFilter; List attributesAsLabels; + List extraMetrics; } public static class MBeanFilter { @@ -355,15 +362,37 @@ private Config loadConfig(Map yamlConfig) throws MalformedObject } mbeanFilter.properties = (Map) mbeanFilterYaml.getOrDefault("properties", new HashMap<>()); - List attributesAsLabels = + List attributesAsLabelsYaml = (List) metricCustomizerYaml.get("attributesAsLabels"); - if (attributesAsLabels == null) { + List> extraMetricsYaml = + (List>) metricCustomizerYaml.get("extraMetrics"); + if (attributesAsLabelsYaml == null && extraMetricsYaml == null) { throw new IllegalArgumentException( - "Must provide attributesAsLabels, if metricCustomizers is given: " + metricCustomizersYaml); + "Must provide attributesAsLabels or extraMetrics, if metricCustomizers is given: " + metricCustomizersYaml); } MetricCustomizer metricCustomizer = new MetricCustomizer(); metricCustomizer.mbeanFilter = mbeanFilter; - metricCustomizer.attributesAsLabels = attributesAsLabels; + metricCustomizer.attributesAsLabels = attributesAsLabelsYaml; + + if (extraMetricsYaml != null) { + List extraMetrics = new ArrayList<>(); + for (Map extraMetricYaml : extraMetricsYaml) { + ExtraMetric extraMetric = new ExtraMetric(); + extraMetric.name = (String) extraMetricYaml.get("name"); + if (extraMetric.name == null) { + throw new IllegalArgumentException( + "Must provide name, if extraMetric is given: " + extraMetricsYaml); + } + extraMetric.value = extraMetricYaml.get("value"); + if (extraMetric.value == null) { + throw new IllegalArgumentException( + "Must provide value, if extraMetric is given: " + extraMetricsYaml); + } + extraMetric.description = (String) extraMetricYaml.get("description"); + extraMetrics.add(extraMetric); + } + metricCustomizer.extraMetrics = extraMetrics; + } cfg.metricCustomizers.add(metricCustomizer); } } else { diff --git a/collector/src/main/java/io/prometheus/jmx/JmxScraper.java b/collector/src/main/java/io/prometheus/jmx/JmxScraper.java index 695da9d76..e31f3f4e4 100644 --- a/collector/src/main/java/io/prometheus/jmx/JmxScraper.java +++ b/collector/src/main/java/io/prometheus/jmx/JmxScraper.java @@ -262,8 +262,22 @@ private void scrapeBean(MBeanServerConnection beanConn, ObjectName mBeanName) { JmxCollector.MetricCustomizer metricCustomizer = getMetricCustomizer(mBeanName); Map attributesAsLabelsWithValues = Collections.emptyMap(); if (metricCustomizer != null) { - attributesAsLabelsWithValues = - getAttributesAsLabelsWithValues(metricCustomizer, attributes); + if (metricCustomizer.attributesAsLabels != null) { + attributesAsLabelsWithValues = + getAttributesAsLabelsWithValues(metricCustomizer, attributes); + } + for (JmxCollector.ExtraMetric extraMetric : getExtraMetrics(metricCustomizer)) { + processBeanValue( + mBeanName, + mBeanDomain, + jmxMBeanPropertyCache.getKeyPropertyList(mBeanName), + attributesAsLabelsWithValues, + new LinkedList<>(), + extraMetric.name, + "UNKNOWN", + extraMetric.description, + extraMetric.value); + } } for (Object object : attributes) { @@ -313,6 +327,13 @@ private void scrapeBean(MBeanServerConnection beanConn, ObjectName mBeanName) { } } + private List getExtraMetrics( + JmxCollector.MetricCustomizer metricCustomizer) { + return metricCustomizer.extraMetrics != null + ? metricCustomizer.extraMetrics + : Collections.emptyList(); + } + private Map getAttributesAsLabelsWithValues(JmxCollector.MetricCustomizer metricCustomizer, AttributeList attributes) { Map attributeMap = attributes.asList().stream() .collect(Collectors.toMap(Attribute::getName, Attribute::getValue)); diff --git a/collector/src/test/java/io/prometheus/jmx/JmxCollectorTest.java b/collector/src/test/java/io/prometheus/jmx/JmxCollectorTest.java index fe5adc1ce..ded60f5d5 100644 --- a/collector/src/test/java/io/prometheus/jmx/JmxCollectorTest.java +++ b/collector/src/test/java/io/prometheus/jmx/JmxCollectorTest.java @@ -57,6 +57,7 @@ public static void classSetUp() throws Exception { Bool.registerBean(mbs); Camel.registerBean(mbs); CustomValue.registerBean(mbs); + StringValue.registerBean(mbs); } @Before @@ -179,6 +180,36 @@ public void testMetricCustomizers() throws Exception { .001); } + @Test + public void testMetricCustomizersExtraMetrics() throws Exception { + new JmxCollector( + "\n---\nincludeObjectNames: [`io.prometheus.jmx:type=stringValue`]\nmetricCustomizers:\n - mbeanFilter:\n domain: io.prometheus.jmx\n properties:\n type: stringValue\n extraMetrics:\n - name: isActive\n value: true\n description: This is a boolean value indicating if the scenario is still active or is completed." + .replace('`', '"')) + .register(prometheusRegistry); + assertEquals( + 1.0, + getSampleValue( + "io_prometheus_jmx_stringValue_isActive", + new String[] {}, + new String[] {}), + .001); + } + + @Test + public void testMetricCustomizersAttributesAsLabelsExtraMetrics() throws Exception { + new JmxCollector( + "\n---\nincludeObjectNames: [`io.prometheus.jmx:type=stringValue`]\nmetricCustomizers:\n - mbeanFilter:\n domain: io.prometheus.jmx\n properties:\n type: stringValue\n attributesAsLabels:\n - Text\n extraMetrics:\n - name: isActive\n value: true\n description: This is a boolean value indicating if the scenario is still active or is completed." + .replace('`', '"')) + .register(prometheusRegistry); + assertEquals( + 1.0, + getSampleValue( + "io_prometheus_jmx_stringValue_isActive", + new String[] {"Text"}, + new String[] {"value"}), + .001); + } + /* @Test public void testHelpFromPattern() throws Exception { diff --git a/collector/src/test/java/io/prometheus/jmx/StringValueMBean.java b/collector/src/test/java/io/prometheus/jmx/StringValueMBean.java new file mode 100644 index 000000000..123190327 --- /dev/null +++ b/collector/src/test/java/io/prometheus/jmx/StringValueMBean.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023-present 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; + +import javax.management.MBeanServer; +import javax.management.ObjectName; + +/** Class to implement StringValueMBean */ +public interface StringValueMBean { + + /** + * Method to get the text + * + * @return text + */ + String getText(); +} + +/** Class to implement StringValue */ +class StringValue implements StringValueMBean { + + @Override + public String getText() { + return "value"; + } + + public static void registerBean(MBeanServer mbs) throws javax.management.JMException { + ObjectName mbeanName = + new ObjectName("io.prometheus.jmx:type=stringValue"); + StringValueMBean mbean = new StringValue(); + mbs.registerMBean(mbean, mbeanName); + } +} diff --git a/docs/content/1.1.0/http-mode/rules.md b/docs/content/1.1.0/http-mode/rules.md index 8cf6c89e5..28a96d4ec 100644 --- a/docs/content/1.1.0/http-mode/rules.md +++ b/docs/content/1.1.0/http-mode/rules.md @@ -25,11 +25,15 @@ labels | A map of label name to label value pairs. Capture groups fro help | Help text for the metric. Capture groups from `pattern` can be used. `name` must be set to use this. Defaults to the mBean attribute description, domain, and name of the attribute. cache | Whether to cache bean name expressions to rule computation (match and mismatch). Not recommended for rules matching on bean value, as only the value from the first scrape will be cached and re-used. This can increase performance when collecting a lot of mbeans. Defaults to `false`. type | The type of the metric, can be `GAUGE`, `COUNTER` or `UNTYPED`. `name` must be set to use this. Defaults to `UNTYPED`. -metricCustomizers | A list of objects that contain `mbeanFilter` and `attributesAsLabels`. For those mBeans that match the filter, the items in the `attributesAsLabels` list will be added as attributes to the existing metrics. +metricCustomizers | A list of objects that contain `mbeanFilter`, and at least one of `attributesAsLabels` and `extraMetrics`. For those mBeans that match the filter, the items in the `attributesAsLabels` list will be added as attributes to the existing, or new metrics, and items in the `extraMetrics` will generate new metrics. mbeanFilter | A map of the criteria by which mBeans are filtered. It contains `domain` and `properties`. domain | Domain of an mBean. Mandatory if `metricCustomizers` defined. properties | Properties of an mBean. Optional -attributesAsLabels | List of elements to be added as attributes to existing metrics. Mandatory if `metricCustomizers` defined. +attributesAsLabels | List of elements to be added as attributes to existing metrics. Mandatory if `metricCustomizers` defined, and `extraMetrics` not. +extraMetrics | A list of map of elements in order to create a new metric. It contains `name`, `value` and `description`. Mandatory if `metricCustomizers` defined, and `attributesAsLabels` not. +name | The name of the new metric. Mandatory if `extraMetrics` defined. +value | The value of the new metric. It needs to be boolean or number. Mandatory if `extraMetrics` defined. +description | The description of the new metric. Used in the HELP section of the logs and indicates what purpose the metric serves. Optional Metric names and label names are sanitized. All characters other than `[a-zA-Z0-9:_]` are replaced with underscores, and adjacent underscores are collapsed. There's no limitations on label values or the help text. diff --git a/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest.java b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest.java new file mode 100644 index 000000000..df766cea5 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2023-present 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.core; + +import io.prometheus.jmx.test.support.ExporterPath; +import io.prometheus.jmx.test.support.ExporterTestEnvironment; +import io.prometheus.jmx.test.support.TestSupport; +import io.prometheus.jmx.test.support.http.HttpClient; +import io.prometheus.jmx.test.support.http.HttpHeader; +import io.prometheus.jmx.test.support.http.HttpResponse; +import io.prometheus.jmx.test.support.metrics.Metric; +import io.prometheus.jmx.test.support.metrics.MetricsContentType; +import io.prometheus.jmx.test.support.metrics.MetricsParser; +import org.testcontainers.containers.Network; +import org.verifyica.api.ArgumentContext; +import org.verifyica.api.ClassContext; +import org.verifyica.api.Trap; +import org.verifyica.api.Verifyica; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Stream; + +import static io.prometheus.jmx.test.support.Assertions.assertCommonMetricsResponse; +import static io.prometheus.jmx.test.support.Assertions.assertHealthyResponse; +import static org.assertj.core.api.Assertions.assertThat; + +public class MetricCustomizersAttributesAsLabelsExtraMetricsTest { + + @Verifyica.ArgumentSupplier(parallelism = Integer.MAX_VALUE) + public static Stream arguments() { + return ExporterTestEnvironment.createExporterTestEnvironments(); + } + + @Verifyica.Prepare + public static void prepare(ClassContext classContext) { + TestSupport.getOrCreateNetwork(classContext); + } + + @Verifyica.BeforeAll + public void beforeAll(ArgumentContext argumentContext) { + Class testClass = argumentContext.classContext().testClass(); + Network network = TestSupport.getOrCreateNetwork(argumentContext); + TestSupport.initializeExporterTestEnvironment(argumentContext, network, testClass); + } + + @Verifyica.Test + @Verifyica.Order(1) + public void testHealthy(ExporterTestEnvironment exporterTestEnvironment) throws + IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.HEALTHY); + + HttpResponse httpResponse = HttpClient.sendRequest(url); + + assertHealthyResponse(httpResponse); + } + + @Verifyica.Test + public void testDefaultTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = HttpClient.sendRequest(url); + + assertMetricsResponse(exporterTestEnvironment, httpResponse, MetricsContentType.DEFAULT); + } + + @Verifyica.Test + public void testOpenMetricsTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.OPEN_METRICS_TEXT_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, + httpResponse, + MetricsContentType.OPEN_METRICS_TEXT_METRICS); + } + + @Verifyica.Test + public void testPrometheusTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.PROMETHEUS_TEXT_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, httpResponse, + MetricsContentType.PROMETHEUS_TEXT_METRICS); + } + + @Verifyica.Test + public void testPrometheusProtobufMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.PROMETHEUS_PROTOBUF_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, + httpResponse, + MetricsContentType.PROMETHEUS_PROTOBUF_METRICS); + } + + @Verifyica.AfterAll + public void afterAll(ArgumentContext argumentContext) throws Throwable { + List traps = new ArrayList<>(); + + traps.add(new Trap(() -> TestSupport.destroyExporterTestEnvironment(argumentContext))); + traps.add(new Trap(() -> TestSupport.destroyNetwork(argumentContext))); + + Trap.assertEmpty(traps); + } + + @Verifyica.Conclude + public static void conclude(ClassContext classContext) throws Throwable { + new Trap(() -> TestSupport.destroyNetwork(classContext)).assertEmpty(); + } + + private void assertMetricsResponse( + ExporterTestEnvironment exporterTestEnvironment, + HttpResponse httpResponse, + MetricsContentType metricsContentType) { + assertCommonMetricsResponse(httpResponse, metricsContentType); + + Collection metrics = MetricsParser.parseCollection(httpResponse); + + metrics.stream() + .filter(metric -> metric.name().equals("io_prometheus_jmx_stringValue_isActive")) + .forEach( + metric -> { + assertThat(metric.value()) + .isEqualTo(1); + assertThat(metric.labels()) + .containsEntry("Text", "value"); + }); + } +} diff --git a/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest.java b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest.java new file mode 100644 index 000000000..901b4b6f6 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/java/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2023-present 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.core; + +import static io.prometheus.jmx.test.support.Assertions.assertCommonMetricsResponse; +import static io.prometheus.jmx.test.support.Assertions.assertHealthyResponse; +import static org.assertj.core.api.Assertions.assertThat; + +import io.prometheus.jmx.test.support.ExporterPath; +import io.prometheus.jmx.test.support.ExporterTestEnvironment; +import io.prometheus.jmx.test.support.TestSupport; +import io.prometheus.jmx.test.support.http.HttpClient; +import io.prometheus.jmx.test.support.http.HttpHeader; +import io.prometheus.jmx.test.support.http.HttpResponse; +import io.prometheus.jmx.test.support.metrics.Metric; +import io.prometheus.jmx.test.support.metrics.MetricsContentType; +import io.prometheus.jmx.test.support.metrics.MetricsParser; + +import java.io.IOException; +import java.util.*; +import java.util.stream.Stream; + +import org.testcontainers.containers.Network; +import org.verifyica.api.ArgumentContext; +import org.verifyica.api.ClassContext; +import org.verifyica.api.Trap; +import org.verifyica.api.Verifyica; + +public class MetricCustomizersExtraMetricsTest { + + @Verifyica.ArgumentSupplier(parallelism = Integer.MAX_VALUE) + public static Stream arguments() { + return ExporterTestEnvironment.createExporterTestEnvironments(); + } + + @Verifyica.Prepare + public static void prepare(ClassContext classContext) { + TestSupport.getOrCreateNetwork(classContext); + } + + @Verifyica.BeforeAll + public void beforeAll(ArgumentContext argumentContext) { + Class testClass = argumentContext.classContext().testClass(); + Network network = TestSupport.getOrCreateNetwork(argumentContext); + TestSupport.initializeExporterTestEnvironment(argumentContext, network, testClass); + } + + @Verifyica.Test + @Verifyica.Order(1) + public void testHealthy(ExporterTestEnvironment exporterTestEnvironment) throws + IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.HEALTHY); + + HttpResponse httpResponse = HttpClient.sendRequest(url); + + assertHealthyResponse(httpResponse); + } + + @Verifyica.Test + public void testDefaultTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = HttpClient.sendRequest(url); + + assertMetricsResponse(exporterTestEnvironment, httpResponse, MetricsContentType.DEFAULT); + } + + @Verifyica.Test + public void testOpenMetricsTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.OPEN_METRICS_TEXT_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, + httpResponse, + MetricsContentType.OPEN_METRICS_TEXT_METRICS); + } + + @Verifyica.Test + public void testPrometheusTextMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.PROMETHEUS_TEXT_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, httpResponse, + MetricsContentType.PROMETHEUS_TEXT_METRICS); + } + + @Verifyica.Test + public void testPrometheusProtobufMetrics(ExporterTestEnvironment exporterTestEnvironment) + throws IOException { + String url = exporterTestEnvironment.getUrl(ExporterPath.METRICS); + + HttpResponse httpResponse = + HttpClient.sendRequest( + url, + HttpHeader.ACCEPT, + MetricsContentType.PROMETHEUS_PROTOBUF_METRICS.toString()); + + assertMetricsResponse( + exporterTestEnvironment, + httpResponse, + MetricsContentType.PROMETHEUS_PROTOBUF_METRICS); + } + + @Verifyica.AfterAll + public void afterAll(ArgumentContext argumentContext) throws Throwable { + List traps = new ArrayList<>(); + + traps.add(new Trap(() -> TestSupport.destroyExporterTestEnvironment(argumentContext))); + traps.add(new Trap(() -> TestSupport.destroyNetwork(argumentContext))); + + Trap.assertEmpty(traps); + } + + @Verifyica.Conclude + public static void conclude(ClassContext classContext) throws Throwable { + new Trap(() -> TestSupport.destroyNetwork(classContext)).assertEmpty(); + } + + private void assertMetricsResponse( + ExporterTestEnvironment exporterTestEnvironment, + HttpResponse httpResponse, + MetricsContentType metricsContentType) { + assertCommonMetricsResponse(httpResponse, metricsContentType); + + Collection metrics = MetricsParser.parseCollection(httpResponse); + + /* + * Assert that the mbean has a certain metric + */ + metrics.stream() + .filter(metric -> metric.name().equals("io_prometheus_jmx_stringValue_isActive")) + .forEach( + metric -> + assertThat(metric.value()) + .isEqualTo(1)); + } +} diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/application.sh new file mode 100644 index 000000000..5795d5c47 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/application.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -javaagent:jmx_prometheus_javaagent.jar=8888:exporter.yaml \ + -jar jmx_example_application.jar diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/exporter.yaml new file mode 100644 index 000000000..c5e441245 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/JavaAgent/exporter.yaml @@ -0,0 +1,12 @@ +includeObjectNames: ["io.prometheus.jmx:type=stringValue"] +metricCustomizers: + - mbeanFilter: + domain: io.prometheus.jmx + properties: + type: stringValue + attributesAsLabels: + - Text + extraMetrics: + - name: isActive + value: true + description: This is a boolean value indicating if the scenario is still active or is completed. diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/application.sh new file mode 100644 index 000000000..9efc7364d --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/application.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -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 diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.sh new file mode 100644 index 000000000..3de46adb5 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -jar jmx_prometheus_standalone.jar 8888 exporter.yaml diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.yaml new file mode 100644 index 000000000..61a908e59 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersAttributesAsLabelsExtraMetricsTest/Standalone/exporter.yaml @@ -0,0 +1,13 @@ +hostPort: application:9999 +includeObjectNames: ["io.prometheus.jmx:type=stringValue"] +metricCustomizers: + - mbeanFilter: + domain: io.prometheus.jmx + properties: + type: stringValue + attributesAsLabels: + - Text + extraMetrics: + - name: isActive + value: true + description: This is a boolean value indicating if the scenario is still active or is completed. diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/application.sh new file mode 100644 index 000000000..5795d5c47 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/application.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -javaagent:jmx_prometheus_javaagent.jar=8888:exporter.yaml \ + -jar jmx_example_application.jar diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/exporter.yaml new file mode 100644 index 000000000..7796d425b --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/JavaAgent/exporter.yaml @@ -0,0 +1,10 @@ +includeObjectNames: ["io.prometheus.jmx:type=stringValue"] +metricCustomizers: + - mbeanFilter: + domain: io.prometheus.jmx + properties: + type: stringValue + extraMetrics: + - name: isActive + value: true + description: This is a boolean value indicating if the scenario is still active or is completed. diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/application.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/application.sh new file mode 100644 index 000000000..9efc7364d --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/application.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -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 diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.sh b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.sh new file mode 100644 index 000000000..3de46adb5 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +java \ + -Xmx512M \ + -jar jmx_prometheus_standalone.jar 8888 exporter.yaml diff --git a/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.yaml b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.yaml new file mode 100644 index 000000000..cc1e19f13 --- /dev/null +++ b/integration_test_suite/integration_tests/src/test/resources/io/prometheus/jmx/test/core/MetricCustomizersExtraMetricsTest/Standalone/exporter.yaml @@ -0,0 +1,11 @@ +hostPort: application:9999 +includeObjectNames: ["io.prometheus.jmx:type=stringValue"] +metricCustomizers: + - mbeanFilter: + domain: io.prometheus.jmx + properties: + type: stringValue + extraMetrics: + - name: isActive + value: true + description: This is a boolean value indicating if the scenario is still active or is completed. diff --git a/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/JmxExampleApplication.java b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/JmxExampleApplication.java index 48b46894d..6900574b1 100644 --- a/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/JmxExampleApplication.java +++ b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/JmxExampleApplication.java @@ -62,6 +62,9 @@ public static void main(String[] args) throws Exception { mBeanServer.registerMBean( new CustomValue(), new ObjectName("io.prometheus.jmx:type=customValue")); + mBeanServer.registerMBean( + new StringValue(), new ObjectName("io.prometheus.jmx:type=stringValue")); + System.out.printf( "%s | %s | INFO | %s | %s%n", LocalDateTime.now().format(DATE_TIME_FORMATTER), diff --git a/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/StringValueMBean.java b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/StringValueMBean.java new file mode 100644 index 000000000..4ae9972c4 --- /dev/null +++ b/integration_test_suite/jmx_example_application/src/main/java/io/prometheus/jmx/StringValueMBean.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023-present 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; + +/** Class to implement StringValueMBean */ +public interface StringValueMBean { + + /** + * Method to get the text + * + * @return text + */ + String getText(); +} + +/** Class to implement CustomValue */ +class StringValue implements StringValueMBean { + + /** Constructor */ + public StringValue() { + // INTENTIONALLY BLANK + } + + @Override + public String getText() { + return "value"; + } +}