Skip to content

Commit

Permalink
Update cassandra jmx metrics script to combine similar metrics into l…
Browse files Browse the repository at this point in the history
…abelled metric (#118)

* Update cassandra script to combine similar metrics into labelled metric

* Appease spotless

* Rename status All to Ok

* Update abstract integration data point asserts

* Address PR feedback

* Update cassandra metrics documentation
  • Loading branch information
dehaansa committed Oct 25, 2021
1 parent f5a170c commit 2ebfe99
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 158 deletions.
45 changes: 6 additions & 39 deletions jmx-metrics/docs/target-systems/cassandra.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,11 @@ These metrics are sourced from Cassandra's exposed Dropwizard Metrics for each n
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.range_slice.latency.count`
* Description: Number of token range read request operations
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.range_slice.latency.max`
* Description: Maximum token range read request latency
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.range_slice.timeout.count`
* Description: Number of token range read request timeouts encountered
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.range_slice.unavailable.count`
* Description: Number of token range read request unavailable exceptions encountered
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.read.latency.50p`
* Description: Standard read request latency - 50th percentile
* Unit: `µs`
Expand All @@ -47,26 +32,11 @@ These metrics are sourced from Cassandra's exposed Dropwizard Metrics for each n
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.read.latency.count`
* Description: Number of standard read request operations
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.read.latency.max`
* Description: Maximum standard read request latency
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.read.timeout.count`
* Description: Number of standard read request timeouts encountered
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.read.unavailable.count`
* Description: Number of standard read request unavailable exceptions encountered
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.write.latency.50p`
* Description: Regular write request latency - 50th percentile
* Unit: `µs`
Expand All @@ -77,23 +47,20 @@ These metrics are sourced from Cassandra's exposed Dropwizard Metrics for each n
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.write.latency.count`
* Description: Number of regular write request operations
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.write.latency.max`
* Description: Maximum regular write request latency
* Unit: `µs`
* Instrument Type: DoubleValueObserver

* Name: `cassandra.client.request.write.timeout.count`
* Description: Number of regular write request timeouts encountered
* Name: `cassandra.client.request.count`
* Description: Number of requests by operation
* Labels: `operation`
* Unit: `1`
* Instrument Type: LongSumObserver

* Name: `cassandra.client.request.write.unavailable.count`
* Description: Number of regular write request unavailable exceptions encountered
* Name: `cassandra.client.request.error.count`
* Description: Number of request errors by operation
* Labels: `operation`, `status`
* Unit: `1`
* Instrument Type: LongSumObserver

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse;
import io.opentelemetry.proto.collector.metrics.v1.MetricsServiceGrpc;
import io.opentelemetry.proto.common.v1.KeyValue;
import io.opentelemetry.proto.metrics.v1.Metric;
import io.opentelemetry.proto.metrics.v1.NumberDataPoint;
import io.opentelemetry.proto.metrics.v1.ResourceMetrics;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.function.Consumer;
Expand Down Expand Up @@ -179,30 +182,59 @@ protected void assertTypedSum(
assertTypedPoints(metric.getSum().getDataPointsList(), types);
}

protected void assertSumWithAttributes(
Metric metric,
String name,
String description,
String unit,
List<Map<String, String>> attributeGroups) {
assertThat(metric.getName()).isEqualTo(name);
assertThat(metric.getDescription()).isEqualTo(description);
assertThat(metric.getUnit()).isEqualTo(unit);
assertThat(metric.hasSum()).isTrue();
assertAttributedPoints(metric.getSum().getDataPointsList(), attributeGroups);
}

private static final String expectedMeterVersion() {
// Automatically set by gradle when running the tests
String version = System.getProperty("gradle.project.version");
assert version != null && !version.isEmpty();
return version;
}

@SuppressWarnings("unchecked")
private static void assertTypedPoints(List<NumberDataPoint> points, List<String> types) {
List<Map<String, String>> expectedAttributes =
types.stream()
.map(
type ->
new HashMap<String, String>() {
{
put("name", type);
}
})
.collect(Collectors.toList());

assertAttributedPoints(points, expectedAttributes);
}

@SuppressWarnings("unchecked")
private static void assertAttributedPoints(
List<NumberDataPoint> points, List<Map<String, String>> attributeGroups) {
assertThat(points)
.extracting(
numberDataPoint ->
numberDataPoint.getAttributesList().stream()
.collect(
Collectors.toMap(
KeyValue::getKey, keyValue -> keyValue.getValue().getStringValue())))
.satisfiesExactlyInAnyOrder(
types.stream()
attributeGroups.stream()
.map(
type ->
(Consumer<NumberDataPoint>)
point ->
assertThat(point.getAttributesList())
.singleElement()
.satisfies(
attribute -> {
assertThat(attribute.getKey()).isEqualTo("name");
assertThat(attribute.getValue().getStringValue())
.isEqualTo(type);
}))
expected ->
(Consumer<Map<String, String>>)
pointAttributes ->
assertThat(pointAttributes)
.containsExactlyInAnyOrderEntriesOf(expected))
.toArray(Consumer[]::new));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@

import io.opentelemetry.contrib.jmxmetrics.AbstractIntegrationTest;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
Expand Down Expand Up @@ -48,30 +53,12 @@ void endToEnd() {
"cassandra.client.request.range_slice.latency.99p",
"Token range read request latency - 99th percentile",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.range_slice.latency.count",
"Number of token range read request operations",
"1"),
metric ->
assertGauge(
metric,
"cassandra.client.request.range_slice.latency.max",
"Maximum token range read request latency",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.range_slice.timeout.count",
"Number of token range read request timeouts encountered",
"1"),
metric ->
assertSum(
metric,
"cassandra.client.request.range_slice.unavailable.count",
"Number of token range read request unavailable exceptions encountered",
"1"),
metric ->
assertGauge(
metric,
Expand All @@ -84,30 +71,12 @@ void endToEnd() {
"cassandra.client.request.read.latency.99p",
"Standard read request latency - 99th percentile",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.read.latency.count",
"Number of standard read request operations",
"1"),
metric ->
assertGauge(
metric,
"cassandra.client.request.read.latency.max",
"Maximum standard read request latency",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.read.timeout.count",
"Number of standard read request timeouts encountered",
"1"),
metric ->
assertSum(
metric,
"cassandra.client.request.read.unavailable.count",
"Number of standard read request unavailable exceptions encountered",
"1"),
metric ->
assertGauge(
metric,
Expand All @@ -120,30 +89,12 @@ void endToEnd() {
"cassandra.client.request.write.latency.99p",
"Regular write request latency - 99th percentile",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.write.latency.count",
"Number of regular write request operations",
"1"),
metric ->
assertGauge(
metric,
"cassandra.client.request.write.latency.max",
"Maximum regular write request latency",
"µs"),
metric ->
assertSum(
metric,
"cassandra.client.request.write.timeout.count",
"Number of regular write request timeouts encountered",
"1"),
metric ->
assertSum(
metric,
"cassandra.client.request.write.unavailable.count",
"Number of regular write request unavailable exceptions encountered",
"1"),
metric ->
assertSum(
metric,
Expand Down Expand Up @@ -175,6 +126,53 @@ void endToEnd() {
"cassandra.storage.total_hints.in_progress.count",
"Number of hints attempting to be sent currently",
"1",
false));
false),
metric ->
assertSumWithAttributes(
metric,
"cassandra.client.request.count",
"Number of requests by operation",
"1",
getRequestCountAttributes()),
metric ->
assertSumWithAttributes(
metric,
"cassandra.client.request.error.count",
"Number of request errors by operation",
"1",
getRequestErrorCountAttributes()));
}

private List<Map<String, String>> getRequestCountAttributes() {
List<String> operations = Arrays.asList("RangeSlice", "Read", "Write");

return operations.stream()
.map(
op ->
new HashMap<String, String>() {
{
put("operation", op);
}
})
.collect(Collectors.toList());
}

private List<Map<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 ->
new HashMap<String, String>() {
{
put("operation", op);
put("status", st);
}
}))
.collect(Collectors.toList());
}
}
Loading

0 comments on commit 2ebfe99

Please sign in to comment.