Repository: cassandra
Updated Branches:
  refs/heads/trunk 5cc280d68 -> 9b47dd50f


Add repaired percentage metric

patch by Chris Lohfink; reviewed by yukim CASSANDRA-11503


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/9b47dd50
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/9b47dd50
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/9b47dd50

Branch: refs/heads/trunk
Commit: 9b47dd50fceb552acd3ca77cff88f4041511bf48
Parents: 5cc280d
Author: Chris Lohfink <chris.lohf...@datastax.com>
Authored: Fri May 20 11:37:26 2016 -0500
Committer: Yuki Morishita <yu...@apache.org>
Committed: Mon May 23 21:15:40 2016 -0500

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/metrics/TableMetrics.java  | 57 ++++++++++++++++++++
 .../org/apache/cassandra/tools/NodeProbe.java   | 22 ++++++--
 .../apache/cassandra/tools/nodetool/Info.java   |  3 ++
 .../cassandra/tools/nodetool/TableStats.java    |  6 +++
 .../tools/nodetool/stats/StatsHolder.java       |  1 +
 .../tools/nodetool/stats/StatsTable.java        |  1 +
 .../tools/nodetool/stats/TableStatsPrinter.java |  1 +
 8 files changed, 88 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 2b53d41..599d7c2 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -5,6 +5,7 @@
  * Remove DatabaseDescriptor dependency from FileUtils (CASSANDRA-11578)
  * Faster streaming (CASSANDRA-9766)
  * Add prepared query parameter to trace for "Execute CQL3 prepared query" 
session (CASSANDRA-11425)
+ * Add repaired percentage metric (CASSANDRA-11503)
 
 
 3.7

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/metrics/TableMetrics.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/metrics/TableMetrics.java 
b/src/java/org/apache/cassandra/metrics/TableMetrics.java
index 4282e16..d4be287 100644
--- a/src/java/org/apache/cassandra/metrics/TableMetrics.java
+++ b/src/java/org/apache/cassandra/metrics/TableMetrics.java
@@ -26,12 +26,16 @@ import com.codahale.metrics.*;
 import com.codahale.metrics.Timer;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
+
+import org.apache.cassandra.config.Schema;
 import org.apache.cassandra.db.ColumnFamilyStore;
 import org.apache.cassandra.db.Keyspace;
 import org.apache.cassandra.db.Memtable;
 import org.apache.cassandra.db.lifecycle.SSTableSet;
+import org.apache.cassandra.index.SecondaryIndexManager;
 import org.apache.cassandra.io.compress.CompressionMetadata;
 import org.apache.cassandra.io.sstable.format.SSTableReader;
+import org.apache.cassandra.repair.SystemDistributedKeyspace;
 import org.apache.cassandra.utils.EstimatedHistogram;
 import org.apache.cassandra.utils.TopKSampler;
 
@@ -139,6 +143,8 @@ public class TableMetrics
     public final LatencyMetrics casPropose;
     /** CAS Commit metrics */
     public final LatencyMetrics casCommit;
+    /** percent of the data that is repaired */
+    public final Gauge<Double> percentRepaired;
 
     public final Timer coordinatorReadLatency;
     public final Timer coordinatorScanLatency;
@@ -160,6 +166,40 @@ public class TableMetrics
     public final static LatencyMetrics globalWriteLatency = new 
LatencyMetrics(globalFactory, globalAliasFactory, "Write");
     public final static LatencyMetrics globalRangeLatency = new 
LatencyMetrics(globalFactory, globalAliasFactory, "Range");
 
+    public final static Gauge<Double> globalPercentRepaired = 
Metrics.register(globalFactory.createMetricName("PercentRepaired"),
+            new Gauge<Double>()
+    {
+        public Double getValue()
+        {
+            double repaired = 0;
+            double total = 0;
+            for (String keyspace : Schema.instance.getNonSystemKeyspaces())
+            {
+                Keyspace k = Schema.instance.getKeyspaceInstance(keyspace);
+                if (SystemDistributedKeyspace.NAME.equals(k.getName()))
+                    continue;
+                if (k.getReplicationStrategy().getReplicationFactor() < 2)
+                    continue;
+
+                for (ColumnFamilyStore cf : k.getColumnFamilyStores())
+                {
+                    if (!SecondaryIndexManager.isIndexColumnFamily(cf.name))
+                    {
+                        for (SSTableReader sstable : 
cf.getSSTables(SSTableSet.CANONICAL))
+                        {
+                            if (sstable.isRepaired())
+                            {
+                                repaired += sstable.uncompressedLength();
+                            }
+                            total += sstable.uncompressedLength();
+                        }
+                    }
+                }
+            }
+            return total > 0 ? (repaired / total) * 100 : 100.0;
+        }
+    });
+
     public final Map<Sampler, TopKSampler<ByteBuffer>> samplers;
     /**
      * stores metrics that will be rolled into a single global metric
@@ -343,6 +383,23 @@ public class TableMetrics
                                                                                
     p -> p.getAllSSTables(SSTableSet.CANONICAL))));
             }
         });
+        percentRepaired = createTableGauge("PercentRepaired", new 
Gauge<Double>()
+        {
+            public Double getValue()
+            {
+                double repaired = 0;
+                double total = 0;
+                for (SSTableReader sstable : 
cfs.getSSTables(SSTableSet.CANONICAL))
+                {
+                    if (sstable.isRepaired())
+                    {
+                        repaired += sstable.uncompressedLength();
+                    }
+                    total += sstable.uncompressedLength();
+                }
+                return total > 0 ? (repaired / total) * 100 : 100.0;
+            }
+        });
         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);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/NodeProbe.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java 
b/src/java/org/apache/cassandra/tools/NodeProbe.java
index 2118308..7775178 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -85,6 +85,7 @@ import org.apache.cassandra.streaming.StreamState;
 import org.apache.cassandra.streaming.management.StreamStateCompositeData;
 
 import com.google.common.base.Function;
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
@@ -1218,16 +1219,28 @@ public class NodeProbe implements AutoCloseable
 
     /**
      * Retrieve ColumnFamily metrics
-     * @param ks Keyspace for which stats are to be displayed.
-     * @param cf ColumnFamily for which stats are to be displayed.
+     * @param ks Keyspace for which stats are to be displayed or null for the 
global value
+     * @param cf ColumnFamily for which stats are to be displayed or null for 
the keyspace value (if ks supplied)
      * @param metricName View {@link TableMetrics}.
      */
     public Object getColumnFamilyMetric(String ks, String cf, String 
metricName)
     {
         try
         {
-            String type = cf.contains(".") ? "IndexTable" : "Table";
-            ObjectName oName = new 
ObjectName(String.format("org.apache.cassandra.metrics:type=%s,keyspace=%s,scope=%s,name=%s",
 type, ks, cf, metricName));
+            ObjectName oName = null;
+            if (!Strings.isNullOrEmpty(ks) && !Strings.isNullOrEmpty(cf))
+            {
+                String type = cf.contains(".") ? "IndexTable" : "Table";
+                oName = new 
ObjectName(String.format("org.apache.cassandra.metrics:type=%s,keyspace=%s,scope=%s,name=%s",
 type, ks, cf, metricName));
+            }
+            else if (!Strings.isNullOrEmpty(ks))
+            {
+                oName = new 
ObjectName(String.format("org.apache.cassandra.metrics:type=Keyspace,keyspace=%s,name=%s",
 ks, metricName));
+            }
+            else
+            {
+                oName = new 
ObjectName(String.format("org.apache.cassandra.metrics:type=Table,name=%s", 
metricName));
+            }
             switch(metricName)
             {
                 case "BloomFilterDiskSpaceUsed":
@@ -1248,6 +1261,7 @@ public class NodeProbe implements AutoCloseable
                 case "MemtableLiveDataSize":
                 case "MemtableOffHeapSize":
                 case "MinPartitionSize":
+                case "PercentRepaired":
                 case "RecentBloomFilterFalsePositives":
                 case "RecentBloomFilterFalseRatio":
                 case "SnapshotsSize":

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/nodetool/Info.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/Info.java 
b/src/java/org/apache/cassandra/tools/nodetool/Info.java
index c37f3b8..032e47f 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/Info.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/Info.java
@@ -139,6 +139,9 @@ public class Info extends NodeToolCmd
             // Chunk cache is not on.
         }
 
+        // Global table stats
+        System.out.printf("%-23s: %s%%%n", "Percent Repaired", 
probe.getColumnFamilyMetric(null, null, "PercentRepaired"));
+
         // check if node is already joined, before getting tokens, since it 
throws exception if not.
         if (probe.isJoined())
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java 
b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
index 01cd1c3..96457ea 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
@@ -131,6 +131,7 @@ public class TableStats extends NodeToolCmd
                 Long indexSummaryOffHeapSize = null;
                 Long compressionMetadataOffHeapSize = null;
                 Long offHeapSize = null;
+                Double percentRepaired = null;
 
                 try
                 {
@@ -139,6 +140,7 @@ public class TableStats extends NodeToolCmd
                     indexSummaryOffHeapSize = (Long) 
probe.getColumnFamilyMetric(keyspaceName, tableName, 
"IndexSummaryOffHeapMemoryUsed");
                     compressionMetadataOffHeapSize = (Long) 
probe.getColumnFamilyMetric(keyspaceName, tableName, 
"CompressionMetadataOffHeapMemoryUsed");
                     offHeapSize = memtableOffHeapSize + bloomFilterOffHeapSize 
+ indexSummaryOffHeapSize + compressionMetadataOffHeapSize;
+                    percentRepaired = (Double) 
probe.getColumnFamilyMetric(keyspaceName, tableName, "PercentRepaired");
                 }
                 catch (RuntimeException e)
                 {
@@ -156,6 +158,10 @@ public class TableStats extends NodeToolCmd
                     statsTable.offHeapMemoryUsedTotal = format(offHeapSize, 
humanReadable);
 
                 }
+                if (percentRepaired != null)
+                {
+                    statsTable.percentRepaired = Math.round(100 * 
percentRepaired) / 100.0;
+                }
                 statsTable.sstableCompressionRatio = 
probe.getColumnFamilyMetric(keyspaceName, tableName, "CompressionRatio");
                 statsTable.numberOfKeysEstimate = 
probe.getColumnFamilyMetric(keyspaceName, tableName, "EstimatedPartitionCount");
                 statsTable.memtableCellCount = 
probe.getColumnFamilyMetric(keyspaceName, tableName, "MemtableColumnsCount");

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/nodetool/stats/StatsHolder.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsHolder.java 
b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsHolder.java
index 96122f4..e26f3f7 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsHolder.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsHolder.java
@@ -71,6 +71,7 @@ public class StatsHolder
                 mpTable.put("local_write_count", table.localWriteCount);
                 mpTable.put("local_write_latency_ms", String.format("%01.3f", 
table.localWriteLatencyMs));
                 mpTable.put("pending_flushes", table.pendingFlushes);
+                mpTable.put("percent_repaired", table.percentRepaired);
                 mpTable.put("bloom_filter_false_positives", 
table.bloomFilterFalsePositives);
                 mpTable.put("bloom_filter_false_ratio", 
String.format("%01.5f", table.bloomFilterFalseRatio));
                 mpTable.put("bloom_filter_space_used", 
table.bloomFilterSpaceUsed);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java 
b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
index b707be6..71f35e9 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
@@ -56,6 +56,7 @@ public class StatsTable
     public long compactedPartitionMinimumBytes;
     public long compactedPartitionMaximumBytes;
     public long compactedPartitionMeanBytes;
+    public double percentRepaired;
     public double averageLiveCellsPerSliceLastFiveMinutes;
     public long maximumLiveCellsPerSliceLastFiveMinutes;
     public double averageTombstonesPerSliceLastFiveMinutes;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9b47dd50/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java 
b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
index 2d8b8a3..a6da189 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
@@ -98,6 +98,7 @@ public enum TableStatsPrinter
                     out.println("\t\tLocal write count: " + 
table.localWriteCount);
                     out.printf("\t\tLocal write latency: %01.3f ms%n", 
table.localWriteLatencyMs);
                     out.println("\t\tPending flushes: " + 
table.pendingFlushes);
+                    out.println("\t\tPercent repaired: " + 
table.percentRepaired);
 
                     out.println("\t\tBloom filter false positives: " + 
table.bloomFilterFalsePositives);
                     out.printf("\t\tBloom filter false ratio: %01.5f%n", 
table.bloomFilterFalseRatio);

Reply via email to