Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Activemq #188

Merged
merged 12 commits into from
Jan 19, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
79 changes: 79 additions & 0 deletions jmx-metrics/docs/target-systems/activemq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# ActiveMQ Metrics
rmfitzpatrick marked this conversation as resolved.
Show resolved Hide resolved

The JMX Metric Gatherer provides built in ActiveMQ metric gathering capabilities.
These metrics are sourced from: https://activemq.apache.org/jmx

### Metrics

* Name: `activemq.consumer.count`
* Description: The number of consumers currently reading from the broker.
* Unit: `{consumers}`
rmfitzpatrick marked this conversation as resolved.
Show resolved Hide resolved
* Labels: `destination`
* Instrument Type: LongUpDownCounterCallback
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to standardize these names throughout our docs, but should these be something like ObservableLongUpDownCounter? I'm not sure where the spec has landed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious about this one, can't seem to find any reference to how we should be naming it, personally, to me, it seems to make sense to match what's actually being used in the script. Is there a reason we're adding "observable"? just wasn't sure about this one. Thanks for any clarification!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.



* Name: `activemq.producer.count`
* Description: The number of producers currently attached to the broker.
* Unit: `{producers}`
* Labels: `destination`
* Instrument Type: LongUpDownCounterCallback


* Name: `activemq.connection.count`
* Description: The total number of current connections.
* Unit: `{connections}`
* Instrument Type: LongUpDownCounterCallback


* Name: `activemq.memory.usage`
* Description: The percentage of configured memory used.
* Unit: `%`
* Labels: `destination`
* Instrument Type: DoubleValueCallback


* Name: `activemq.disk.store_usage`
* Description: The percentage of configured disk used for persistent messages.
* Unit: `%`
* Instrument Type: DoubleValueCallback


* Name: `activemq.disk.temp_usage`
* Description: The percentage of configured disk used for non-persistent messages.
* Unit: `%`
* Instrument Type: DoubleValueCallback


* Name: `activemq.message.current`
* Description: The current number of messages waiting to be consumed.
* Unit: `messages`
* Labels: `destination`
* Instrument Type: LongUpDownCounterCallback


* Name: `activemq.message.expired`
* Description: The total number of messages not delivered because they expired.
* Unit: `messages`
* Labels: `destination`
* Instrument Type: LongCounterCallback


* Name: `activemq.message.enqueued`
* Description: The total number of messages received by the broker.
* Unit: `messages`
* Labels: `destination`
* Instrument Type: LongCounterCallback


* Name: `activemq.message.dequeued`
* Description: The total number of messages delivered to consumers.
* Unit: `messages`
* Labels: `destination`
* Instrument Type: LongCounterCallback


* Name: `activemq.wait_time.avg`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this name is wrong compared to the script activemq.message.wait_time.avg

* Description: The average time a message was held on a destination.
* Unit: `ms`
* Labels: `destination`
* Instrument Type: DoubleValueCallback
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.jmxmetrics.target_systems;

import static org.assertj.core.api.Assertions.entry;

import io.opentelemetry.contrib.jmxmetrics.AbstractIntegrationTest;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;
import org.testcontainers.junit.jupiter.Container;

class ActivemqIntegrationTest extends AbstractIntegrationTest {

ActivemqIntegrationTest() {
super(/* configFromStdin= */ false, "target-systems/activemq.properties");
}

@Container
GenericContainer<?> activemq =
new GenericContainer<>(
new ImageFromDockerfile()
.withFileFromClasspath("config/env", "activemq/config/env")
.withFileFromClasspath("Dockerfile", "activemq/Dockerfile"))
.withNetwork(Network.SHARED)
.withEnv("LOCAL_JMX", "no")
.withNetworkAliases("activemq")
.withExposedPorts(10991)
.withStartupTimeout(Duration.ofMinutes(2))
.waitingFor(Wait.forListeningPort());

@Test
void endToEnd() {
waitAndAssertMetrics(
metric ->
assertSumWithAttributes(
metric,
"activemq.consumer.count",
"The number of consumers currently reading from the broker.",
"{consumers}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
metric ->
assertSumWithAttributes(
metric,
"activemq.producer.count",
"The number of producers currently attached to the broker.",
"{producers}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
metric ->
assertSum(
metric,
"activemq.connection.count",
"The total number of current connections.",
"{connections}",
/* isMonotonic= */ false),
metric ->
assertGaugeWithAttributes(
metric,
"activemq.memory.usage",
"The percentage of configured memory used.",
"%",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
metric ->
assertGauge(
metric,
"activemq.disk.store_usage",
"The percentage of configured disk used for persistent messages.",
"%"),
metric ->
assertGauge(
metric,
"activemq.disk.temp_usage",
"The percentage of configured disk used for non-persistent messages.",
"%"),
metric ->
assertSumWithAttributes(
metric,
"activemq.message.current",
"The current number of messages waiting to be consumed.",
"{messages}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
metric ->
assertSumWithAttributes(
metric,
"activemq.message.current",
"The current number of messages waiting to be consumed.",
"{messages}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
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"))),
metric ->
assertSumWithAttributes(
metric,
"activemq.message.enqueued",
"The total number of messages received by the broker.",
"{messages}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
metric ->
assertSumWithAttributes(
metric,
"activemq.message.dequeued",
"The total number of messages delivered to consumers.",
"{messages}",
attrs ->
attrs.containsOnly(entry("destination", "ActiveMQ.Advisory.MasterBroker"))),
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"))));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM rmohr/activemq:5.15.9-alpine


COPY --chown=activemq config/env /opt/activemq/bin/env
ENV ACTIVEMQ_JMX=10991
EXPOSE $ACTIVEMQ_JMX

ENV ACTIVEMQ_JMX_OPTS="-Dcom.sun.management.jmxremote.port=10991 -Dcom.sun.management.jmxremote.rmi.port=10991 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
117 changes: 117 additions & 0 deletions jmx-metrics/src/integrationTest/resources/activemq/config/env
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/bin/sh
# ------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
# ------------------------------------------------------------------------
#
# Configuration file for running Apache Active MQ as standalone provider.
#
# This file overwrites the predefined settings of the sysv init-script.
# You can also use alternate location for default settings -
# invoke the init-script without a argument an review help section "Configuration of this script"
# /etc/default/activemq <activemq user home>/.activemqrc <activemq installation dir>/bin/env

# Active MQ installation dirs
# ACTIVEMQ_HOME="<Installationdir>/"
# ACTIVEMQ_BASE="$ACTIVEMQ_HOME"
# ACTIVEMQ_CONF="$ACTIVEMQ_BASE/conf"
# ACTIVEMQ_DATA="$ACTIVEMQ_BASE/data"
# ACTIVEMQ_TMP="$ACTIVEMQ_BASE/tmp"

# Set jvm memory configuration (minimal/maximum amount of memory)
ACTIVEMQ_OPTS_MEMORY="-Xms64M -Xmx256M"

if [ -z "$ACTIVEMQ_OPTS" ] ; then
ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS_MEMORY -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=$ACTIVEMQ_CONF/login.config"
fi

if [ -z "$ACTIVEMQ_OUT" ]; then
ACTIVEMQ_OUT="/dev/null"
fi

# Uncomment to enable audit logging
#ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS -Dorg.apache.activemq.audit=true"

# Set jvm jmx configuration
# This enables jmx access over a configured jmx-tcp-port.
# You have to configure the first four settings if you run a ibm jvm, caused by the
# fact that IBM's jvm does not support VirtualMachine.attach(PID).
# JMX access is needed for quering a running activemq instance to gain data or to
# trigger management operations.
#
# Example for ${ACTIVEMQ_CONF}/jmx.access:
# ---
# # The "monitorRole" role has readonly access.
# # The "controlRole" role has readwrite access.
# monitorRole readonly
# controlRole readwrite
# ---
#
# Example for ${ACTIVEMQ_CONF}/jmx.password:
# ---
# # The "monitorRole" role has password "abc123".
# # # The "controlRole" role has password "abcd1234".
# monitorRole abc123
# controlRole abcd1234
# ---
#
# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.port=11099 "
# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.password.file=${ACTIVEMQ_CONF}/jmx.password"
# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.access.file=${ACTIVEMQ_CONF}/jmx.access"
# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote.ssl=false"
# ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote"
ACTIVEMQ_SUNJMX_START="$ACTIVEMQ_SUNJMX_START -Dcom.sun.management.jmxremote"

# Set jvm jmx configuration for controlling the broker process
# You only have to configure the first four settings if you run a ibm jvm, caused by the
# fact that IBM's jvm does not support VirtualMachine.attach(PID)
# (see also com.sun.management.jmxremote.port, .jmx.password.file and .jmx.access.file )
#ACTIVEMQ_SUNJMX_CONTROL="--jmxurl service:jmx:rmi:///jndi/rmi://127.0.0.1:1099/jmxrmi --jmxuser controlRole --jmxpassword abcd1234"
ACTIVEMQ_SUNJMX_CONTROL=""

# Specify the queue manager URL for using "browse" option of sysv initscript
if [ -z "$ACTIVEMQ_QUEUEMANAGERURL" ]; then
ACTIVEMQ_QUEUEMANAGERURL="--amqurl tcp://localhost:61616"
fi

# Set additional JSE arguments
if [ -z "$ACTIVEMQ_SSL_OPTS" ] ; then
#ACTIVEMQ_SSL_OPTS="-Djava.security.properties=$ACTIVEMQ_CONF/java.security"
ACTIVEMQ_SSL_OPTS=""
fi

# Uncomment to enable remote debugging
#ACTIVEMQ_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"

# ActiveMQ tries to shutdown the broker by jmx,
# after a specified number of seconds send SIGKILL
if [ -z "$ACTIVEMQ_KILL_MAXSECONDS" ]; then
ACTIVEMQ_KILL_MAXSECONDS=30
fi

# Configure a user with non root privileges, if no user is specified do not change user
# (the entire activemq installation should be owned by this user)
ACTIVEMQ_USER=""

# location of the pidfile
# ACTIVEMQ_PIDFILE="$ACTIVEMQ_DATA/activemq.pid"

# Location of the java installation
# Specify the location of your java installation using JAVA_HOME, or specify the
# path to the "java" binary using JAVACMD
# (set JAVACMD to "auto" for automatic detection)
#JAVA_HOME=""
JAVACMD="auto"
ACTIVEMQ_OPTS="$ACTIVEMQ_OPTS $ACTIVEMQ_JMX_OPTS -Dhawtio.authenticationEnabled=false -Dhawtio.realm=activemq -Dhawtio.role=admins -Dhawtio.rolePrincipalClasses=org.apache.activemq.jaas.GroupPrincipal"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
otel.jmx.interval.milliseconds = 3000
otel.metrics.exporter = otlp
otel.jmx.service.url = service:jmx:rmi:///jndi/rmi://activemq:10991/jmxrmi
otel.jmx.target.system = activemq

# these will be overridden by cmd line
otel.exporter.otlp.endpoint = http://host.testcontainers.internal
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class JmxConfig {
static final String JMX_REALM = PREFIX + "jmx.realm";

static final List<String> AVAILABLE_TARGET_SYSTEMS =
Arrays.asList("cassandra", "jvm", "kafka", "kafka-consumer", "kafka-producer", "tomcat");
Arrays.asList(
"cassandra", "jvm", "kafka", "kafka-consumer", "kafka-producer", "tomcat", "activemq");

final String serviceUrl;
final String groovyScript;
Expand Down
Loading