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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]