This is an automated email from the ASF dual-hosted git repository.
maedhroz pushed a commit to branch cassandra-5.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-5.0 by this push:
new 79630fb42a Add selected SAI index state and query performance metrics
to nodetool tablestats
79630fb42a is described below
commit 79630fb42ae9e42691f516590100c279f372ac89
Author: Sunil Ramchandra Pawar <[email protected]>
AuthorDate: Thu Jan 16 20:43:25 2025 +0530
Add selected SAI index state and query performance metrics to nodetool
tablestats
patch by Sunil Ramchandra Pawar; reviewed by Caleb Rackliffe, Matt Byrd,
and Maxim Muzafarov for CASSANDRA-20026
---
CHANGES.txt | 1 +
.../index/sai/metrics/IndexGroupMetrics.java | 3 +-
.../index/sai/metrics/TableQueryMetrics.java | 4 +-
src/java/org/apache/cassandra/tools/NodeProbe.java | 71 +++++++++++++++++
.../cassandra/tools/nodetool/TableStats.java | 6 +-
.../cassandra/tools/nodetool/stats/StatsTable.java | 10 +++
.../tools/nodetool/stats/StatsTableComparator.java | 46 ++++++++++-
.../tools/nodetool/stats/TableStatsHolder.java | 59 +++++++++++++++
.../tools/nodetool/stats/TableStatsPrinter.java | 14 ++++
.../cassandra/tools/nodetool/TableStatsTest.java | 6 +-
.../nodetool/stats/TableStatsPrinterTest.java | 88 ++++++++++++++--------
.../tools/nodetool/stats/TableStatsTestBase.java | 24 ++++++
12 files changed, 294 insertions(+), 38 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index feae546032..85c50621d1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0.3
+ * Add selected SAI index state and query performance metrics to nodetool
tablestats (CASSANDRA-20026)
* Remove v30 and v3X from 5.x in-JVM upgrade tests (CASSANDRA-20103)
* Avoid memory allocation in offheap_object's NativeCell.valueSize() and
NativeClustering.dataSize() (CASSANDRA-20162)
* Add flag to avoid invalidating key cache on sstable deletions
(CASSANDRA-20068)
diff --git
a/src/java/org/apache/cassandra/index/sai/metrics/IndexGroupMetrics.java
b/src/java/org/apache/cassandra/index/sai/metrics/IndexGroupMetrics.java
index f6545760b7..fff6291ab0 100644
--- a/src/java/org/apache/cassandra/index/sai/metrics/IndexGroupMetrics.java
+++ b/src/java/org/apache/cassandra/index/sai/metrics/IndexGroupMetrics.java
@@ -25,9 +25,10 @@ import static
org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
public class IndexGroupMetrics extends AbstractMetrics
{
+ public static final String INDEX_GROUP_METRICS_TYPE = "IndexGroupMetrics";
public IndexGroupMetrics(TableMetadata table, StorageAttachedIndexGroup
group)
{
- super(table.keyspace, table.name, "IndexGroupMetrics");
+ super(table.keyspace, table.name, INDEX_GROUP_METRICS_TYPE);
Metrics.register(createMetricName("OpenIndexFiles"), (Gauge<Integer>)
group::openIndexFiles);
Metrics.register(createMetricName("DiskUsedBytes"), (Gauge<Long>)
group::diskUsage);
diff --git
a/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
b/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
index 987c70ef75..bbfbe1d287 100644
--- a/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
+++ b/src/java/org/apache/cassandra/index/sai/metrics/TableQueryMetrics.java
@@ -71,6 +71,8 @@ public class TableQueryMetrics extends AbstractMetrics
public class PerQueryMetrics extends AbstractMetrics
{
+ public static final String PER_QUERY_METRICS_TYPE = "PerQuery";
+
private final Timer queryLatency;
/**
@@ -99,7 +101,7 @@ public class TableQueryMetrics extends AbstractMetrics
public PerQueryMetrics(TableMetadata table)
{
- super(table.keyspace, table.name, "PerQuery");
+ super(table.keyspace, table.name, PER_QUERY_METRICS_TYPE);
queryLatency = Metrics.timer(createMetricName("QueryLatency"));
diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java
b/src/java/org/apache/cassandra/tools/NodeProbe.java
index 93cb38128a..a917793ecc 100644
--- a/src/java/org/apache/cassandra/tools/NodeProbe.java
+++ b/src/java/org/apache/cassandra/tools/NodeProbe.java
@@ -90,6 +90,9 @@ import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.gms.GossiperMBean;
import org.apache.cassandra.hints.HintsService;
import org.apache.cassandra.hints.HintsServiceMBean;
+import org.apache.cassandra.index.sai.metrics.IndexGroupMetrics;
+import org.apache.cassandra.index.sai.metrics.TableQueryMetrics;
+import org.apache.cassandra.index.sai.metrics.TableStateMetrics;
import org.apache.cassandra.locator.DynamicEndpointSnitchMBean;
import org.apache.cassandra.locator.EndpointSnitchInfoMBean;
import org.apache.cassandra.metrics.CIDRAuthorizerMetrics;
@@ -1867,6 +1870,74 @@ public class NodeProbe implements AutoCloseable
}
}
+ public Object getSaiMetric(String ks, String cf, String metricName)
+ {
+ try
+ {
+ String scope = getSaiMetricScope(metricName);
+ String objectNameStr =
String.format("org.apache.cassandra.metrics:type=StorageAttachedIndex,keyspace=%s,table=%s,scope=%s,name=%s",ks,
cf, scope, metricName);
+ ObjectName oName = new ObjectName(objectNameStr);
+
+ Set<ObjectName> matchingMBeans = mbeanServerConn.queryNames(oName,
null);
+ if (matchingMBeans.isEmpty())
+ return null;
+
+ return getSaiMetricValue(metricName, oName);
+ }
+ catch (MalformedObjectNameException e)
+ {
+ throw new RuntimeException("Invalid ObjectName format: " +
e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Error accessing MBean server: " +
e.getMessage(), e);
+ }
+ }
+
+ private Object getSaiMetricValue(String metricName, ObjectName oName)
throws IOException
+ {
+ switch (metricName)
+ {
+ case "QueryLatency":
+ return JMX.newMBeanProxy(mbeanServerConn, oName,
CassandraMetricsRegistry.JmxTimerMBean.class);
+ case "PostFilteringReadLatency":
+ case "SSTableIndexesHit":
+ case "IndexSegmentsHit":
+ case "RowsFiltered":
+ return JMX.newMBeanProxy(mbeanServerConn, oName,
CassandraMetricsRegistry.JmxHistogramMBean.class);
+ case "DiskUsedBytes":
+ case "TotalIndexCount":
+ case "TotalQueryableIndexCount":
+ return JMX.newMBeanProxy(mbeanServerConn, oName,
CassandraMetricsRegistry.JmxGaugeMBean.class).getValue();
+ case "TotalQueryTimeouts":
+ return JMX.newMBeanProxy(mbeanServerConn, oName,
CassandraMetricsRegistry.JmxCounterMBean.class).getCount();
+ default:
+ throw new IllegalArgumentException("Unknown metric name: " +
metricName);
+ }
+ }
+
+ private String getSaiMetricScope(String metricName)
+ {
+ switch (metricName)
+ {
+ case "QueryLatency":
+ case "SSTableIndexesHit":
+ case "IndexSegmentsHit":
+ case "RowsFiltered":
+ return
TableQueryMetrics.PerQueryMetrics.PER_QUERY_METRICS_TYPE;
+ case "PostFilteringReadLatency":
+ case "TotalQueryTimeouts":
+ return TableQueryMetrics.TABLE_QUERY_METRIC_TYPE;
+ case "DiskUsedBytes":
+ return IndexGroupMetrics.INDEX_GROUP_METRICS_TYPE;
+ case "TotalIndexCount":
+ case "TotalQueryableIndexCount":
+ return TableStateMetrics.TABLE_STATE_METRIC_TYPE;
+ default:
+ throw new IllegalArgumentException("Unknown metric name: " +
metricName);
+ }
+ }
+
/**
* Retrieve threadpool paths and names for threadpools with metrics.
* @return Multimap from path (internal, request, etc.) to name
diff --git a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
index fc641e7891..a347fd5f7d 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
@@ -60,8 +60,10 @@ public class TableStats extends NodeToolCmd
+ "memtable_off_heap_memory_used,
memtable_switch_count, number_of_partitions_estimate, "
+ "off_heap_memory_used_total, pending_flushes,
percent_repaired, read_latency, reads, "
+ "space_used_by_snapshots_total, space_used_live,
space_used_total, "
- + "sstable_compression_ratio, sstable_count,
table_name, write_latency, writes, " +
- "max_sstable_size, local_read_write_ratio,
twcs_max_duration)")
+ + "sstable_compression_ratio, sstable_count,
table_name, write_latency, writes, "
+ + "max_sstable_size, local_read_write_ratio,
twcs_max_duration, sai_local_query_latency_ms,"
+ + "sai_post_filtering_read_latency,
sai_disk_used_bytes, sai_sstable_indexes_hit, sai_index_segments_hit "
+ + "sai_rows_filtered, sai_total_query_timeouts,
sai_total_queryable_index_ratio)")
private String sortKey = "";
@Option(title = "top",
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 680ebf649a..9272babf4b 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
@@ -82,4 +82,14 @@ public class StatsTable
public double localReadWriteRatio;
public Long twcsDurationInMillis;
public String twcs;
+
+ public double saiQueryLatencyMs;
+ public double saiPostFilteringReadLatencyMs;
+ public String saiDiskUsedBytes;
+ public double saiSSTableIndexesHit;
+ public double saiIndexSegmentsHit;
+ public double saiRowsFiltered;
+ public long saiTotalQueryTimeouts;
+ public int saiTotalIndexCount;
+ public String saiTotalQueryableIndexRatio;
}
diff --git
a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTableComparator.java
b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTableComparator.java
index c668829cdc..98d38120cc 100644
---
a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTableComparator.java
+++
b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTableComparator.java
@@ -66,7 +66,10 @@ public class StatsTableComparator implements
Comparator<StatsTable>
"space_used_by_snapshots_total", "space_used_live",
"space_used_total",
"sstable_compression_ratio", "sstable_count",
"table_name",
"write_latency", "writes", "max_sstable_size",
-
"local_read_write_ratio", "twcs_max_duration"};
+
"local_read_write_ratio", "twcs_max_duration", "sai_local_query_latency_ms",
+
"sai_post_filtering_read_latency","sai_disk_used_bytes","sai_sstable_indexes_hit",
+
"sai_index_segments_hit","sai_rows_filtered","sai_total_query_timeouts",
+
"sai_total_queryable_index_ratio"};
public StatsTableComparator(String sortKey, boolean humanReadable)
{
@@ -338,6 +341,47 @@ public class StatsTableComparator implements
Comparator<StatsTable>
{
return sign * stx.tableName.compareTo(sty.tableName);
}
+ else if(sortKey.equals("sai_local_query_latency_ms"))
+ {
+ result = compareDoubles(stx.saiQueryLatencyMs,
sty.saiQueryLatencyMs);
+ }
+ else if(sortKey.equals("sai_post_filtering_read_latency"))
+ {
+ result = compareDoubles(stx.saiPostFilteringReadLatencyMs,
sty.saiPostFilteringReadLatencyMs);
+ }
+ else if(sortKey.equals("sai_disk_used_bytes"))
+ {
+ result = compareFileSizes(stx.saiDiskUsedBytes,
+ sty.saiDiskUsedBytes);
+ }
+ else if(sortKey.equals("sai_sstable_indexes_hit"))
+ {
+ result = compareDoubles(stx.saiSSTableIndexesHit,
sty.saiSSTableIndexesHit);
+ }
+ else if(sortKey.equals("sai_index_segments_hit"))
+ {
+ result = compareDoubles(stx.saiIndexSegmentsHit,
sty.saiIndexSegmentsHit);
+ }
+ else if(sortKey.equals("sai_rows_filtered"))
+ {
+ result = compareDoubles(stx.saiRowsFiltered, sty.saiRowsFiltered);
+ }
+ else if(sortKey.equals("sai_total_query_timeouts"))
+ {
+ result = sign * Long.valueOf(stx.saiTotalQueryTimeouts)
+
.compareTo(Long.valueOf(sty.saiTotalQueryTimeouts));
+ }
+ else if(sortKey.equals("sai_total_queryable_index_ratio"))
+ {
+ if (stx.saiTotalQueryableIndexRatio == null &&
sty.saiTotalQueryableIndexRatio != null)
+ return sign * -1;
+ else if (stx.saiTotalQueryableIndexRatio != null &&
sty.saiTotalQueryableIndexRatio == null)
+ return sign;
+ else if (stx.saiTotalQueryableIndexRatio == null &&
sty.saiTotalQueryableIndexRatio == null)
+ return 0;
+
+ result = sign *
stx.saiTotalQueryableIndexRatio.compareTo(sty.saiTotalQueryableIndexRatio);
+ }
else
{
throw new IllegalStateException(String.format("Unsupported sort
key: %s", sortKey));
diff --git
a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
index af5190e647..a225ccb88c 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
@@ -33,6 +33,7 @@ import
org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy;
import org.apache.cassandra.db.compaction.TimeWindowCompactionStrategyOptions;
import org.apache.cassandra.io.util.*;
import org.apache.cassandra.metrics.*;
+import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.tools.*;
public class TableStatsHolder implements StatsHolder
@@ -173,6 +174,16 @@ public class TableStatsHolder implements StatsHolder
mpTable.put("top_tombstone_partitions", table.topTombstonePartitions);
if (locationCheck)
mpTable.put("sstables_in_correct_location",
table.isInCorrectLocation);
+
+ mpTable.put("sai_local_query_latency_ms",String.format("%01.3f",
table.saiQueryLatencyMs));
+ mpTable.put("sai_post_filtering_read_latency",String.format("%01.3f",
table.saiPostFilteringReadLatencyMs));
+ mpTable.put("sai_disk_used_bytes",table.saiDiskUsedBytes);
+ mpTable.put("sai_sstable_indexes_hit",table.saiSSTableIndexesHit);
+ mpTable.put("sai_index_segments_hit",table.saiIndexSegmentsHit);
+ mpTable.put("sai_rows_filtered",table.saiRowsFiltered);
+ mpTable.put("sai_total_query_timeouts",table.saiTotalQueryTimeouts);
+ mpTable.put("sai_total_queryable_index_ratio",
table.saiTotalQueryableIndexRatio);
+
return mpTable;
}
@@ -385,12 +396,60 @@ public class TableStatsHolder implements StatsHolder
if (table.getTopTombstonePartitionsLastUpdate() != null)
statsTable.topTombstonePartitionsLastUpdate =
millisToDateString(table.getTopTombstonePartitionsLastUpdate());
+ if (!SchemaConstants.isSystemKeyspace(keyspaceName))
+ {
+ Object totalIndexCount = probe.getSaiMetric(keyspaceName,
tableName, "TotalIndexCount");
+ statsTable.saiTotalIndexCount = (totalIndexCount != null)
? (int) totalIndexCount : 0;
+
+ if (statsTable.saiTotalIndexCount > 0)
+ {
+ Object queryLatencyMetric =
probe.getSaiMetric(keyspaceName, tableName, "QueryLatency");
+ double queryLatency =
getMetricMean(queryLatencyMetric);
+ statsTable.saiQueryLatencyMs = queryLatency > 0 ?
queryLatency : Double.NaN;
+
+ Object PostFilteringReadLatency =
probe.getSaiMetric(keyspaceName, tableName, "PostFilteringReadLatency");
+ double postfilteringreadlatency =
getMetricMean(PostFilteringReadLatency);
+ statsTable.saiPostFilteringReadLatencyMs =
postfilteringreadlatency > 0 ? postfilteringreadlatency : Double.NaN;
+
+ Object diskUsedBytes =
probe.getSaiMetric(keyspaceName, tableName, "DiskUsedBytes");
+ long saidiskusedbytes = (diskUsedBytes != null) ?
(long) diskUsedBytes : 0L;
+ statsTable.saiDiskUsedBytes = format(saidiskusedbytes,
humanReadable);
+
+ Object SSTableIndexesHit =
probe.getSaiMetric(keyspaceName, tableName, "SSTableIndexesHit");
+ statsTable.saiSSTableIndexesHit =
getMetricMean(SSTableIndexesHit);
+
+ Object IndexSegmentsHit =
probe.getSaiMetric(keyspaceName, tableName, "IndexSegmentsHit");
+ statsTable.saiIndexSegmentsHit =
getMetricMean(IndexSegmentsHit);
+
+ Object RowsFiltered = probe.getSaiMetric(keyspaceName,
tableName, "RowsFiltered");
+ statsTable.saiRowsFiltered =
getMetricMean(RowsFiltered);
+
+ Object totalQueryTimeouts =
probe.getSaiMetric(keyspaceName, tableName, "TotalQueryTimeouts");
+ statsTable.saiTotalQueryTimeouts = (totalQueryTimeouts
!= null) ? (Long) totalQueryTimeouts : 0L;
+
+ Object totalQueryableIndexCount =
probe.getSaiMetric(keyspaceName, tableName, "TotalQueryableIndexCount");
+ int saiTotalQueryableIndexCount =
(totalQueryableIndexCount != null) ? (int) totalQueryableIndexCount : 0;
+
+ statsTable.saiTotalQueryableIndexRatio =
String.format("%d/%d", saiTotalQueryableIndexCount,
statsTable.saiTotalIndexCount);
+ }
+ }
+
statsKeyspace.tables.add(statsTable);
}
keyspaces.add(statsKeyspace);
}
}
+ private double getMetricMean(Object metricObject) {
+ if (metricObject instanceof CassandraMetricsRegistry.JmxTimerMBean) {
+ return ((CassandraMetricsRegistry.JmxTimerMBean)
metricObject).getMean() / 1000;
+ }
+ if (metricObject instanceof
CassandraMetricsRegistry.JmxHistogramMBean) {
+ return Math.round(((CassandraMetricsRegistry.JmxHistogramMBean)
metricObject).getMean() * 100.0) / 100.0;
+ }
+ throw new IllegalArgumentException("Unsupported metric object type: "
+ metricObject.getClass().getName());
+ }
+
private void maybeAddTWCSWindowWithMaxDuration(StatsTable statsTable,
NodeProbe probe, String keyspaceName, String tableName)
{
Map<String, String> compactionParameters =
probe.getCfsProxy(statsTable.keyspaceName, statsTable.tableName)
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 02c0787a15..eb272d38dc 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
@@ -22,6 +22,7 @@ import java.io.PrintStream;
import java.util.List;
import java.util.Map;
+import org.apache.cassandra.schema.SchemaConstants;
import org.apache.cassandra.utils.FBUtilities;
public class TableStatsPrinter<T extends StatsHolder>
@@ -163,6 +164,19 @@ public class TableStatsPrinter<T extends StatsHolder>
for (Map.Entry<String, Long> tombstonecnt :
table.topTombstonePartitions.entrySet())
out.printf(indent + " %-" + maxWidth + "s %s%n",
tombstonecnt.getKey(), tombstonecnt.getValue());
}
+
+ if (!SchemaConstants.isSystemKeyspace(table.keyspaceName) &&
table.saiTotalIndexCount > 0)
+ {
+ out.println(indent + "SAI local query latency (mean): " +
String.format("%.3f ms", table.saiQueryLatencyMs));
+ out.println(indent + "SAI post-filtering latency (mean): " +
String.format("%.3f ms",table.saiPostFilteringReadLatencyMs));
+ out.println(indent + "SAI space used (bytes): " +
table.saiDiskUsedBytes);
+ out.println(indent + "SAI sstable indexes hit per query
(mean): " + table.saiSSTableIndexesHit);
+ out.println(indent + "SAI index segments hit per query (mean):
" + table.saiIndexSegmentsHit);
+ out.println(indent + "SAI rows filtered per query (mean): " +
table.saiRowsFiltered);
+ out.println(indent + "SAI local query timeouts: " +
table.saiTotalQueryTimeouts);
+ out.println(indent + "SAI queryable/total indexes: " +
table.saiTotalQueryableIndexRatio);
+ }
+
out.println("");
}
}
diff --git a/test/unit/org/apache/cassandra/tools/nodetool/TableStatsTest.java
b/test/unit/org/apache/cassandra/tools/nodetool/TableStatsTest.java
index b4e9b90f4a..bfd7b8bee4 100644
--- a/test/unit/org/apache/cassandra/tools/nodetool/TableStatsTest.java
+++ b/test/unit/org/apache/cassandra/tools/nodetool/TableStatsTest.java
@@ -112,7 +112,11 @@ public class TableStatsTest extends CQLTester
" read_latency, reads,
space_used_by_snapshots_total, space_used_live,\n" +
" space_used_total,
sstable_compression_ratio, sstable_count,\n" +
" table_name, write_latency, writes,
max_sstable_size,\n" +
- " local_read_write_ratio,
twcs_max_duration)\n" +
+ " local_read_write_ratio,
twcs_max_duration,\n" +
+ "
sai_local_query_latency_ms,sai_post_filtering_read_latency,\n" +
+ " sai_disk_used_bytes,
sai_sstable_indexes_hit, sai_index_segments_hit\n" +
+ " sai_rows_filtered,
sai_total_query_timeouts,\n" +
+ " sai_total_queryable_index_ratio)\n" +
"\n" +
" -t <top>, --top <top>\n" +
" Show only the top K tables for the sort
key (specify the number K of\n" +
diff --git
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
index 80dcb97642..427c5e2a40 100644
---
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
+++
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
@@ -228,6 +228,14 @@ public class TableStatsPrinterTest extends
TableStatsTestBase
"\tAverage tombstones per slice (last five minutes): 4.01\n" +
"\tMaximum tombstones per slice (last five minutes): 5\n" +
"\tDroppable tombstone ratio: 0.55556\n" +
+ "\tSAI local query latency (mean): 10.000 ms\n" +
+ "\tSAI post-filtering latency (mean): 1.000 ms\n" +
+ "\tSAI space used (bytes): 40 bytes\n" +
+ "\tSAI sstable indexes hit per query (mean): 3.5\n" +
+ "\tSAI index segments hit per query (mean): 4.0\n" +
+ "\tSAI rows filtered per query (mean): 55.0\n" +
+ "\tSAI local query timeouts: 4\n" +
+ "\tSAI queryable/total indexes: 5/5\n" +
"\n";
public static final String expectedDefaultTable6Output =
@@ -412,48 +420,56 @@ public class TableStatsPrinterTest extends
TableStatsTestBase
" \"write_latency_ms\" : null,\n" +
" \"tables\" : {\n" +
" \"table6\" : {\n" +
+ " \"twcs\" : null,\n" +
+ " \"sai_total_queryable_index_ratio\"
: \"0/0\",\n" +
+ " \"memtable_switch_count\" : 6,\n" +
+ " \"sai_post_filtering_read_latency\"
: \"NaN\",\n" +
+ " \"speculative_retries\" : 0,\n" +
+ "
\"average_live_cells_per_slice_last_five_minutes\" : 5.0,\n" +
+ " \"local_read_latency_ms\" :
\"1.000\",\n" +
+ " \"sstable_count\" : 1000,\n" +
+ "
\"compacted_partition_minimum_bytes\" : 6,\n" +
+ " \"sstable_compression_ratio\" :
0.68,\n" +
+ " \"max_sstable_size\" : 0,\n" +
+ " \"sai_index_segments_hit\" :
\"NaN\",\n" +
+ " \"memtable_off_heap_memory_used\" :
\"161803398\",\n" +
+ " \"bloom_filter_space_used\" :
\"101112\",\n" +
+ "
\"compacted_partition_maximum_bytes\" : 20,\n" +
+ " \"sai_rows_filtered\" : \"NaN\",\n" +
+ " \"droppable_tombstone_ratio\" :
\"0.66667\",\n" +
+ "
\"compression_metadata_off_heap_memory_used\" : \"1\",\n" +
+ " \"bloom_filter_false_ratio\" :
\"0.03000\",\n" +
+ " \"percent_repaired\" : 0.0,\n" +
"
\"average_tombstones_per_slice_last_five_minutes\" : 6.0,\n" +
" \"top_tombstone_partitions\" :
null,\n" +
+ " \"sai_total_query_timeouts\" : 0,\n"
+
"
\"bloom_filter_off_heap_memory_used\" : \"667408\",\n" +
- " \"twcs\" : null,\n" +
" \"bytes_pending_repair\" : 0,\n" +
- " \"memtable_switch_count\" : 6,\n" +
- " \"speculative_retries\" : 0,\n" +
"
\"maximum_tombstones_per_slice_last_five_minutes\" : 6,\n" +
" \"memtable_cell_count\" : 6666,\n" +
" \"memtable_data_size\" :
\"1000000\",\n" +
- "
\"average_live_cells_per_slice_last_five_minutes\" : 5.0,\n" +
- " \"local_read_latency_ms\" :
\"1.000\",\n" +
- " \"sstable_count\" : 1000,\n" +
" \"local_write_latency_ms\" :
\"0.500\",\n" +
" \"pending_flushes\" : 66,\n" +
- "
\"compacted_partition_minimum_bytes\" : 6,\n" +
" \"local_read_count\" : 5,\n" +
- " \"sstable_compression_ratio\" :
0.68,\n" +
- " \"max_sstable_size\" : 0,\n" +
" \"top_size_partitions\" : null,\n" +
" \"bloom_filter_false_positives\" :
400,\n" +
" \"off_heap_memory_used_total\" :
\"162470810\",\n" +
- " \"memtable_off_heap_memory_used\" :
\"161803398\",\n" +
"
\"index_summary_off_heap_memory_used\" : \"3\",\n" +
- " \"bloom_filter_space_used\" :
\"101112\",\n" +
+ " \"sai_local_query_latency_ms\" :
\"NaN\",\n" +
" \"sstables_in_each_level\" : [ ],\n"
+
- "
\"compacted_partition_maximum_bytes\" : 20,\n" +
" \"sstable_bytes_in_each_level\" : [
],\n" +
" \"space_used_total\" : \"0\",\n" +
" \"local_write_count\" : 0,\n" +
- " \"droppable_tombstone_ratio\" :
\"0.66667\",\n" +
- "
\"compression_metadata_off_heap_memory_used\" : \"1\",\n" +
+ " \"sai_sstable_indexes_hit\" :
\"NaN\",\n" +
" \"local_read_write_ratio\" :
\"0.00000\",\n" +
" \"number_of_partitions_estimate\" :
6,\n" +
+ " \"sai_disk_used_bytes\" :
\"NaN\",\n" +
" \"bytes_repaired\" : 0,\n" +
"
\"maximum_live_cells_per_slice_last_five_minutes\" : 2,\n" +
" \"space_used_live\" : \"666666\",\n"
+
" \"compacted_partition_mean_bytes\" :
3,\n" +
- " \"bloom_filter_false_ratio\" :
\"0.03000\",\n" +
" \"old_sstable_count\" : 0,\n" +
" \"bytes_unrepaired\" : 0,\n" +
- " \"percent_repaired\" : 0.0,\n" +
" \"space_used_by_snapshots_total\" :
\"0\"\n" +
" }\n" +
" },\n" +
@@ -481,48 +497,56 @@ public class TableStatsPrinterTest extends
TableStatsTestBase
" write_latency_ms: .NaN\n" +
" tables:\n" +
" table6:\n" +
+ " twcs: null\n" +
+ " sai_total_queryable_index_ratio:
0/0\n" +
+ " memtable_switch_count: 6\n" +
+ " sai_post_filtering_read_latency:
NaN\n" +
+ " speculative_retries: 0\n" +
+ "
average_live_cells_per_slice_last_five_minutes: 5.0\n" +
+ " local_read_latency_ms: '1.000'\n" +
+ " sstable_count: 1000\n" +
+ " compacted_partition_minimum_bytes:
6\n" +
+ " sstable_compression_ratio: 0.68\n" +
+ " max_sstable_size: 0\n" +
+ " sai_index_segments_hit: .NaN\n" +
+ " memtable_off_heap_memory_used:
'161803398'\n" +
+ " bloom_filter_space_used: '101112'\n" +
+ " compacted_partition_maximum_bytes:
20\n" +
+ " sai_rows_filtered: .NaN\n" +
+ " droppable_tombstone_ratio:
'0.66667'\n" +
+ "
compression_metadata_off_heap_memory_used: '1'\n" +
+ " bloom_filter_false_ratio: '0.03000'\n"
+
+ " percent_repaired: 0.0\n" +
"
average_tombstones_per_slice_last_five_minutes: 6.0\n" +
" top_tombstone_partitions: null\n" +
+ " sai_total_query_timeouts: 0\n" +
" bloom_filter_off_heap_memory_used:
'667408'\n" +
- " twcs: null\n" +
" bytes_pending_repair: 0\n" +
- " memtable_switch_count: 6\n" +
- " speculative_retries: 0\n" +
"
maximum_tombstones_per_slice_last_five_minutes: 6\n" +
" memtable_cell_count: 6666\n" +
" memtable_data_size: '1000000'\n" +
- "
average_live_cells_per_slice_last_five_minutes: 5.0\n" +
- " local_read_latency_ms: '1.000'\n" +
- " sstable_count: 1000\n" +
" local_write_latency_ms: '0.500'\n" +
" pending_flushes: 66\n" +
- " compacted_partition_minimum_bytes:
6\n" +
" local_read_count: 5\n" +
- " sstable_compression_ratio: 0.68\n" +
- " max_sstable_size: 0\n" +
" top_size_partitions: null\n" +
" bloom_filter_false_positives: 400\n" +
" off_heap_memory_used_total:
'162470810'\n" +
- " memtable_off_heap_memory_used:
'161803398'\n" +
" index_summary_off_heap_memory_used:
'3'\n" +
- " bloom_filter_space_used: '101112'\n" +
+ " sai_local_query_latency_ms: NaN\n" +
" sstables_in_each_level: []\n" +
- " compacted_partition_maximum_bytes:
20\n" +
" sstable_bytes_in_each_level: []\n" +
" space_used_total: '0'\n" +
" local_write_count: 0\n" +
- " droppable_tombstone_ratio:
'0.66667'\n" +
- "
compression_metadata_off_heap_memory_used: '1'\n" +
+ " sai_sstable_indexes_hit: .NaN\n" +
" local_read_write_ratio: '0.00000'\n" +
" number_of_partitions_estimate: 6\n" +
+ " sai_disk_used_bytes: NaN\n" +
" bytes_repaired: 0\n" +
"
maximum_live_cells_per_slice_last_five_minutes: 2\n" +
" space_used_live: '666666'\n" +
" compacted_partition_mean_bytes: 3\n" +
- " bloom_filter_false_ratio: '0.03000'\n"
+
" old_sstable_count: 0\n" +
" bytes_unrepaired: 0\n" +
- " percent_repaired: 0.0\n" +
" space_used_by_snapshots_total: '0'\n" +
" read_latency_ms: 0.0\n" +
" pending_flushes: 66\n" +
diff --git
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsTestBase.java
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsTestBase.java
index 317eff01f4..0e55e5a3d7 100644
---
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsTestBase.java
+++
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsTestBase.java
@@ -102,6 +102,14 @@ public class TableStatsTestBase
template.maximumTombstonesPerSliceLastFiveMinutes = 0L;
template.twcs = null;
template.twcsDurationInMillis = 0L;
+ template.saiQueryLatencyMs = Double.NaN;
+ template.saiPostFilteringReadLatencyMs = Double.NaN;
+ template.saiDiskUsedBytes = "NaN";
+ template.saiSSTableIndexesHit = Double.NaN;
+ template.saiIndexSegmentsHit = Double.NaN;
+ template.saiRowsFiltered = Double.NaN;
+ template.saiTotalQueryTimeouts = 0L;
+ template.saiTotalQueryableIndexRatio = "0/0";
return template;
}
@@ -337,6 +345,18 @@ public class TableStatsTestBase
table2.twcsDurationInMillis = 2000L;
table4.twcsDurationInMillis = 1000L;
table5.twcsDurationInMillis = null;
+
+ // Table5 with 5 SAI.
+ table5.saiQueryLatencyMs = 10.000D;
+ table5.saiPostFilteringReadLatencyMs = 1.000D;
+ table5.saiDiskUsedBytes = "40 bytes";
+ table5.saiSSTableIndexesHit = 3.5D;
+ table5.saiIndexSegmentsHit = 4.0D;
+ table5.saiRowsFiltered = 55.0D;
+ table5.saiTotalQueryTimeouts = 4L;
+ table5.saiTotalIndexCount = 5;
+ table5.saiTotalQueryableIndexRatio = "5/5";
+
// create test keyspaces from templates
testKeyspaces = new ArrayList<>();
StatsKeyspace keyspace1 = createStatsKeyspaceTemplate("keyspace1");
@@ -395,6 +415,10 @@ public class TableStatsTestBase
humanReadableTable4.memtableDataSize = "999 bytes";
humanReadableTable5.memtableDataSize = "3.14 MiB";
humanReadableTable6.memtableDataSize = "0 bytes";
+
+ // cretae human-readable SAI disk space used size:
+ humanReadableTable5.saiDiskUsedBytes = "40 bytes";
+
// create human readable keyspaces from template
humanReadableKeyspaces = new ArrayList<>();
StatsKeyspace humanReadableKeyspace1 =
createStatsKeyspaceTemplate("keyspace1");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]