From f8c7cb43f9db80c26cc1112ad63544654747b33b Mon Sep 17 00:00:00 2001 From: Robert Niedziela <175605712+robsunday@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:12:09 +0200 Subject: [PATCH] Integration test activemq (#1497) Co-authored-by: Sylvain Juge <763082+SylvainJuge@users.noreply.github.com> --- .../ActiveMqIntegrationTest.java | 152 ++++++++++++++++++ .../target_systems/MetricAssertions.java | 13 ++ .../target_systems/TomcatIntegrationTest.java | 1 - .../contrib/jmxscraper/JmxScraper.java | 2 +- jmx-scraper/src/main/resources/activemq.yaml | 85 ++++++++++ 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java create mode 100644 jmx-scraper/src/main/resources/activemq.yaml diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java new file mode 100644 index 000000000..036996f5e --- /dev/null +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/ActiveMqIntegrationTest.java @@ -0,0 +1,152 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jmxscraper.target_systems; + +import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertGaugeWithAttributes; +import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertSumWithAttributes; +import static org.assertj.core.api.Assertions.entry; + +import io.opentelemetry.contrib.jmxscraper.JmxScraperContainer; +import java.time.Duration; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.images.builder.ImageFromDockerfile; + +public class ActiveMqIntegrationTest extends TargetSystemIntegrationTest { + + @Override + protected GenericContainer createTargetContainer(int jmxPort) { + return new GenericContainer<>( + new ImageFromDockerfile() + .withDockerfileFromBuilder( + builder -> builder.from("apache/activemq-classic:5.18.6").build())) + .withEnv( + "JAVA_TOOL_OPTIONS", + "-Dcom.sun.management.jmxremote.port=" + + jmxPort + + " -Dcom.sun.management.jmxremote.rmi.port=" + + jmxPort + + " -Dcom.sun.management.jmxremote.ssl=false" + + " -Dcom.sun.management.jmxremote.authenticate=false") + .withStartupTimeout(Duration.ofMinutes(2)) + .waitingFor(Wait.forListeningPort()); + } + + @Override + protected JmxScraperContainer customizeScraperContainer(JmxScraperContainer scraper) { + return scraper.withTargetSystem("activemq"); + } + + @Override + protected void verifyMetrics() { + waitAndAssertMetrics( + metric -> + assertSumWithAttributes( + metric, + "activemq.consumer.count", + "The number of consumers currently reading from the broker.", + "consumers", + /* isMonotonic= */ false, + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.producer.count", + "The number of producers currently attached to the broker.", + "producers", + /* isMonotonic= */ false, + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.connection.count", + "The total number of current connections.", + "connections", + /* isMonotonic= */ false, + attrs -> attrs.containsOnly(entry("broker", "localhost"))), + metric -> + assertGaugeWithAttributes( + metric, + "activemq.memory.usage", + "The percentage of configured memory used.", + "%", + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertGaugeWithAttributes( + metric, + "activemq.disk.store_usage", + "The percentage of configured disk used for persistent messages.", + "%", + attrs -> attrs.containsOnly(entry("broker", "localhost"))), + metric -> + assertGaugeWithAttributes( + metric, + "activemq.disk.temp_usage", + "The percentage of configured disk used for non-persistent messages.", + "%", + attrs -> attrs.containsOnly(entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.message.current", + "The current number of messages waiting to be consumed.", + "messages", + /* isMonotonic= */ false, + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.message.expired", + "The total number of messages not delivered because they expired.", + "messages", + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.message.enqueued", + "The total number of messages received by the broker.", + "messages", + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertSumWithAttributes( + metric, + "activemq.message.dequeued", + "The total number of messages delivered to consumers.", + "messages", + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost"))), + metric -> + assertGaugeWithAttributes( + metric, + "activemq.message.wait_time.avg", + "The average time a message was held on a destination.", + "ms", + attrs -> + attrs.containsOnly( + entry("destination", "ActiveMQ.Advisory.MasterBroker"), + entry("broker", "localhost")))); + } +} diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/MetricAssertions.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/MetricAssertions.java index addf145ea..cbd46c350 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/MetricAssertions.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/MetricAssertions.java @@ -72,10 +72,23 @@ static void assertSumWithAttributes( String description, String unit, Consumer>... attributeGroupAssertions) { + assertSumWithAttributes( + metric, name, description, unit, /* isMonotonic= */ true, attributeGroupAssertions); + } + + @SafeVarargs + static void assertSumWithAttributes( + Metric metric, + String name, + String description, + String unit, + boolean isMonotonic, + Consumer>... attributeGroupAssertions) { assertThat(metric.getName()).isEqualTo(name); assertThat(metric.getDescription()).isEqualTo(description); assertThat(metric.getUnit()).isEqualTo(unit); assertThat(metric.hasSum()).isTrue(); + assertThat(metric.getSum().getIsMonotonic()).isEqualTo(isMonotonic); assertAttributedPoints(metric.getSum().getDataPointsList(), attributeGroupAssertions); } diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java index 500e89f82..76bacf265 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/TomcatIntegrationTest.java @@ -30,7 +30,6 @@ protected GenericContainer createTargetContainer(int jmxPort) { "https://tomcat.apache.org/tomcat-9.0-doc/appdev/sample/sample.war", "/usr/local/tomcat/webapps/ROOT.war") .build())) - .withEnv("LOCAL_JMX", "no") .withEnv( "CATALINA_OPTS", "-Dcom.sun.management.jmxremote.local.only=false" diff --git a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java index 1ad51893e..fdee1e0e4 100644 --- a/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java +++ b/jmx-scraper/src/main/java/io/opentelemetry/contrib/jmxscraper/JmxScraper.java @@ -78,7 +78,7 @@ public static void main(String[] args) { System.err.println("Unable to connect " + e.getMessage()); System.exit(2); } catch (RuntimeException e) { - System.err.println("ERROR: " + e.getMessage()); + e.printStackTrace(System.err); System.exit(3); } } diff --git a/jmx-scraper/src/main/resources/activemq.yaml b/jmx-scraper/src/main/resources/activemq.yaml new file mode 100644 index 000000000..8387cf5b6 --- /dev/null +++ b/jmx-scraper/src/main/resources/activemq.yaml @@ -0,0 +1,85 @@ +--- +rules: + - beans: + - org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=* + - org.apache.activemq:type=Broker,brokerName=*,destinationType=Topic,destinationName=* + metricAttribute: + destination: param(destinationName) + broker: param(brokerName) + prefix: activemq. + mapping: + ProducerCount: + metric: producer.count + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "producers" + type: updowncounter + desc: The number of producers currently attached to the broker. + ConsumerCount: + metric: consumer.count + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "consumers" + type: updowncounter + desc: The number of consumers currently reading from the broker. + MemoryPercentUsage: + metric: memory.usage + unit: "%" + type: gauge + desc: The percentage of configured memory used. + QueueSize: + metric: message.current + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "messages" + type: updowncounter + desc: The current number of messages waiting to be consumed. + ExpiredCount: + metric: message.expired + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "messages" + type: counter + desc: The total number of messages not delivered because they expired. + EnqueueCount: + metric: message.enqueued + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "messages" + type: counter + desc: The total number of messages received by the broker. + DequeueCount: + metric: message.dequeued + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "messages" + type: counter + desc: The total number of messages delivered to consumers. + AverageEnqueueTime: + metric: message.wait_time.avg + unit: ms + type: gauge + desc: The average time a message was held on a destination. + + - bean: org.apache.activemq:type=Broker,brokerName=* + metricAttribute: + # minor divergence from activemq.groovy to capture broker name, making it closer to + # the definition in JMX Insights + broker: param(brokerName) + prefix: activemq. + unit: "%" + type: gauge + mapping: + CurrentConnectionsCount: + metric: connection.count + type: updowncounter + # Unit name inherited from activemq.groovy file. + # Will be updated to {} semconv notation when we switch to use original files from JMX Insights + unit: "connections" + desc: The total number of current connections. + StorePercentUsage: + metric: disk.store_usage + desc: The percentage of configured disk used for persistent messages. + TempPercentUsage: + metric: disk.temp_usage + desc: The percentage of configured disk used for non-persistent messages.