Skip to content

Commit

Permalink
CASSANDRA-18305: Enhance nodetool compactionstats for cassandra 4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mghildiy committed May 27, 2023
1 parent f0699bc commit 5f27b73
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,11 @@ public void setMaxConcurrentAutoUpgradeTasks(int value)
}
}

public double getCompactionRate()
{
return compactionRateLimiter.getRate();
}

/**
* Try to stop all of the compactions for given ColumnFamilies.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,9 @@ public interface CompactionManagerMBean
* when automatic sstable upgrades are enabled
*/
public void setMaxConcurrentAutoUpgradeTasks(int value);

/**
* Get the compaction rate
*/
public double getCompactionRate();
}
5 changes: 5 additions & 0 deletions src/java/org/apache/cassandra/tools/NodeProbe.java
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,11 @@ public int getCompactionThroughput()
return ssProxy.getCompactionThroughputMbPerSec();
}

public double getCompactionRate()
{
return compactionProxy.getCompactionRate();
}

public void setBatchlogReplayThrottle(int value)
{
ssProxy.setBatchlogReplayThrottleInKB(value);
Expand Down
82 changes: 70 additions & 12 deletions src/java/org/apache/cassandra/tools/nodetool/CompactionStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@

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;

import io.airlift.airline.Command;
import io.airlift.airline.Option;

import org.apache.cassandra.config.CassandraRelevantProperties;
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;
Expand All @@ -39,6 +42,8 @@
@Command(name = "compactionstats", description = "Print statistics on compactions")
public class CompactionStats extends NodeToolCmd
{
private static final String LINE_SEPARATOR = CassandraRelevantProperties.LINE_SEPARATOR.getString();

@Option(title = "human_readable",
name = {"-H", "--human-readable"},
description = "Display bytes in human readable form, i.e. KiB, MiB, GiB, TiB")
Expand All @@ -48,29 +53,82 @@ public class CompactionStats extends NodeToolCmd
public void execute(NodeProbe probe)
{
PrintStream out = probe.output().out;
out.print(pendingTasksAndConcurrentCompactorsStats(probe));
out.print(compactionsCompletedStats(probe));
out.print(compactionThroughputStats(probe));
out.println();
CompactionManagerMBean cm = probe.getCompactionManagerProxy();
reportCompactionTable(cm.getCompactions(), probe.getCompactionThroughput(), humanReadable, out);
}

private static String pendingTasksAndConcurrentCompactorsStats(NodeProbe probe)
{
Map<String, Map<String, Integer>> pendingTaskNumberByTable =
(Map<String, Map<String, Integer>>) probe.getCompactionMetric("PendingTasksByTableName");
int numTotalPendingTask = 0;
(Map<String, Map<String, Integer>>) probe.getCompactionMetric("PendingTasksByTableName");
StringBuffer toPrint = new StringBuffer();
toPrint.append(String.format("%s concurrent compactors, %s pending tasks", probe.getConcurrentCompactors()
, numPendingTasks(pendingTaskNumberByTable)));
toPrint.append(LINE_SEPARATOR);
for (Entry<String, Map<String, Integer>> ksEntry : pendingTaskNumberByTable.entrySet())
{
String ksName = ksEntry.getKey();
for (Entry<String, Integer> tableEntry : ksEntry.getValue().entrySet())
numTotalPendingTask += tableEntry.getValue();
{
toPrint.append("- " + ksName + '.' + tableEntry.getKey() + ": " + tableEntry.getValue());
toPrint.append(LINE_SEPARATOR);
}
}
out.println("pending tasks: " + numTotalPendingTask);

return toPrint.toString();
}

private static int numPendingTasks(Map<String, Map<String, Integer>> pendingTaskNumberByTable)
{
int numTotalPendingTasks = 0;
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();
numTotalPendingTasks += tableEntry.getValue();
}

out.println("- " + ksName + '.' + tableName + ": " + pendingTaskCount);
}
return numTotalPendingTasks;
}

private static String compactionsCompletedStats(NodeProbe probe)
{
Long completedTasks = (Long)probe.getCompactionMetric("CompletedTasks");
CassandraMetricsRegistry.JmxMeterMBean totalCompactionsCompletedMetrics =
(CassandraMetricsRegistry.JmxMeterMBean)probe.getCompactionMetric("TotalCompactionsCompleted");
NumberFormat formatter = new DecimalFormat("##.00");
StringBuffer toPrint = new StringBuffer();
toPrint.append(String.format("compactions completed: %s", completedTasks));
toPrint.append(LINE_SEPARATOR);
toPrint.append(String.format("\tminute rate: %s/second", formatter.format(totalCompactionsCompletedMetrics.getOneMinuteRate())));
toPrint.append(LINE_SEPARATOR);
toPrint.append(String.format("\t5 minute rate: %s/second", formatter.format(totalCompactionsCompletedMetrics.getFiveMinuteRate())));
toPrint.append(LINE_SEPARATOR);
toPrint.append(String.format("\t15 minute rate: %s/second", formatter.format(totalCompactionsCompletedMetrics.getFifteenMinuteRate())));
toPrint.append(LINE_SEPARATOR);
toPrint.append(String.format("\tMean rate: %s/second", formatter.format(totalCompactionsCompletedMetrics.getMeanRate())));
toPrint.append(LINE_SEPARATOR);

return toPrint.toString();
}

private static String compactionThroughputStats(NodeProbe probe)
{
double configured = probe.getCompactionThroughput();
double actual = probe.getCompactionRate() / (1024 * 1024);
if(configured == 0)
{
return String.format("compaction throughput absolute: %s MBps", actual);
}
out.println();
reportCompactionTable(cm.getCompactions(), probe.getCompactionThroughput(), humanReadable, out);
else
{
double percentage = (actual / configured) * 100;
return String.format("compaction throughput ratio: %s MBps / %s MBps (%s%s)", actual, configured, percentage, "%");
}

}

public static void reportCompactionTable(List<Map<String,String>> compactions, int compactionThroughput, boolean humanReadable, PrintStream out)
Expand Down

0 comments on commit 5f27b73

Please sign in to comment.