diff --git a/build.xml b/build.xml index d8d4bb764b..f72f54f2b0 100644 --- a/build.xml +++ b/build.xml @@ -592,7 +592,7 @@ - + diff --git a/test/distributed/org/apache/cassandra/distributed/impl/AbstractCluster.java b/test/distributed/org/apache/cassandra/distributed/impl/AbstractCluster.java index 1ae594fbe6..0eea077950 100644 --- a/test/distributed/org/apache/cassandra/distributed/impl/AbstractCluster.java +++ b/test/distributed/org/apache/cassandra/distributed/impl/AbstractCluster.java @@ -67,6 +67,7 @@ import org.apache.cassandra.distributed.api.NodeToolResult; import org.apache.cassandra.distributed.api.TokenSupplier; import org.apache.cassandra.distributed.shared.InstanceClassLoader; import org.apache.cassandra.distributed.shared.MessageFilters; +import org.apache.cassandra.distributed.shared.Metrics; import org.apache.cassandra.distributed.shared.NetworkTopology; import org.apache.cassandra.distributed.shared.Shared; import org.apache.cassandra.distributed.shared.ShutdownException; @@ -256,6 +257,14 @@ public abstract class AbstractCluster implements ICluster new InstanceMetrics(CassandraMetricsRegistry.Metrics)); + } + public NodeToolResult nodetoolResult(boolean withNotifications, String... commandAndArgs) { return sync(() -> { diff --git a/test/distributed/org/apache/cassandra/distributed/impl/InstanceMetrics.java b/test/distributed/org/apache/cassandra/distributed/impl/InstanceMetrics.java new file mode 100644 index 0000000000..3bd58940fe --- /dev/null +++ b/test/distributed/org/apache/cassandra/distributed/impl/InstanceMetrics.java @@ -0,0 +1,183 @@ +/* + * 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. + */ + +package org.apache.cassandra.distributed.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Meter; +import com.codahale.metrics.Snapshot; +import com.codahale.metrics.Timer; +import org.apache.cassandra.distributed.shared.Metrics; +import org.apache.cassandra.metrics.CassandraMetricsRegistry; + +/** + * Pulls metrics out of in-JVM dtest cluster instance. + */ +class InstanceMetrics implements Metrics +{ + private final CassandraMetricsRegistry metricsRegistry; + + InstanceMetrics(CassandraMetricsRegistry metricsRegistry) + { + this.metricsRegistry = metricsRegistry; + } + + public List getNames() + { + return new ArrayList<>(metricsRegistry.getNames()); + } + + public long getCounter(String name) + { + return metricsRegistry.getCounters().get(name).getCount(); + } + + public Map getCounters(Predicate filter) + { + Map values = new HashMap<>(); + for (Map.Entry e : metricsRegistry.getCounters().entrySet()) + { + if (filter.test(e.getKey())) + values.put(e.getKey(), e.getValue().getCount()); + } + return values; + } + + public double getHistogram(String name, MetricValue value) + { + Histogram histogram = metricsRegistry.getHistograms().get(name); + if (value == MetricValue.COUNT) + return histogram.getCount(); + + return getValue(histogram.getSnapshot(), value); + } + + public Map getHistograms(Predicate filter, MetricValue value) + { + Map values = new HashMap<>(); + for (Map.Entry e : metricsRegistry.getHistograms().entrySet()) + { + if (filter.test(e.getKey())) + values.put(e.getKey(), getValue(e.getValue().getSnapshot(), value)); + } + return values; + } + + public Object getGauge(String name) + { + return metricsRegistry.getGauges().get(name).getValue(); + } + + public Map getGauges(Predicate filter) + { + Map values = new HashMap<>(); + for (Map.Entry e : metricsRegistry.getGauges().entrySet()) + { + if (filter.test(e.getKey())) + values.put(e.getKey(), e.getValue().getValue()); + } + return values; + } + + public double getMeter(String name, Rate value) + { + return getRate(metricsRegistry.getMeters().get(name), value); + } + + public Map getMeters(Predicate filter, Rate rate) + { + Map values = new HashMap<>(); + for (Map.Entry e : metricsRegistry.getMeters().entrySet()) + { + if (filter.test(e.getKey())) + values.put(e.getKey(), getRate(e.getValue(), rate)); + } + return values; + } + + public double getTimer(String name, MetricValue value) + { + return getValue(metricsRegistry.getTimers().get(name).getSnapshot(), value); + } + + public Map getTimers(Predicate filter, MetricValue value) + { + Map values = new HashMap<>(); + for (Map.Entry e : metricsRegistry.getTimers().entrySet()) + { + if (filter.test(e.getKey())) + values.put(e.getKey(), getValue(e.getValue().getSnapshot(), value)); + } + + return values; + } + + static double getValue(Snapshot snapshot, MetricValue value) + { + switch (value) + { + case MEDIAN: + return snapshot.getMedian(); + case P75: + return snapshot.get75thPercentile(); + case P95: + return snapshot.get95thPercentile(); + case P98: + return snapshot.get98thPercentile(); + case P99: + return snapshot.get99thPercentile(); + case P999: + return snapshot.get999thPercentile(); + case MAX: + return snapshot.getMax(); + case MEAN: + return snapshot.getMean(); + case MIN: + return snapshot.getMin(); + case STDDEV: + return snapshot.getStdDev(); + default: + throw new RuntimeException("Shouldn't happen"); + } + } + + static double getRate(Meter meter, Rate rate) + { + switch (rate) + { + case RATE15_MIN: + return meter.getFifteenMinuteRate(); + case RATE5_MIN: + return meter.getFiveMinuteRate(); + case RATE1_MIN: + return meter.getOneMinuteRate(); + case RATE_MEAN: + return meter.getMeanRate(); + default: + throw new RuntimeException("Shouldn't happen"); + } + } +} diff --git a/test/distributed/org/apache/cassandra/distributed/test/MetricsTest.java b/test/distributed/org/apache/cassandra/distributed/test/MetricsTest.java new file mode 100644 index 0000000000..c9e110ad14 --- /dev/null +++ b/test/distributed/org/apache/cassandra/distributed/test/MetricsTest.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.apache.cassandra.distributed.test; + +import com.google.common.collect.ImmutableMap; +import org.junit.Assert; +import org.junit.Test; + +import org.apache.cassandra.distributed.api.ICluster; +import org.apache.cassandra.distributed.api.IInvokableInstance; +import org.apache.cassandra.metrics.CassandraMetricsRegistry; + +public class MetricsTest extends TestBaseImpl +{ + @Test + public void testMetrics() throws Throwable + { + try (ICluster cluster = init(builder().withNodes(1) + .start())) + { + cluster.get(1).runOnInstance(() -> { + CassandraMetricsRegistry.Metrics.counter("test_counter").inc(100); + CassandraMetricsRegistry.Metrics.counter("test_counter_2").inc(101); + }); + + Assert.assertEquals(100, cluster.get(1).metrics().getCounter("test_counter")); + Assert.assertEquals(ImmutableMap.of("test_counter", 100L, + "test_counter_2", 101L), + cluster.get(1).metrics().getCounters(s -> s.startsWith("test_counter"))); + } + } +}