You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by dj...@apache.org on 2020/06/23 17:24:08 UTC
[cassandra] branch trunk updated: Several mbeans are not
unregistered when dropping a keyspace and table
This is an automated email from the ASF dual-hosted git repository.
djoshi pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/trunk by this push:
new 1731e2f Several mbeans are not unregistered when dropping a keyspace and table
1731e2f is described below
commit 1731e2fe84c1da2a6f4b0d1f73b8fd76c88b3acd
Author: Alex <st...@apache.org>
AuthorDate: Mon Apr 15 19:19:05 2019 +0200
Several mbeans are not unregistered when dropping a keyspace and table
Patch By Alex Deparvu; Reviewed by Caleb Rackliffe, Chris Lohfink and Dinesh Joshi for CASSANDRA-14888
---
CHANGES.txt | 1 +
.../apache/cassandra/metrics/KeyspaceMetrics.java | 275 ++++++++-------------
.../org/apache/cassandra/metrics/TableMetrics.java | 193 ++++++++-------
.../cassandra/metrics/KeyspaceMetricsTest.java | 74 ++++++
.../apache/cassandra/metrics/TableMetricsTest.java | 45 +++-
5 files changed, 332 insertions(+), 256 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 1212030..4fa1567 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0-alpha5
+ * Several mbeans are not unregistered when dropping a keyspace and table (CASSANDRA-14888)
* Update defaults for server and client TLS settings (CASSANDRA-15262)
* Differentiate follower/initator in StreamMessageHeader (CASSANDRA-15665)
* Add a startup check to detect if LZ4 uses java rather than native implementation (CASSANDRA-15884)
diff --git a/src/java/org/apache/cassandra/metrics/KeyspaceMetrics.java b/src/java/org/apache/cassandra/metrics/KeyspaceMetrics.java
index 9c45dc0..4af26c0 100644
--- a/src/java/org/apache/cassandra/metrics/KeyspaceMetrics.java
+++ b/src/java/org/apache/cassandra/metrics/KeyspaceMetrics.java
@@ -18,6 +18,7 @@
package org.apache.cassandra.metrics;
import java.util.Set;
+import java.util.function.ToLongFunction;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
@@ -26,8 +27,9 @@ import com.codahale.metrics.Meter;
import com.codahale.metrics.Timer;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.Keyspace;
+import org.apache.cassandra.metrics.CassandraMetricsRegistry.MetricName;
+import org.apache.cassandra.metrics.TableMetrics.ReleasableMetric;
-import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
@@ -155,7 +157,7 @@ public class KeyspaceMetrics
private Keyspace keyspace;
/** set containing names of all the metrics stored here, for releasing later */
- private Set<String> allMetrics = Sets.newHashSet();
+ private Set<ReleasableMetric> allMetrics = Sets.newHashSet();
/**
* Creates metrics for given {@link ColumnFamilyStore}.
@@ -166,137 +168,53 @@ public class KeyspaceMetrics
{
factory = new KeyspaceMetricNameFactory(ks);
keyspace = ks;
- memtableColumnsCount = createKeyspaceGauge("MemtableColumnsCount", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.memtableColumnsCount.getValue();
- }
- });
- memtableLiveDataSize = createKeyspaceGauge("MemtableLiveDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.memtableLiveDataSize.getValue();
- }
- });
- memtableOnHeapDataSize = createKeyspaceGauge("MemtableOnHeapDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.memtableOnHeapSize.getValue();
- }
- });
- memtableOffHeapDataSize = createKeyspaceGauge("MemtableOffHeapDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.memtableOffHeapSize.getValue();
- }
- });
- allMemtablesLiveDataSize = createKeyspaceGauge("AllMemtablesLiveDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.allMemtablesLiveDataSize.getValue();
- }
- });
- allMemtablesOnHeapDataSize = createKeyspaceGauge("AllMemtablesOnHeapDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.allMemtablesOnHeapSize.getValue();
- }
- });
- allMemtablesOffHeapDataSize = createKeyspaceGauge("AllMemtablesOffHeapDataSize", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.allMemtablesOffHeapSize.getValue();
- }
- });
- memtableSwitchCount = createKeyspaceGauge("MemtableSwitchCount", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.memtableSwitchCount.getCount();
- }
- });
- pendingCompactions = createKeyspaceGauge("PendingCompactions", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return (long) metric.pendingCompactions.getValue();
- }
- });
- pendingFlushes = createKeyspaceGauge("PendingFlushes", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return (long) metric.pendingFlushes.getCount();
- }
- });
- liveDiskSpaceUsed = createKeyspaceGauge("LiveDiskSpaceUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.liveDiskSpaceUsed.getCount();
- }
- });
- totalDiskSpaceUsed = createKeyspaceGauge("TotalDiskSpaceUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.totalDiskSpaceUsed.getCount();
- }
- });
- bloomFilterDiskSpaceUsed = createKeyspaceGauge("BloomFilterDiskSpaceUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.bloomFilterDiskSpaceUsed.getValue();
- }
- });
- bloomFilterOffHeapMemoryUsed = createKeyspaceGauge("BloomFilterOffHeapMemoryUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.bloomFilterOffHeapMemoryUsed.getValue();
- }
- });
- indexSummaryOffHeapMemoryUsed = createKeyspaceGauge("IndexSummaryOffHeapMemoryUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.indexSummaryOffHeapMemoryUsed.getValue();
- }
- });
- compressionMetadataOffHeapMemoryUsed = createKeyspaceGauge("CompressionMetadataOffHeapMemoryUsed", new MetricValue()
- {
- public Long getValue(TableMetrics metric)
- {
- return metric.compressionMetadataOffHeapMemoryUsed.getValue();
- }
- });
+ memtableColumnsCount = createKeyspaceGauge("MemtableColumnsCount",
+ metric -> metric.memtableColumnsCount.getValue());
+ memtableLiveDataSize = createKeyspaceGauge("MemtableLiveDataSize",
+ metric -> metric.memtableLiveDataSize.getValue());
+ memtableOnHeapDataSize = createKeyspaceGauge("MemtableOnHeapDataSize",
+ metric -> metric.memtableOnHeapSize.getValue());
+ memtableOffHeapDataSize = createKeyspaceGauge("MemtableOffHeapDataSize",
+ metric -> metric.memtableOffHeapSize.getValue());
+ allMemtablesLiveDataSize = createKeyspaceGauge("AllMemtablesLiveDataSize",
+ metric -> metric.allMemtablesLiveDataSize.getValue());
+ allMemtablesOnHeapDataSize = createKeyspaceGauge("AllMemtablesOnHeapDataSize",
+ metric -> metric.allMemtablesOnHeapSize.getValue());
+ allMemtablesOffHeapDataSize = createKeyspaceGauge("AllMemtablesOffHeapDataSize",
+ metric -> metric.allMemtablesOffHeapSize.getValue());
+ memtableSwitchCount = createKeyspaceGauge("MemtableSwitchCount",
+ metric -> metric.memtableSwitchCount.getCount());
+ pendingCompactions = createKeyspaceGauge("PendingCompactions", metric -> metric.pendingCompactions.getValue());
+ pendingFlushes = createKeyspaceGauge("PendingFlushes", metric -> metric.pendingFlushes.getCount());
+ liveDiskSpaceUsed = createKeyspaceGauge("LiveDiskSpaceUsed", metric -> metric.liveDiskSpaceUsed.getCount());
+ totalDiskSpaceUsed = createKeyspaceGauge("TotalDiskSpaceUsed", metric -> metric.totalDiskSpaceUsed.getCount());
+ bloomFilterDiskSpaceUsed = createKeyspaceGauge("BloomFilterDiskSpaceUsed",
+ metric -> metric.bloomFilterDiskSpaceUsed.getValue());
+ bloomFilterOffHeapMemoryUsed = createKeyspaceGauge("BloomFilterOffHeapMemoryUsed",
+ metric -> metric.bloomFilterOffHeapMemoryUsed.getValue());
+ indexSummaryOffHeapMemoryUsed = createKeyspaceGauge("IndexSummaryOffHeapMemoryUsed",
+ metric -> metric.indexSummaryOffHeapMemoryUsed.getValue());
+ compressionMetadataOffHeapMemoryUsed = createKeyspaceGauge("CompressionMetadataOffHeapMemoryUsed",
+ metric -> metric.compressionMetadataOffHeapMemoryUsed.getValue());
+
// latency metrics for TableMetrics to update
- readLatency = new LatencyMetrics(factory, "Read");
- writeLatency = new LatencyMetrics(factory, "Write");
- rangeLatency = new LatencyMetrics(factory, "Range");
+ readLatency = createLatencyMetrics("Read");
+ writeLatency = createLatencyMetrics("Write");
+ rangeLatency = createLatencyMetrics("Range");
+
// create histograms for TableMetrics to replicate updates to
- sstablesPerReadHistogram = Metrics.histogram(factory.createMetricName("SSTablesPerReadHistogram"), true);
- tombstoneScannedHistogram = Metrics.histogram(factory.createMetricName("TombstoneScannedHistogram"), false);
- liveScannedHistogram = Metrics.histogram(factory.createMetricName("LiveScannedHistogram"), false);
- colUpdateTimeDeltaHistogram = Metrics.histogram(factory.createMetricName("ColUpdateTimeDeltaHistogram"), false);
- viewLockAcquireTime = Metrics.timer(factory.createMetricName("ViewLockAcquireTime"));
- viewReadTime = Metrics.timer(factory.createMetricName("ViewReadTime"));
- // add manually since histograms do not use createKeyspaceGauge method
- allMetrics.addAll(Lists.newArrayList("SSTablesPerReadHistogram", "TombstoneScannedHistogram", "LiveScannedHistogram"));
+ sstablesPerReadHistogram = createKeyspaceHistogram("SSTablesPerReadHistogram", true);
+ tombstoneScannedHistogram = createKeyspaceHistogram("TombstoneScannedHistogram", false);
+ liveScannedHistogram = createKeyspaceHistogram("LiveScannedHistogram", false);
+ colUpdateTimeDeltaHistogram = createKeyspaceHistogram("ColUpdateTimeDeltaHistogram", false);
+ viewLockAcquireTime = createKeyspaceTimer("ViewLockAcquireTime");
+ viewReadTime = createKeyspaceTimer("ViewReadTime");
- casPrepare = new LatencyMetrics(factory, "CasPrepare");
- casPropose = new LatencyMetrics(factory, "CasPropose");
- casCommit = new LatencyMetrics(factory, "CasCommit");
- writeFailedIdealCL = Metrics.counter(factory.createMetricName("WriteFailedIdealCL"));
- idealCLWriteLatency = new LatencyMetrics(factory, "IdealCLWrite");
+ casPrepare = createLatencyMetrics("CasPrepare");
+ casPropose = createLatencyMetrics("CasPropose");
+ casCommit = createLatencyMetrics("CasCommit");
+ writeFailedIdealCL = createKeyspaceCounter("WriteFailedIdealCL");
+ idealCLWriteLatency = createLatencyMetrics("IdealCLWrite");
speculativeRetries = createKeyspaceCounter("SpeculativeRetries", metric -> metric.speculativeRetries.getCount());
speculativeFailedRetries = createKeyspaceCounter("SpeculativeFailedRetries", metric -> metric.speculativeFailedRetries.getCount());
@@ -304,19 +222,19 @@ public class KeyspaceMetrics
additionalWrites = createKeyspaceCounter("AdditionalWrites", metric -> metric.additionalWrites.getCount());
repairsStarted = createKeyspaceCounter("RepairJobsStarted", metric -> metric.repairsStarted.getCount());
repairsCompleted = createKeyspaceCounter("RepairJobsCompleted", metric -> metric.repairsCompleted.getCount());
- repairTime = Metrics.timer(factory.createMetricName("RepairTime"));
- repairPrepareTime = Metrics.timer(factory.createMetricName("RepairPrepareTime"));
- anticompactionTime = Metrics.timer(factory.createMetricName("AntiCompactionTime"));
- validationTime = Metrics.timer(factory.createMetricName("ValidationTime"));
- repairSyncTime = Metrics.timer(factory.createMetricName("RepairSyncTime"));
- partitionsValidated = Metrics.histogram(factory.createMetricName("PartitionsValidated"), false);
- bytesValidated = Metrics.histogram(factory.createMetricName("BytesValidated"), false);
+ repairTime =createKeyspaceTimer("RepairTime");
+ repairPrepareTime = createKeyspaceTimer("RepairPrepareTime");
+ anticompactionTime = createKeyspaceTimer("AntiCompactionTime");
+ validationTime = createKeyspaceTimer("ValidationTime");
+ repairSyncTime = createKeyspaceTimer("RepairSyncTime");
+ partitionsValidated = createKeyspaceHistogram("PartitionsValidated", false);
+ bytesValidated = createKeyspaceHistogram("BytesValidated", false);
- confirmedRepairedInconsistencies = Metrics.meter(factory.createMetricName("RepairedDataInconsistenciesConfirmed"));
- unconfirmedRepairedInconsistencies = Metrics.meter(factory.createMetricName("RepairedDataInconsistenciesUnconfirmed"));
+ confirmedRepairedInconsistencies = createKeyspaceMeter("RepairedDataInconsistenciesConfirmed");
+ unconfirmedRepairedInconsistencies = createKeyspaceMeter("RepairedDataInconsistenciesUnconfirmed");
- repairedDataTrackingOverreadRows = Metrics.histogram(factory.createMetricName("RepairedOverreadRows"), false);
- repairedDataTrackingOverreadTime = Metrics.timer(factory.createMetricName("RepairedOverreadTime"));
+ repairedDataTrackingOverreadRows = createKeyspaceHistogram("RepairedOverreadRows", false);
+ repairedDataTrackingOverreadTime = createKeyspaceTimer("RepairedOverreadTime");
}
/**
@@ -324,28 +242,10 @@ public class KeyspaceMetrics
*/
public void release()
{
- for(String name : allMetrics)
+ for (ReleasableMetric metric : allMetrics)
{
- Metrics.remove(factory.createMetricName(name));
+ metric.release();
}
- // latency metrics contain multiple metrics internally and need to be released manually
- readLatency.release();
- writeLatency.release();
- rangeLatency.release();
- idealCLWriteLatency.release();
- }
-
- /**
- * Represents a column family metric value.
- */
- private interface MetricValue
- {
- /**
- * get value of a metric
- * @param metric of a column family in this keyspace
- * @return current value of a metric
- */
- public Long getValue(TableMetrics metric);
}
/**
@@ -354,9 +254,9 @@ public class KeyspaceMetrics
* @param extractor
* @return Gauge>Long> that computes sum of MetricValue.getValue()
*/
- private Gauge<Long> createKeyspaceGauge(String name, final MetricValue extractor)
+ private Gauge<Long> createKeyspaceGauge(String name, final ToLongFunction<TableMetrics> extractor)
{
- allMetrics.add(name);
+ allMetrics.add(() -> releaseMetric(name));
return Metrics.register(factory.createMetricName(name), new Gauge<Long>()
{
public Long getValue()
@@ -364,7 +264,7 @@ public class KeyspaceMetrics
long sum = 0;
for (ColumnFamilyStore cf : keyspace.getColumnFamilyStores())
{
- sum += extractor.getValue(cf.metric);
+ sum += extractor.applyAsLong(cf.metric);
}
return sum;
}
@@ -377,9 +277,9 @@ public class KeyspaceMetrics
* @param extractor
* @return Counter that computes sum of MetricValue.getValue()
*/
- private Counter createKeyspaceCounter(String name, final MetricValue extractor)
+ private Counter createKeyspaceCounter(String name, final ToLongFunction<TableMetrics> extractor)
{
- allMetrics.add(name);
+ allMetrics.add(() -> releaseMetric(name));
return Metrics.register(factory.createMetricName(name), new Counter()
{
@Override
@@ -388,13 +288,49 @@ public class KeyspaceMetrics
long sum = 0;
for (ColumnFamilyStore cf : keyspace.getColumnFamilyStores())
{
- sum += extractor.getValue(cf.metric);
+ sum += extractor.applyAsLong(cf.metric);
}
return sum;
}
});
}
+ protected Counter createKeyspaceCounter(String name)
+ {
+ allMetrics.add(() -> releaseMetric(name));
+ return Metrics.counter(factory.createMetricName(name));
+ }
+
+ protected Histogram createKeyspaceHistogram(String name, boolean considerZeroes)
+ {
+ allMetrics.add(() -> releaseMetric(name));
+ return Metrics.histogram(factory.createMetricName(name), considerZeroes);
+ }
+
+ protected Timer createKeyspaceTimer(String name)
+ {
+ allMetrics.add(() -> releaseMetric(name));
+ return Metrics.timer(factory.createMetricName(name));
+ }
+
+ protected Meter createKeyspaceMeter(String name)
+ {
+ allMetrics.add(() -> releaseMetric(name));
+ return Metrics.meter(factory.createMetricName(name));
+ }
+
+ private LatencyMetrics createLatencyMetrics(String name)
+ {
+ LatencyMetrics metric = new LatencyMetrics(factory, name);
+ allMetrics.add(() -> metric.release());
+ return metric;
+ }
+
+ private void releaseMetric(String name)
+ {
+ Metrics.remove(factory.createMetricName(name));
+ }
+
static class KeyspaceMetricNameFactory implements MetricNameFactory
{
private final String keyspaceName;
@@ -404,7 +340,8 @@ public class KeyspaceMetrics
this.keyspaceName = ks.getName();
}
- public CassandraMetricsRegistry.MetricName createMetricName(String metricName)
+ @Override
+ public MetricName createMetricName(String metricName)
{
String groupName = TableMetrics.class.getPackage().getName();
@@ -414,7 +351,7 @@ public class KeyspaceMetrics
mbeanName.append(",keyspace=").append(keyspaceName);
mbeanName.append(",name=").append(metricName);
- return new CassandraMetricsRegistry.MetricName(groupName, "keyspace", metricName, keyspaceName, mbeanName.toString());
+ return new MetricName(groupName, "keyspace", metricName, keyspaceName, mbeanName.toString());
}
}
}
diff --git a/src/java/org/apache/cassandra/metrics/TableMetrics.java b/src/java/org/apache/cassandra/metrics/TableMetrics.java
index 449b6c0..bfb261d 100644
--- a/src/java/org/apache/cassandra/metrics/TableMetrics.java
+++ b/src/java/org/apache/cassandra/metrics/TableMetrics.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.EnumMap;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -33,7 +32,7 @@ import java.util.function.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
-
+import com.google.common.collect.Sets;
import com.codahale.metrics.Timer;
import org.apache.cassandra.db.ColumnFamilyStore;
@@ -338,9 +337,9 @@ public class TableMetrics
public final static ConcurrentMap<String, Set<Metric>> allTableMetrics = Maps.newConcurrentMap();
/**
- * Stores all metric names created that can be used when unregistering, optionally mapped to an alias name.
+ * Stores all metrics created that can be used when unregistering
*/
- public final static Map<String, String> all = Maps.newHashMap();
+ public final static Set<ReleasableMetric> all = Sets.newHashSet();
private interface GetHistogram
{
@@ -494,52 +493,45 @@ public class TableMetrics
}
});
memtableSwitchCount = createTableCounter("MemtableSwitchCount");
- estimatedPartitionSizeHistogram = Metrics.register(factory.createMetricName("EstimatedPartitionSizeHistogram"),
- aliasFactory.createMetricName("EstimatedRowSizeHistogram"),
- new Gauge<long[]>()
- {
- public long[] getValue()
- {
- return combineHistograms(cfs.getSSTables(SSTableSet.CANONICAL), new GetHistogram()
- {
- public EstimatedHistogram getHistogram(SSTableReader reader)
- {
- return reader.getEstimatedPartitionSize();
- }
- });
- }
- });
- estimatedPartitionCount = Metrics.register(factory.createMetricName("EstimatedPartitionCount"),
- aliasFactory.createMetricName("EstimatedRowCount"),
- new Gauge<Long>()
- {
- public Long getValue()
- {
- long memtablePartitions = 0;
- for (Memtable memtable : cfs.getTracker().getView().getAllMemtables())
- memtablePartitions += memtable.partitionCount();
- try(ColumnFamilyStore.RefViewFragment refViewFragment = cfs.selectAndReference(View.selectFunction(SSTableSet.CANONICAL)))
- {
- return SSTableReader.getApproximateKeyCount(refViewFragment.sstables) + memtablePartitions;
- }
-
- }
- });
- estimatedColumnCountHistogram = Metrics.register(factory.createMetricName("EstimatedColumnCountHistogram"),
- aliasFactory.createMetricName("EstimatedColumnCountHistogram"),
- new Gauge<long[]>()
- {
- public long[] getValue()
- {
- return combineHistograms(cfs.getSSTables(SSTableSet.CANONICAL), new GetHistogram()
- {
- public EstimatedHistogram getHistogram(SSTableReader reader)
- {
- return reader.getEstimatedCellPerPartitionCount();
- }
- });
+ estimatedPartitionSizeHistogram = createTableGauge("EstimatedPartitionSizeHistogram", "EstimatedRowSizeHistogram", new Gauge<long[]>()
+ {
+ public long[] getValue()
+ {
+ return combineHistograms(cfs.getSSTables(SSTableSet.CANONICAL), new GetHistogram()
+ {
+ public EstimatedHistogram getHistogram(SSTableReader reader)
+ {
+ return reader.getEstimatedPartitionSize();
+ }
+ });
}
- });
+ }, null);
+ estimatedPartitionCount = createTableGauge("EstimatedPartitionCount", "EstimatedRowCount", new Gauge<Long>()
+ {
+ public Long getValue()
+ {
+ long memtablePartitions = 0;
+ for (Memtable memtable : cfs.getTracker().getView().getAllMemtables())
+ memtablePartitions += memtable.partitionCount();
+ try(ColumnFamilyStore.RefViewFragment refViewFragment = cfs.selectAndReference(View.selectFunction(SSTableSet.CANONICAL)))
+ {
+ return SSTableReader.getApproximateKeyCount(refViewFragment.sstables) + memtablePartitions;
+ }
+ }
+ }, null);
+ estimatedColumnCountHistogram = createTableGauge("EstimatedColumnCountHistogram", "EstimatedColumnCountHistogram", new Gauge<long[]>()
+ {
+ public long[] getValue()
+ {
+ return combineHistograms(cfs.getSSTables(SSTableSet.CANONICAL), new GetHistogram()
+ {
+ public EstimatedHistogram getHistogram(SSTableReader reader)
+ {
+ return reader.getEstimatedCellPerPartitionCount();
+ }
+ });
+ }
+ }, null);
sstablesPerReadHistogram = createTableHistogram("SSTablesPerReadHistogram", cfs.keyspace.metric.sstablesPerReadHistogram, true);
compressionRatio = createTableGauge("CompressionRatio", new Gauge<Double>()
{
@@ -613,9 +605,9 @@ public class TableMetrics
}
});
- readLatency = new LatencyMetrics(factory, "Read", cfs.keyspace.metric.readLatency, globalReadLatency);
- writeLatency = new LatencyMetrics(factory, "Write", cfs.keyspace.metric.writeLatency, globalWriteLatency);
- rangeLatency = new LatencyMetrics(factory, "Range", cfs.keyspace.metric.rangeLatency, globalRangeLatency);
+ readLatency = createLatencyMetrics("Read", cfs.keyspace.metric.readLatency, globalReadLatency);
+ writeLatency = createLatencyMetrics("Write", cfs.keyspace.metric.writeLatency, globalWriteLatency);
+ rangeLatency = createLatencyMetrics("Range", cfs.keyspace.metric.rangeLatency, globalRangeLatency);
pendingFlushes = createTableCounter("PendingFlushes");
bytesFlushed = createTableCounter("BytesFlushed");
@@ -863,9 +855,7 @@ public class TableMetrics
additionalWrites = createTableCounter("AdditionalWrites");
additionalWriteLatencyNanos = createTableGauge("AdditionalWriteLatencyNanos", () -> cfs.additionalWriteLatencyNanos);
- keyCacheHitRate = Metrics.register(factory.createMetricName("KeyCacheHitRate"),
- aliasFactory.createMetricName("KeyCacheHitRate"),
- new RatioGauge()
+ keyCacheHitRate = createTableGauge("KeyCacheHitRate", "KeyCacheHitRate", new RatioGauge()
{
@Override
public Ratio getRatio()
@@ -888,14 +878,14 @@ public class TableMetrics
requests += sstable.getKeyCacheRequest();
return Math.max(requests, 1); // to avoid NaN.
}
- });
+ }, null);
tombstoneScannedHistogram = createTableHistogram("TombstoneScannedHistogram", cfs.keyspace.metric.tombstoneScannedHistogram, false);
liveScannedHistogram = createTableHistogram("LiveScannedHistogram", cfs.keyspace.metric.liveScannedHistogram, false);
colUpdateTimeDeltaHistogram = createTableHistogram("ColUpdateTimeDeltaHistogram", cfs.keyspace.metric.colUpdateTimeDeltaHistogram, false);
- coordinatorReadLatency = Metrics.timer(factory.createMetricName("CoordinatorReadLatency"));
- coordinatorScanLatency = Metrics.timer(factory.createMetricName("CoordinatorScanLatency"));
- coordinatorWriteLatency = Metrics.timer(factory.createMetricName("CoordinatorWriteLatency"));
- waitingOnFreeMemtableSpace = Metrics.histogram(factory.createMetricName("WaitingOnFreeMemtableSpace"), false);
+ coordinatorReadLatency = createTableTimer("CoordinatorReadLatency");
+ coordinatorScanLatency = createTableTimer("CoordinatorScanLatency");
+ coordinatorWriteLatency = createTableTimer("CoordinatorWriteLatency");
+ waitingOnFreeMemtableSpace = createTableHistogram("WaitingOnFreeMemtableSpace", false);
// We do not want to capture view mutation specific metrics for a view
// They only makes sense to capture on the base table
@@ -926,9 +916,9 @@ public class TableMetrics
droppedMutations = createTableCounter("DroppedMutations");
- casPrepare = new LatencyMetrics(factory, "CasPrepare", cfs.keyspace.metric.casPrepare);
- casPropose = new LatencyMetrics(factory, "CasPropose", cfs.keyspace.metric.casPropose);
- casCommit = new LatencyMetrics(factory, "CasCommit", cfs.keyspace.metric.casCommit);
+ casPrepare = createLatencyMetrics("CasPrepare", cfs.keyspace.metric.casPrepare);
+ casPropose = createLatencyMetrics("CasPropose", cfs.keyspace.metric.casPropose);
+ casCommit = createLatencyMetrics("CasCommit", cfs.keyspace.metric.casCommit);
repairsStarted = createTableCounter("RepairJobsStarted");
repairsCompleted = createTableCounter("RepairJobsCompleted");
@@ -981,28 +971,10 @@ public class TableMetrics
*/
public void release()
{
- for(Map.Entry<String, String> entry : all.entrySet())
- {
- CassandraMetricsRegistry.MetricName name = factory.createMetricName(entry.getKey());
- CassandraMetricsRegistry.MetricName alias = aliasFactory.createMetricName(entry.getValue());
- final Metric metric = Metrics.getMetrics().get(name.getMetricName());
- if (metric != null)
- { // Metric will be null if it's a view metric we are releasing. Views have null for ViewLockAcquireTime and ViewLockReadTime
- allTableMetrics.get(entry.getKey()).remove(metric);
- Metrics.remove(name, alias);
- }
+ for (ReleasableMetric entry : all)
+ {
+ entry.release();
}
- readLatency.release();
- writeLatency.release();
- rangeLatency.release();
- Metrics.remove(factory.createMetricName("EstimatedPartitionSizeHistogram"), aliasFactory.createMetricName("EstimatedRowSizeHistogram"));
- Metrics.remove(factory.createMetricName("EstimatedPartitionCount"), aliasFactory.createMetricName("EstimatedRowCount"));
- Metrics.remove(factory.createMetricName("EstimatedColumnCountHistogram"), aliasFactory.createMetricName("EstimatedColumnCountHistogram"));
- Metrics.remove(factory.createMetricName("KeyCacheHitRate"), aliasFactory.createMetricName("KeyCacheHitRate"));
- Metrics.remove(factory.createMetricName("CoordinatorReadLatency"), aliasFactory.createMetricName("CoordinatorReadLatency"));
- Metrics.remove(factory.createMetricName("CoordinatorScanLatency"), aliasFactory.createMetricName("CoordinatorScanLatency"));
- Metrics.remove(factory.createMetricName("CoordinatorWriteLatency"), aliasFactory.createMetricName("CoordinatorWriteLatency"));
- Metrics.remove(factory.createMetricName("WaitingOnFreeMemtableSpace"), aliasFactory.createMetricName("WaitingOnFreeMemtableSpace"));
}
@@ -1038,7 +1010,7 @@ public class TableMetrics
protected <G,T> Gauge<T> createTableGauge(String name, String alias, Gauge<T> gauge, Gauge<G> globalGauge)
{
Gauge<T> cfGauge = Metrics.register(factory.createMetricName(name), aliasFactory.createMetricName(alias), gauge);
- if (register(name, alias, cfGauge))
+ if (register(name, alias, cfGauge) && globalGauge != null)
{
Metrics.register(globalFactory.createMetricName(name), globalAliasFactory.createMetricName(alias), globalGauge);
}
@@ -1135,6 +1107,18 @@ public class TableMetrics
considerZeroes));
}
+ protected Histogram createTableHistogram(String name, boolean considerZeroes)
+ {
+ return createTableHistogram(name, name, considerZeroes);
+ }
+
+ protected Histogram createTableHistogram(String name, String alias, boolean considerZeroes)
+ {
+ Histogram tableHistogram = Metrics.histogram(factory.createMetricName(name), aliasFactory.createMetricName(alias), considerZeroes);
+ register(name, alias, tableHistogram);
+ return tableHistogram;
+ }
+
protected TableTimer createTableTimer(String name, Timer keyspaceTimer)
{
return createTableTimer(name, name, keyspaceTimer);
@@ -1150,6 +1134,18 @@ public class TableMetrics
globalAliasFactory.createMetricName(alias)));
}
+ protected Timer createTableTimer(String name)
+ {
+ return createTableTimer(name, name);
+ }
+
+ protected Timer createTableTimer(String name, String alias)
+ {
+ Timer tableTimer = Metrics.timer(factory.createMetricName(name), aliasFactory.createMetricName(alias));
+ register(name, alias, tableTimer);
+ return tableTimer;
+ }
+
protected TableMeter createTableMeter(String name, Meter keyspaceMeter)
{
return createTableMeter(name, name, keyspaceMeter);
@@ -1165,6 +1161,13 @@ public class TableMetrics
globalAliasFactory.createMetricName(alias)));
}
+ private LatencyMetrics createLatencyMetrics(String namePrefix, LatencyMetrics ... parents)
+ {
+ LatencyMetrics metric = new LatencyMetrics(factory, namePrefix, parents);
+ all.add(() -> metric.release());
+ return metric;
+ }
+
/**
* Registers a metric to be removed when unloading CF.
* @return true if first time metric with that name has been registered
@@ -1173,10 +1176,22 @@ public class TableMetrics
{
boolean ret = allTableMetrics.putIfAbsent(name, ConcurrentHashMap.newKeySet()) == null;
allTableMetrics.get(name).add(metric);
- all.put(name, alias);
+ all.add(() -> releaseMetric(name, alias));
return ret;
}
+ private void releaseMetric(String metricName, String metricAlias)
+ {
+ CassandraMetricsRegistry.MetricName name = factory.createMetricName(metricName);
+ CassandraMetricsRegistry.MetricName alias = aliasFactory.createMetricName(metricAlias);
+ final Metric metric = Metrics.getMetrics().get(name.getMetricName());
+ if (metric != null)
+ { // Metric will be null if we are releasing a view metric. Views have null for ViewLockAcquireTime and ViewLockReadTime
+ allTableMetrics.get(metricName).remove(metric);
+ Metrics.remove(name, alias);
+ }
+ }
+
public static class TableMeter
{
public final Meter[] all;
@@ -1307,4 +1322,10 @@ public class TableMetrics
return new CassandraMetricsRegistry.MetricName(groupName, type, metricName, "all", mbeanName.toString());
}
}
+
+ @FunctionalInterface
+ public interface ReleasableMetric
+ {
+ void release();
+ }
}
diff --git a/test/unit/org/apache/cassandra/metrics/KeyspaceMetricsTest.java b/test/unit/org/apache/cassandra/metrics/KeyspaceMetricsTest.java
new file mode 100644
index 0000000..ae92146
--- /dev/null
+++ b/test/unit/org/apache/cassandra/metrics/KeyspaceMetricsTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.metrics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.schema.Schema;
+import org.apache.cassandra.service.EmbeddedCassandraService;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+
+public class KeyspaceMetricsTest extends SchemaLoader
+{
+ private static Session session;
+
+ @BeforeClass()
+ public static void setup() throws ConfigurationException, IOException
+ {
+ Schema.instance.clear();
+
+ EmbeddedCassandraService cassandra = new EmbeddedCassandraService();
+ cassandra.start();
+
+ Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").withPort(DatabaseDescriptor.getNativeTransportPort()).build();
+ session = cluster.connect();
+ }
+
+ @Test
+ public void testMetricsCleanupOnDrop()
+ {
+ String keyspace = "keyspacemetricstest_metrics_cleanup";
+ CassandraMetricsRegistry registry = CassandraMetricsRegistry.Metrics;
+ Supplier<Stream<String>> metrics = () -> registry.getNames().stream().filter(m -> m.contains(keyspace));
+
+ // no metrics before creating
+ assertEquals(0, metrics.get().count());
+
+ session.execute(String.format("CREATE KEYSPACE %s WITH replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };", keyspace));
+ // some metrics
+ assertTrue(metrics.get().count() > 0);
+
+ session.execute(String.format("DROP KEYSPACE %s;", keyspace));
+ // no metrics after drop
+ assertEquals(metrics.get().collect(Collectors.joining(",")), 0, metrics.get().count());
+ }
+}
diff --git a/test/unit/org/apache/cassandra/metrics/TableMetricsTest.java b/test/unit/org/apache/cassandra/metrics/TableMetricsTest.java
index c5434fe..56ad401 100644
--- a/test/unit/org/apache/cassandra/metrics/TableMetricsTest.java
+++ b/test/unit/org/apache/cassandra/metrics/TableMetricsTest.java
@@ -19,6 +19,9 @@
package org.apache.cassandra.metrics;
import java.io.IOException;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -235,4 +238,44 @@ public class TableMetricsTest extends SchemaLoader
private static void assertGreaterThan(double actual, double expectedLessThan) {
assertTrue("Expected " + actual + " > " + expectedLessThan, actual > expectedLessThan);
}
-}
\ No newline at end of file
+
+ @Test
+ public void testMetricsCleanupOnDrop()
+ {
+ String tableName = TABLE + "_metrics_cleanup";
+ CassandraMetricsRegistry registry = CassandraMetricsRegistry.Metrics;
+ Supplier<Stream<String>> metrics = () -> registry.getNames().stream().filter(m -> m.contains(tableName));
+
+ // no metrics before creating
+ assertEquals(0, metrics.get().count());
+
+ recreateTable(tableName);
+ // some metrics
+ assertTrue(metrics.get().count() > 0);
+
+ session.execute(String.format("DROP TABLE IF EXISTS %s.%s", KEYSPACE, tableName));
+ // no metrics after drop
+ assertEquals(metrics.get().collect(Collectors.joining(",")), 0, metrics.get().count());
+ }
+
+ @Test
+ public void testViewMetricsCleanupOnDrop()
+ {
+ String tableName = TABLE + "_metrics_cleanup";
+ String viewName = TABLE + "_materialized_view_cleanup";
+ CassandraMetricsRegistry registry = CassandraMetricsRegistry.Metrics;
+ Supplier<Stream<String>> metrics = () -> registry.getNames().stream().filter(m -> m.contains(viewName));
+
+ // no metrics before creating
+ assertEquals(0, metrics.get().count());
+
+ recreateTable(tableName);
+ session.execute(String.format("CREATE MATERIALIZED VIEW %s.%s AS SELECT id,val1 FROM %s.%s WHERE id IS NOT NULL AND val1 IS NOT NULL PRIMARY KEY (id,val1);", KEYSPACE, viewName, KEYSPACE, tableName));
+ // some metrics
+ assertTrue(metrics.get().count() > 0);
+
+ session.execute(String.format("DROP MATERIALIZED VIEW IF EXISTS %s.%s;", KEYSPACE, viewName));
+ // no metrics after drop
+ assertEquals(metrics.get().collect(Collectors.joining(",")), 0, metrics.get().count());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org