Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class JmxScraperContainer extends GenericContainer<JmxScraperContainer> {
private final Set<String> customYamlFiles;

public JmxScraperContainer(String otlpEndpoint) {
super("openjdk:8u272-jre-slim");
super("openjdk:8u342-jre-slim");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

[for reviewer] Updated to most recent version of Java8 and to support arm64 arch


String scraperJarPath = System.getProperty("shadow.jar.path");
assertThat(scraperJarPath).isNotNull();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
* 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.assertGauge;
import static io.opentelemetry.contrib.jmxscraper.target_systems.MetricAssertions.assertSum;
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 java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import org.assertj.core.api.MapAssert;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.images.builder.ImageFromDockerfile;

public class CassandraIntegrationTest extends TargetSystemIntegrationTest {

@Override
protected GenericContainer<?> createTargetContainer(int jmxPort) {
return new GenericContainer<>(
new ImageFromDockerfile()
.withDockerfileFromBuilder(builder -> builder.from("cassandra:5.0.2").build()))
.withEnv(
"JVM_EXTRA_OPTS",
" -Dcassandra.jmx.remote.port="
+ jmxPort
+ " -Dcom.sun.management.jmxremote.rmi.port="
+ jmxPort
+ " -Dcom.sun.management.jmxremote.local.only=false"
+ " -Dcom.sun.management.jmxremote.ssl=false"
+ " -Dcom.sun.management.jmxremote.authenticate=false")
.withStartupTimeout(Duration.ofMinutes(2))
.waitingFor(Wait.forLogMessage(".*Startup complete.*", 1));
}

@Override
protected JmxScraperContainer customizeScraperContainer(JmxScraperContainer scraper) {
return scraper.withTargetSystem("cassandra");
}

@Override
protected void verifyMetrics() {
waitAndAssertMetrics(
metric ->
assertGauge(
metric,
"cassandra.client.request.range_slice.latency.50p",
Copy link
Contributor

Choose a reason for hiding this comment

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

Bummer that cassandra doesn't provide a histogram. :)

"Token range read request latency - 50th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.range_slice.latency.99p",
"Token range read request latency - 99th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.range_slice.latency.max",
"Maximum token range read request latency",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.read.latency.50p",
"Standard read request latency - 50th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.read.latency.99p",
"Standard read request latency - 99th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.read.latency.max",
"Maximum standard read request latency",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.write.latency.50p",
"Regular write request latency - 50th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.write.latency.99p",
"Regular write request latency - 99th percentile",
"us"),
metric ->
assertGauge(
metric,
"cassandra.client.request.write.latency.max",
"Maximum regular write request latency",
"us"),
metric ->
assertSum(
metric,
"cassandra.compaction.tasks.completed",
"Number of completed compactions since server [re]start",
"1"),
metric ->
assertGauge(
metric,
"cassandra.compaction.tasks.pending",
"Estimated number of compactions remaining to perform",
"1"),
metric ->
assertSum(
metric,
"cassandra.storage.load.count",
"Size of the on disk data size this node manages",
"by",
/* isMonotonic= */ false),
metric ->
assertSum(
metric,
"cassandra.storage.total_hints.count",
"Number of hint messages written to this node since [re]start",
"1"),
metric ->
assertSum(
metric,
"cassandra.storage.total_hints.in_progress.count",
"Number of hints attempting to be sent currently",
"1",
/* isMonotonic= */ false),
metric ->
assertSumWithAttributes(
metric,
"cassandra.client.request.count",
"Number of requests by operation",
"1",
attrs -> attrs.containsOnly(entry("operation", "RangeSlice")),
attrs -> attrs.containsOnly(entry("operation", "Read")),
attrs -> attrs.containsOnly(entry("operation", "Write"))),
metric ->
assertSumWithAttributes(
metric,
"cassandra.client.request.error.count",
"Number of request errors by operation",
"1",
getRequestErrorCountAttributes()));
}

@SuppressWarnings("unchecked")
private static Consumer<MapAssert<String, String>>[] getRequestErrorCountAttributes() {
List<String> operations = Arrays.asList("RangeSlice", "Read", "Write");
List<String> statuses = Arrays.asList("Timeout", "Failure", "Unavailable");

return operations.stream()
.flatMap(
op ->
statuses.stream()
.map(
st ->
(Consumer<MapAssert<String, String>>)
attrs ->
attrs.containsOnly(
entry("operation", op), entry("status", st))))
.toArray(Consumer[]::new);
}
}
146 changes: 146 additions & 0 deletions jmx-scraper/src/main/resources/cassandra.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
rules:

# Compaction task
- bean: org.apache.cassandra.metrics:type=Compaction,name=CompletedTasks
mapping:
Value:
metric: cassandra.compaction.tasks.completed
type: counter
unit: "1"
desc: Number of completed compactions since server [re]start

- bean: org.apache.cassandra.metrics:type=Compaction,name=PendingTasks
mapping:
Value:
metric: cassandra.compaction.tasks.pending
type: gauge
unit: "1"
desc: Estimated number of compactions remaining to perform

# Storage
- bean: org.apache.cassandra.metrics:type=Storage,name=Load
mapping:
Count:
metric: cassandra.storage.load.count
type: updowncounter
unit: by
desc: Size of the on disk data size this node manages

- bean: org.apache.cassandra.metrics:type=Storage,name=TotalHints
mapping:
Count:
metric: cassandra.storage.total_hints.count
type: counter
unit: "1"
desc: Number of hint messages written to this node since [re]start

- bean: org.apache.cassandra.metrics:type=Storage,name=TotalHintsInProgress
mapping:
Count:
metric: cassandra.storage.total_hints.in_progress.count
type: updowncounter
unit: "1"
desc: Number of hints attempting to be sent currently

# Client latency
- bean: org.apache.cassandra.metrics:type=ClientRequest,scope=RangeSlice,name=Latency
prefix: cassandra.client.request.range_slice.latency.
unit: us
type: gauge
mapping:
50thPercentile:
metric: 50p
desc: Token range read request latency - 50th percentile
99thPercentile:
metric: 99p
desc: Token range read request latency - 99th percentile
Max:
metric: max
desc: Maximum token range read request latency

- bean: org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency
prefix: cassandra.client.request.read.latency.
unit: us
type: gauge
mapping:
50thPercentile:
metric: 50p
desc: Standard read request latency - 50th percentile
99thPercentile:
metric: 99p
desc: Standard read request latency - 99th percentile
Max:
metric: max
desc: Maximum standard read request latency

- bean: org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Latency
prefix: cassandra.client.request.write.latency.
unit: us
type: gauge
mapping:
50thPercentile:
metric: 50p
desc: Regular write request latency - 50th percentile
99thPercentile:
metric: 99p
desc: Regular write request latency - 99th percentile
Max:
metric: max
desc: Maximum regular write request latency

# Client request count
- beans:
- org.apache.cassandra.metrics:type=ClientRequest,scope=RangeSlice,name=Latency
- org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency
- org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Latency
metricAttribute:
operation: param(scope)
mapping:
Count:
metric: cassandra.client.request.count
type: counter
unit: "1"
desc: Number of requests by operation

# Client error count
- beans:
- org.apache.cassandra.metrics:type=ClientRequest,scope=RangeSlice,name=Unavailables
- org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Unavailables
- org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Unavailables
metricAttribute:
operation: param(scope)
status: const(Unavailable)
mapping:
Count:
metric: cassandra.client.request.error.count
type: counter
unit: "1"
desc: Number of request errors by operation

- beans:
- org.apache.cassandra.metrics:type=ClientRequest,scope=RangeSlice,name=Timeouts
- org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Timeouts
- org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Timeouts
metricAttribute:
operation: param(scope)
status: const(Timeout)
mapping:
Count:
metric: cassandra.client.request.error.count
type: counter
unit: "1"
desc: Number of request errors by operation

- beans:
- org.apache.cassandra.metrics:type=ClientRequest,scope=RangeSlice,name=Failures
- org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Failures
- org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Failures
metricAttribute:
operation: param(scope)
status: const(Failure)
mapping:
Count:
metric: cassandra.client.request.error.count
type: counter
unit: "1"
desc: Number of request errors by operation
Loading