Enhance nodetool compactionstats with additional metrics

patch by Manish Ghildiyal; reviewed by Stefan Miklosovic, Brandon Williams for CASSANDRA-18305

Co-authored-by: Stefan Miklosovic <smiklosovic@apache.org>
This commit is contained in:
mghildiy 2023-06-17 19:15:26 +05:30 committed by Stefan Miklosovic
parent ae537abc64
commit 7998e22127
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
6 changed files with 185 additions and 120 deletions

View File

@ -1,4 +1,5 @@
5.0
* Enhance nodetool compactionstats with additional metrics (CASSANDRA-18305)
* Added support for type VECTOR<type, dimension> (CASSANDRA-18504)
* Expose bootstrap and decommission state to nodetool info (CASSANDRA-18555)
* Fix SSTabledump errors when dumping data from index (CASSANDRA-17698)

View File

@ -101,7 +101,7 @@ public class CompactionIterator extends CompactionInfo.Holder implements Unfilte
private long totalSourceCQLRows;
// Keep targetDirectory for compactions, needed for `nodetool compactionstats`
private String targetDirectory;
private volatile String targetDirectory;
/*
* counters for merged rows.

View File

@ -1918,7 +1918,9 @@ public class NodeProbe implements AutoCloseable
/**
* Retrieve Proxy metrics
* @param metricName CompletedTasks, PendingTasks, BytesCompacted or TotalCompactionsCompleted.
* @param metricName BytesCompacted, CompactionsAborted, CompactionsReduced,
* SSTablesDroppedFromCompaction, CompletedTasks, PendingTasks, PendingTasksByTableName
* or TotalCompactionsCompleted.
*/
public Object getCompactionMetric(String metricName)
{
@ -1927,6 +1929,9 @@ public class NodeProbe implements AutoCloseable
switch(metricName)
{
case "BytesCompacted":
case "CompactionsAborted":
case "CompactionsReduced":
case "SSTablesDroppedFromCompaction":
return JMX.newMBeanProxy(mbeanServerConn,
new ObjectName("org.apache.cassandra.metrics:type=Compaction,name=" + metricName),
CassandraMetricsRegistry.JmxCounterMBean.class);
@ -1941,7 +1946,7 @@ public class NodeProbe implements AutoCloseable
new ObjectName("org.apache.cassandra.metrics:type=Compaction,name=" + metricName),
CassandraMetricsRegistry.JmxMeterMBean.class);
default:
throw new RuntimeException("Unknown compaction metric.");
throw new RuntimeException("Unknown compaction metric " + metricName);
}
}
catch (MalformedObjectNameException e)

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.tools.nodetool;
import java.io.PrintStream;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@ -28,8 +29,8 @@ import io.airlift.airline.Option;
import org.apache.cassandra.db.compaction.CompactionInfo;
import org.apache.cassandra.db.compaction.CompactionInfo.Unit;
import org.apache.cassandra.db.compaction.CompactionManagerMBean;
import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.metrics.CassandraMetricsRegistry;
import org.apache.cassandra.tools.NodeProbe;
import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
import org.apache.cassandra.tools.nodetool.formatter.TableBuilder;
@ -53,82 +54,119 @@ public class CompactionStats extends NodeToolCmd
public void execute(NodeProbe probe)
{
PrintStream out = probe.output().out;
CompactionManagerMBean cm = probe.getCompactionManagerProxy();
TableBuilder tableBuilder = new TableBuilder();
pendingTasksAndConcurrentCompactorsStats(probe, tableBuilder);
compactionsStats(probe, tableBuilder);
reportCompactionTable(probe.getCompactionManagerProxy().getCompactions(), probe.getCompactionThroughputBytes(), humanReadable, vtableOutput, out, tableBuilder);
}
private void pendingTasksAndConcurrentCompactorsStats(NodeProbe probe, TableBuilder tableBuilder)
{
Map<String, Map<String, Integer>> pendingTaskNumberByTable =
(Map<String, Map<String, Integer>>) probe.getCompactionMetric("PendingTasksByTableName");
int numTotalPendingTask = 0;
for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
{
for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
numTotalPendingTask += tableEntry.getValue();
}
out.println("pending tasks: " + numTotalPendingTask);
for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
{
String ksName = ksEntry.getKey();
for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
{
String tableName = tableEntry.getKey();
int pendingTaskCount = tableEntry.getValue();
(Map<String, Map<String, Integer>>) probe.getCompactionMetric("PendingTasksByTableName");
out.println("- " + ksName + '.' + tableName + ": " + pendingTaskCount);
}
}
out.println();
reportCompactionTable(cm.getCompactions(), probe.getCompactionThroughputBytes(), humanReadable, vtableOutput, out);
tableBuilder.add("concurrent compactors", Integer.toString(probe.getConcurrentCompactors()));
tableBuilder.add("pending tasks", Integer.toString(numPendingTasks(pendingTaskNumberByTable)));
for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
tableBuilder.add(ksEntry.getKey(), tableEntry.getKey(), tableEntry.getValue().toString());
}
public static void reportCompactionTable(List<Map<String,String>> compactions, long compactionThroughputInBytes, boolean humanReadable, PrintStream out)
private int numPendingTasks(Map<String, Map<String, Integer>> pendingTaskNumberByTable)
{
reportCompactionTable(compactions, compactionThroughputInBytes, humanReadable, false, out);
int numTotalPendingTasks = 0;
for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
numTotalPendingTasks += tableEntry.getValue();
return numTotalPendingTasks;
}
public static void reportCompactionTable(List<Map<String,String>> compactions, long compactionThroughputInBytes, boolean humanReadable, boolean vtableOutput, PrintStream out)
private void compactionsStats(NodeProbe probe, TableBuilder tableBuilder)
{
if (!compactions.isEmpty())
CassandraMetricsRegistry.JmxMeterMBean totalCompactionsCompletedMetrics =
(CassandraMetricsRegistry.JmxMeterMBean) probe.getCompactionMetric("TotalCompactionsCompleted");
tableBuilder.add("compactions completed", String.valueOf(totalCompactionsCompletedMetrics.getCount()));
CassandraMetricsRegistry.JmxCounterMBean bytesCompacted = (CassandraMetricsRegistry.JmxCounterMBean) probe.getCompactionMetric("BytesCompacted");
if (humanReadable)
tableBuilder.add("data compacted", FileUtils.stringifyFileSize(Double.parseDouble(Long.toString(bytesCompacted.getCount()))));
else
tableBuilder.add("data compacted", Long.toString(bytesCompacted.getCount()));
CassandraMetricsRegistry.JmxCounterMBean compactionsAborted = (CassandraMetricsRegistry.JmxCounterMBean) probe.getCompactionMetric("CompactionsAborted");
tableBuilder.add("compactions aborted", Long.toString(compactionsAborted.getCount()));
CassandraMetricsRegistry.JmxCounterMBean compactionsReduced = (CassandraMetricsRegistry.JmxCounterMBean) probe.getCompactionMetric("CompactionsReduced");
tableBuilder.add("compactions reduced", Long.toString(compactionsReduced.getCount()));
CassandraMetricsRegistry.JmxCounterMBean sstablesDroppedFromCompaction = (CassandraMetricsRegistry.JmxCounterMBean) probe.getCompactionMetric("SSTablesDroppedFromCompaction");
tableBuilder.add("sstables dropped from compaction", Long.toString(sstablesDroppedFromCompaction.getCount()));
NumberFormat formatter = new DecimalFormat("0.00");
tableBuilder.add("15 minute rate", String.format("%s/minute", formatter.format(totalCompactionsCompletedMetrics.getFifteenMinuteRate() * 60)));
tableBuilder.add("mean rate", String.format("%s/hour", formatter.format(totalCompactionsCompletedMetrics.getMeanRate() * 60 * 60)));
double configured = probe.getStorageService().getCompactionThroughtputMibPerSecAsDouble();
tableBuilder.add("compaction throughput (MiB/s)", configured == 0 ? "throttling disabled (0)" : Double.toString(configured));
}
public static void reportCompactionTable(List<Map<String,String>> compactions, long compactionThroughputInBytes, boolean humanReadable, PrintStream out, TableBuilder table)
{
reportCompactionTable(compactions, compactionThroughputInBytes, humanReadable, false, out, table);
}
public static void reportCompactionTable(List<Map<String,String>> compactions, long compactionThroughputInBytes, boolean humanReadable, boolean vtableOutput, PrintStream out, TableBuilder table)
{
if (compactions.isEmpty())
{
long remainingBytes = 0;
TableBuilder table = new TableBuilder();
if (vtableOutput)
table.add("keyspace", "table", "task id", "completion ratio", "kind", "progress", "sstables", "total", "unit", "target directory");
else
table.add("id", "compaction type", "keyspace", "table", "completed", "total", "unit", "progress");
for (Map<String, String> c : compactions)
{
long total = Long.parseLong(c.get(CompactionInfo.TOTAL));
long completed = Long.parseLong(c.get(CompactionInfo.COMPLETED));
String taskType = c.get(CompactionInfo.TASK_TYPE);
String keyspace = c.get(CompactionInfo.KEYSPACE);
String columnFamily = c.get(CompactionInfo.COLUMNFAMILY);
String unit = c.get(CompactionInfo.UNIT);
boolean toFileSize = humanReadable && Unit.isFileSize(unit);
String[] tables = c.get(CompactionInfo.SSTABLES).split(",");
String progressStr = toFileSize ? FileUtils.stringifyFileSize(completed) : Long.toString(completed);
String totalStr = toFileSize ? FileUtils.stringifyFileSize(total) : Long.toString(total);
String percentComplete = total == 0 ? "n/a" : new DecimalFormat("0.00").format((double) completed / total * 100) + "%";
String id = c.get(CompactionInfo.COMPACTION_ID);
if (vtableOutput)
{
String targetDirectory = c.get(CompactionInfo.TARGET_DIRECTORY);
table.add(keyspace, columnFamily, id, percentComplete, taskType, progressStr, String.valueOf(tables.length), totalStr, unit, targetDirectory);
}
else
table.add(id, taskType, keyspace, columnFamily, progressStr, totalStr, unit, percentComplete);
remainingBytes += total - completed;
}
table.printTo(out);
String remainingTime = "n/a";
if (compactionThroughputInBytes != 0)
{
long remainingTimeInSecs = remainingBytes / compactionThroughputInBytes;
remainingTime = format("%dh%02dm%02ds", remainingTimeInSecs / 3600, (remainingTimeInSecs % 3600) / 60, (remainingTimeInSecs % 60));
}
out.printf("%25s%10s%n", "Active compaction remaining time : ", remainingTime);
return;
}
long remainingBytes = 0;
if (vtableOutput)
table.add("keyspace", "table", "task id", "completion ratio", "kind", "progress", "sstables", "total", "unit", "target directory");
else
table.add("id", "compaction type", "keyspace", "table", "completed", "total", "unit", "progress");
for (Map<String, String> c : compactions)
{
long total = Long.parseLong(c.get(CompactionInfo.TOTAL));
long completed = Long.parseLong(c.get(CompactionInfo.COMPLETED));
String taskType = c.get(CompactionInfo.TASK_TYPE);
String keyspace = c.get(CompactionInfo.KEYSPACE);
String columnFamily = c.get(CompactionInfo.COLUMNFAMILY);
String unit = c.get(CompactionInfo.UNIT);
boolean toFileSize = humanReadable && Unit.isFileSize(unit);
String[] tables = c.get(CompactionInfo.SSTABLES).split(",");
String progressStr = toFileSize ? FileUtils.stringifyFileSize(completed) : Long.toString(completed);
String totalStr = toFileSize ? FileUtils.stringifyFileSize(total) : Long.toString(total);
String percentComplete = total == 0 ? "n/a" : new DecimalFormat("0.00").format((double) completed / total * 100) + '%';
String id = c.get(CompactionInfo.COMPACTION_ID);
if (vtableOutput)
{
String targetDirectory = c.get(CompactionInfo.TARGET_DIRECTORY);
table.add(keyspace, columnFamily, id, percentComplete, taskType, progressStr, String.valueOf(tables.length), totalStr, unit, targetDirectory);
}
else
table.add(id, taskType, keyspace, columnFamily, progressStr, totalStr, unit, percentComplete);
remainingBytes += total - completed;
}
String remainingTime = "n/a";
if (compactionThroughputInBytes != 0)
{
long remainingTimeInSecs = remainingBytes / compactionThroughputInBytes;
remainingTime = format("%dh%02dm%02ds", remainingTimeInSecs / 3600, (remainingTimeInSecs % 3600) / 60, (remainingTimeInSecs % 60));
}
table.add("active compaction remaining time", remainingTime);
table.printTo(out);
}
}

View File

@ -35,11 +35,10 @@ import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.schema.MockSchema;
import org.apache.cassandra.tools.ToolRunner;
import org.apache.cassandra.utils.TimeUUID;
import org.assertj.core.api.Assertions;
import org.awaitility.Awaitility;
import static org.apache.cassandra.utils.TimeUUID.Generator.nextTimeUUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
public class CompactionStatsTest extends CQLTester
{
@ -58,42 +57,42 @@ public class CompactionStatsTest extends CQLTester
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("help", "compactionstats");
tool.assertOnCleanExit();
String help = "NAME\n" +
" nodetool compactionstats - Print statistics on compactions\n" +
"\n" +
"SYNOPSIS\n" +
" nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]\n" +
" [(-pp | --print-port)] [(-pw <password> | --password <password>)]\n" +
" [(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]\n" +
" [(-u <username> | --username <username>)] compactionstats\n" +
" [(-H | --human-readable)] [(-V | --vtable)]\n" +
"\n" +
"OPTIONS\n" +
" -h <host>, --host <host>\n" +
" Node hostname or ip address\n" +
"\n" +
" -H, --human-readable\n" +
" Display bytes in human readable form, i.e. KiB, MiB, GiB, TiB\n" +
"\n" +
" -p <port>, --port <port>\n" +
" Remote jmx agent port number\n" +
"\n" +
" -pp, --print-port\n" +
" Operate in 4.0 mode with hosts disambiguated by port number\n" +
"\n" +
" -pw <password>, --password <password>\n" +
" Remote jmx agent password\n" +
"\n" +
" -pwf <passwordFilePath>, --password-file <passwordFilePath>\n" +
" Path to the JMX password file\n" +
"\n" +
" -u <username>, --username <username>\n" +
" Remote jmx agent username\n" +
"\n" +
" -V, --vtable\n" +
" Display fields matching vtable output\n" +
"\n" +
"\n";
String help = "NAME\n" +
" nodetool compactionstats - Print statistics on compactions\n" +
"\n" +
"SYNOPSIS\n" +
" nodetool [(-h <host> | --host <host>)] [(-p <port> | --port <port>)]\n" +
" [(-pp | --print-port)] [(-pw <password> | --password <password>)]\n" +
" [(-pwf <passwordFilePath> | --password-file <passwordFilePath>)]\n" +
" [(-u <username> | --username <username>)] compactionstats\n" +
" [(-H | --human-readable)] [(-V | --vtable)]\n" +
"\n" +
"OPTIONS\n" +
" -h <host>, --host <host>\n" +
" Node hostname or ip address\n" +
"\n" +
" -H, --human-readable\n" +
" Display bytes in human readable form, i.e. KiB, MiB, GiB, TiB\n" +
"\n" +
" -p <port>, --port <port>\n" +
" Remote jmx agent port number\n" +
"\n" +
" -pp, --print-port\n" +
" Operate in 4.0 mode with hosts disambiguated by port number\n" +
"\n" +
" -pw <password>, --password <password>\n" +
" Remote jmx agent password\n" +
"\n" +
" -pwf <passwordFilePath>, --password-file <passwordFilePath>\n" +
" Path to the JMX password file\n" +
"\n" +
" -u <username>, --username <username>\n" +
" Remote jmx agent username\n" +
"\n" +
" -V, --vtable\n" +
" Display fields matching vtable output\n" +
"\n" +
"\n";
assertThat(tool.getStdout()).isEqualTo(help);
}
@ -124,11 +123,23 @@ public class CompactionStatsTest extends CQLTester
CompactionManager.instance.active.beginCompaction(compactionHolder);
String stdout = waitForNumberOfPendingTasks(1, "compactionstats");
Assertions.assertThat(stdout).containsPattern("id\\s+compaction type\\s+keyspace\\s+table\\s+completed\\s+total\\s+unit\\s+progress");
assertThat(stdout).containsPattern("id\\s+compaction type\\s+keyspace\\s+table\\s+completed\\s+total\\s+unit\\s+progress");
String expectedStatsPattern = String.format("%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%.2f%%",
compactionId, OperationType.COMPACTION, CQLTester.KEYSPACE, currentTable(), bytesCompacted, bytesTotal,
CompactionInfo.Unit.BYTES, (double) bytesCompacted / bytesTotal * 100);
Assertions.assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern("concurrent compactors\\s+[0-9]*");
assertThat(stdout).containsPattern("pending tasks\\s+[0-9]*");
assertThat(stdout).containsPattern("compactions completed\\s+[0-9]*");
assertThat(stdout).containsPattern("data compacted\\s+[0-9]*");
assertThat(stdout).containsPattern("compactions aborted\\s+[0-9]*");
assertThat(stdout).containsPattern("compactions reduced\\s+[0-9]*");
assertThat(stdout).containsPattern("sstables dropped from compaction\\s+[0-9]*");
assertThat(stdout).containsPattern("15 minute rate\\s+[0-9]*.[0-9]*[0-9]*/minute");
assertThat(stdout).containsPattern("mean rate\\s+[0-9]*.[0-9]*[0-9]*/hour");
assertThat(stdout).containsPattern("compaction throughput \\(MiB/s\\)\\s+throttling disabled \\(0\\)");
CompactionManager.instance.active.finishCompaction(compactionHolder);
waitForNumberOfPendingTasks(0, "compactionstats");
@ -176,17 +187,17 @@ public class CompactionStatsTest extends CQLTester
CompactionManager.instance.active.beginCompaction(compactionHolder);
CompactionManager.instance.active.beginCompaction(nonCompactionHolder);
String stdout = waitForNumberOfPendingTasks(2, "compactionstats", "-V");
Assertions.assertThat(stdout).containsPattern("keyspace\\s+table\\s+task id\\s+completion ratio\\s+kind\\s+progress\\s+sstables\\s+total\\s+unit\\s+target directory");
assertThat(stdout).containsPattern("keyspace\\s+table\\s+task id\\s+completion ratio\\s+kind\\s+progress\\s+sstables\\s+total\\s+unit\\s+target directory");
String expectedStatsPattern = String.format("%s\\s+%s\\s+%s\\s+%.2f%%\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s",
CQLTester.KEYSPACE, currentTable(), compactionId, (double) bytesCompacted / bytesTotal * 100,
OperationType.COMPACTION, bytesCompacted, sstables.size(), bytesTotal, CompactionInfo.Unit.BYTES,
targetDirectory);
Assertions.assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern(expectedStatsPattern);
String expectedStatsPatternForNonCompaction = String.format("%s\\s+%s\\s+%s\\s+%.2f%%\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s",
CQLTester.KEYSPACE, currentTable(), compactionId, (double) bytesCompacted / bytesTotal * 100,
OperationType.COMPACTION, bytesCompacted, sstables.size(), bytesTotal, CompactionInfo.Unit.BYTES);
Assertions.assertThat(stdout).containsPattern(expectedStatsPatternForNonCompaction);
assertThat(stdout).containsPattern(expectedStatsPatternForNonCompaction);
CompactionManager.instance.active.finishCompaction(compactionHolder);
CompactionManager.instance.active.finishCompaction(nonCompactionHolder);
@ -220,11 +231,11 @@ public class CompactionStatsTest extends CQLTester
CompactionManager.instance.active.beginCompaction(compactionHolder);
String stdout = waitForNumberOfPendingTasks(1, "compactionstats", "--human-readable");
Assertions.assertThat(stdout).containsPattern("id\\s+compaction type\\s+keyspace\\s+table\\s+completed\\s+total\\s+unit\\s+progress");
assertThat(stdout).containsPattern("id\\s+compaction type\\s+keyspace\\s+table\\s+completed\\s+total\\s+unit\\s+progress");
String expectedStatsPattern = String.format("%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%.2f%%",
compactionId, OperationType.COMPACTION, CQLTester.KEYSPACE, currentTable(), "123 bytes", "120.56 KiB",
CompactionInfo.Unit.BYTES, (double) bytesCompacted / bytesTotal * 100);
Assertions.assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern(expectedStatsPattern);
CompactionManager.instance.active.finishCompaction(compactionHolder);
waitForNumberOfPendingTasks(0, "compactionstats", "--human-readable");
@ -272,16 +283,16 @@ public class CompactionStatsTest extends CQLTester
CompactionManager.instance.active.beginCompaction(compactionHolder);
CompactionManager.instance.active.beginCompaction(nonCompactionHolder);
String stdout = waitForNumberOfPendingTasks(2, "compactionstats", "--vtable", "--human-readable");
Assertions.assertThat(stdout).containsPattern("keyspace\\s+table\\s+task id\\s+completion ratio\\s+kind\\s+progress\\s+sstables\\s+total\\s+unit\\s+target directory");
assertThat(stdout).containsPattern("keyspace\\s+table\\s+task id\\s+completion ratio\\s+kind\\s+progress\\s+sstables\\s+total\\s+unit\\s+target directory");
String expectedStatsPattern = String.format("%s\\s+%s\\s+%s\\s+%.2f%%\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s",
CQLTester.KEYSPACE, currentTable(), compactionId, (double) bytesCompacted / bytesTotal * 100,
OperationType.COMPACTION, "123 bytes", sstables.size(), "120.56 KiB", CompactionInfo.Unit.BYTES,
targetDirectory);
Assertions.assertThat(stdout).containsPattern(expectedStatsPattern);
assertThat(stdout).containsPattern(expectedStatsPattern);
String expectedStatsPatternForNonCompaction = String.format("%s\\s+%s\\s+%s\\s+%.2f%%\\s+%s\\s+%s\\s+%s\\s+%s\\s+%s",
CQLTester.KEYSPACE, currentTable(), compactionId, (double) bytesCompacted / bytesTotal * 100,
OperationType.CLEANUP, "123 bytes", sstables.size(), "120.56 KiB", CompactionInfo.Unit.BYTES);
Assertions.assertThat(stdout).containsPattern(expectedStatsPatternForNonCompaction);
assertThat(stdout).containsPattern(expectedStatsPatternForNonCompaction);
CompactionManager.instance.active.finishCompaction(compactionHolder);
CompactionManager.instance.active.finishCompaction(nonCompactionHolder);
@ -291,12 +302,21 @@ public class CompactionStatsTest extends CQLTester
private String waitForNumberOfPendingTasks(int pendingTasksToWaitFor, String... args)
{
AtomicReference<String> stdout = new AtomicReference<>();
Awaitility.await().until(() -> {
await().until(() -> {
ToolRunner.ToolResult tool = ToolRunner.invokeNodetool(args);
tool.assertOnCleanExit();
String output = tool.getStdout();
stdout.set(output);
return output.contains("pending tasks: " + pendingTasksToWaitFor);
try
{
assertThat(output).containsPattern("pending tasks\\s+" + pendingTasksToWaitFor);
return true;
}
catch (AssertionError e)
{
return false;
}
});
return stdout.get();

View File

@ -64,6 +64,7 @@ import org.apache.cassandra.stress.generate.SeedManager;
import org.apache.cassandra.stress.operations.userdefined.SchemaInsert;
import org.apache.cassandra.stress.settings.StressSettings;
import org.apache.cassandra.tools.nodetool.CompactionStats;
import org.apache.cassandra.tools.nodetool.formatter.TableBuilder;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.concurrent.Future;
@ -274,7 +275,7 @@ public abstract class CompactionStress implements Runnable
{
System.out.println("========");
System.out.println(String.format("Pending compactions: %d\n", CompactionManager.instance.getPendingTasks()));
CompactionStats.reportCompactionTable(CompactionManager.instance.getCompactions(), 0, true, System.out);
CompactionStats.reportCompactionTable(CompactionManager.instance.getCompactions(), 0, true, System.out, new TableBuilder());
}