Skip to content
Open
Show file tree
Hide file tree
Changes from 19 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
2 changes: 1 addition & 1 deletion instrumentation/jmx-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ $ java -javaagent:path/to/opentelemetry-javaagent.jar \

No targets are enabled by default. The supported target environments are listed below.

- [activemq](javaagent/activemq.md)
- [activemq](library/activemq.md)
- [camel](javaagent/camel.md)
- [jetty](library/jetty.md)
- [kafka-broker](javaagent/kafka-broker.md)
Expand Down
17 changes: 0 additions & 17 deletions instrumentation/jmx-metrics/javaagent/activemq.md

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
class JmxMetricInsightInstallerTest {
private static final String PATH_TO_ALL_EXISTING_RULES = "src/main/resources/jmx/rules";
private static final Set<String> FILES_TO_BE_TESTED =
new HashSet<>(Arrays.asList("activemq.yaml", "camel.yaml", "kafka-broker.yaml"));
new HashSet<>(Arrays.asList("camel.yaml", "kafka-broker.yaml"));

@Test
void testToVerifyExistingRulesAreValid() throws Exception {
Expand Down
33 changes: 33 additions & 0 deletions instrumentation/jmx-metrics/library/activemq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ActiveMQ Metrics

Here is the list of metrics based on MBeans exposed by ActiveMQ.

For now, only ActiveMQ classic is supported.

| Metric Name | Type | Unit | Attributes | Description |
|-------------------------------------------|---------------|--------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| activemq.producer.count | UpDownCounter | {producer} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The number of producers attached to this destination |
| activemq.consumer.count | UpDownCounter | {consumer} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The number of consumers subscribed to this destination |
| activemq.memory.destination.usage | UpDownCounter | By | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The amount of used memory by this destination |
| activemq.memory.destination.limit | UpDownCounter | By | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The amount of configured memory limit for this destination |
| activemq.temp.destination.utilization | gauge | 1 | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The percentage of non-persistent storage used by this destination |
| activemq.temp.destination.limit | UpDownCounter | By | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The amount of configured non-persistent storage limit |
| activemq.message.queue.size | UpDownCounter | {message} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The current number of messages waiting to be consumed |
| activemq.message.expired | Counter | {message} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The number of messages not delivered because they expired |
| activemq.message.enqueued | Counter | {message} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The number of messages sent to this destination |
| activemq.message.dequeued | Counter | {message} | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The number of messages acknowledged and removed from this destination |
| activemq.message.enqueue.average_duration | Gauge | s | messaging.system, messaging.destination.name, activemq.broker.name, activemq.destination.type | The average time a message was held on this destination |
| activemq.connection.count | UpDownCounter | {connection} | messaging.system, activemq.broker.name | The number of active connections |
| activemq.memory.utilization | Gauge | 1 | messaging.system, activemq.broker.name | The percentage of broker memory used |
| activemq.memory.limit | UpDownCounter | By | messaging.system, activemq.broker.name | The amount of configured broker memory limit |
| activemq.store.utilization | Gauge | 1 | messaging.system, activemq.broker.name | The percentage of broker persistent storage used |
| activemq.store.limit | UpDownCounter | By | messaging.system, activemq.broker.name | The amount of configured broker persistent storage limit |
| activemq.temp.utilization | Gauge | 1 | messaging.system, activemq.broker.name | The percentage of broker non-persistent storage used |
| activemq.temp.limit | UpDownCounter | By | messaging.system, activemq.broker.name | The amount of configured broker non-persistent storage limit |

## Attributes

- `messaging.system` is always set to `activemq` ([semconv](https://opentelemetry.io/docs/specs/semconv/registry/attributes/messaging/#messaging-system))
- `messaging.destination.name` contains the destination.name ([semconv](https://opentelemetry.io/docs/specs/semconv/registry/attributes/messaging/#messaging-destination-name))
- `activemq.broker.name` contains the name of the broker
- `activemq.destination.type` is set to `queue` for queues (point-to-point), `topic` for topics (multicast).
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class UnitConverter {
registerConversion("ms", "s", value -> value.doubleValue() / TimeUnit.SECONDS.toMillis(1));
registerConversion("us", "s", value -> value.doubleValue() / TimeUnit.SECONDS.toMicros(1));
registerConversion("ns", "s", value -> value.doubleValue() / TimeUnit.SECONDS.toNanos(1));
registerConversion("%", "1", value -> value.doubleValue() / 100d);
}

private final Function<Number, Number> convertingFunction;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
rules:

# Topic and Queues level metrics
- bean: org.apache.activemq:type=Broker,brokerName=*,destinationType=*,destinationName=*
metricAttribute:
messaging.destination.name: param(destinationName)
messaging.system: const(activemq)
# 'topic' or 'queue'
activemq.destination.type: lowercase(param(destinationType))
activemq.broker.name: param(brokerName)
prefix: activemq.
mapping:
# activemq.producer.count
ProducerCount:
metric: producer.count
unit: "{producer}"
type: updowncounter
desc: The number of producers attached to this destination
# activemq.consumer.count
ConsumerCount:
metric: consumer.count
unit: "{consumer}"
type: updowncounter
desc: The number of consumers subscribed to this destination
# activemq.memory.destination.usage
MemoryUsageByteCount:
metric: memory.destination.usage
unit: By
type: updowncounter
desc: The amount of used memory by this destination
# activemq.memory.destination.limit
MemoryLimit:
metric: memory.destination.limit
unit: By
type: updowncounter
desc: The amount of configured memory limit for this destination
# activemq.temp.destination.utilization
TempUsagePercentUsage:
metric: temp.destination.utilization
unit: "1"
type: gauge
desc: The percentage of non-persistent storage used by this destination
# activemq.temp.destination.limit
TempUsageLimit:
metric: temp.destination.limit
unit: By
type: updowncounter
desc: The amount of configured non-persistent storage limit for this destination
# activemq.message.queue.size
QueueSize:
metric: message.queue.size
unit: "{message}"
type: updowncounter
desc: The current number of messages waiting to be consumed
# activemq.message.expired
ExpiredCount:
metric: message.expired
unit: "{message}"
type: counter
desc: The number of messages not delivered because they expired
# activemq.message.enqueued
EnqueueCount:
metric: message.enqueued
unit: "{message}"
type: counter
desc: The number of messages sent to this destination
# activemq.message.dequeued
DequeueCount:
metric: message.dequeued
unit: "{message}"
type: counter
desc: The number of messages acknowledged and removed from this destination
# activemq.message.enqueue.average_duration
AverageEnqueueTime:
metric: message.enqueue.average_duration
sourceUnit: ms
unit: s
type: gauge
desc: The average time a message was held on this destination

# Broker-level metrics
- bean: org.apache.activemq:type=Broker,brokerName=*
metricAttribute:
messaging.system: const(activemq)
activemq.broker.name: param(brokerName)
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider messaging.activemq.broker.name

Choose a reason for hiding this comment

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

Or even messaging.brooker.name so it can be reused.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is messaging.broker.name a part of semconv?

Choose a reason for hiding this comment

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

Not currently but it could be added.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In order to generalize activemq.broker.name by adding messaging.broker.name to semconv we need to have more than one implementation to serve as an example (this PR provides one).

From experience, it usually takes a while as name-related discussions always take time to settle, I don't think we should make this PR depend on it. We can always iterate on it later and change that once a stable semconv attribute is available.

prefix: activemq.
mapping:
# activemq.connection.count
CurrentConnectionsCount:
metric: connection.count
type: updowncounter
unit: "{connection}"
desc: The number of active connections
# activemq.memory.utilization
MemoryPercentUsage:
metric: memory.utilization
type: gauge
sourceUnit: "%"
unit: "1"
desc: The percentage of broker memory used
# activemq.memory.limit
MemoryLimit:
metric: memory.limit
type: updowncounter
unit: By
desc: The amount of configured broker memory limit
# activemq.store.utilization
StorePercentUsage:
metric: store.utilization
type: gauge
sourceUnit: "%"
unit: "1"
desc: The percentage of broker persistent storage used
# activemq.store.limit
StoreLimit:
metric: store.limit
type: updowncounter
unit: By
desc: The amount of configured broker persistent storage limit
# activemq.temp.utilization
TempPercentUsage:
metric: temp.utilization
type: gauge
sourceUnit: "%"
unit: "1"
desc: The percentage of broker non-persistent storage used
# activemq.temp.limit
TempLimit:
metric: temp.limit
type: updowncounter
unit: By
desc: The amount of configured broker non-persistent storage limit
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,26 @@ class UnitConverterTest {
})
void shouldSupportPredefined_to_s_Conversions(
Long originalValue, String originalUnit, Double expectedConvertedValue) {
// Given
String targetUnit = "s";
testConversion(originalValue, originalUnit, expectedConvertedValue, "s");
}

// When
@ParameterizedTest
@CsvSource({
"100,1.0", "99,0.99", "1,0.01", "0,0",
})
void shouldSupportPredefined_percent_Conversions(
Long originalValue, Double expectedConvertedValue) {
testConversion(originalValue, "%", expectedConvertedValue, "1");
}

private static void testConversion(
Long originalValue, String originalUnit, Double expectedConvertedValue, String targetUnit) {
UnitConverter converter = UnitConverter.getInstance(originalUnit, targetUnit);

assertThat(converter).isNotNull();
Number actualValue = converter.convert(originalValue);

// Then
assertEquals(expectedConvertedValue, actualValue);
assertThat(expectedConvertedValue).isEqualTo(actualValue);
}

@ParameterizedTest
Expand Down
Loading
Loading