Print header and statistics for cassandra-stress output with arbitrary frequency
patch by Stefan Miklosovic; reviewed by Brandon Williams and Berenguer Blasi for CASSANDRA-12972
diff --git a/CHANGES.txt b/CHANGES.txt
index be232c4..cb81015 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
5.0
+ * Print header and statistics for cassandra-stress output with arbitrary frequency (CASSANDRA-12972)
* CEP-25: Trie-indexed SSTable format (CASSANDRA-18398)
* Make cassandra-stress able to read all credentials from a file (CASSANDRA-18544)
* Add guardrail for partition size and deprecate compaction_large_partition_warning_threshold (CASSANDRA-18500)
diff --git a/doc/modules/cassandra/pages/managing/tools/cassandra_stress.adoc b/doc/modules/cassandra/pages/managing/tools/cassandra_stress.adoc
index e24367c..5d6f0a1 100644
--- a/doc/modules/cassandra/pages/managing/tools/cassandra_stress.adoc
+++ b/doc/modules/cassandra/pages/managing/tools/cassandra_stress.adoc
@@ -75,6 +75,8 @@
Username and password for JMX connection
-credentials-file <path>:;;
Credentials file to specify for CQL, JMX and transport
+ -reporting:;;
+ Frequency of printing statistics and header for stress output
Suboptions:::
Every command and primary option has its own collection of suboptions.
These are too numerous to list here. For information on the suboptions
diff --git a/tools/stress/src/org/apache/cassandra/stress/report/StressMetrics.java b/tools/stress/src/org/apache/cassandra/stress/report/StressMetrics.java
index 85bfc32..8579bbf 100644
--- a/tools/stress/src/org/apache/cassandra/stress/report/StressMetrics.java
+++ b/tools/stress/src/org/apache/cassandra/stress/report/StressMetrics.java
@@ -83,11 +83,14 @@
private final Queue<OpMeasurement> leftovers = new ArrayDeque<>();
private final TimingInterval totalCurrentInterval;
private final TimingInterval totalSummaryInterval;
+ private final int outputFrequencyInSeconds;
+ private final int headerFrequencyInSeconds;
+ private int outputLines = 0;
public StressMetrics(ResultLogger output, final long logIntervalMillis, StressSettings settings)
{
this.output = output;
- if(settings.log.hdrFile != null)
+ if (settings.log.hdrFile != null)
{
try
{
@@ -134,6 +137,8 @@
reportingLoop(logIntervalMillis);
});
thread.setName("StressMetrics");
+ headerFrequencyInSeconds = settings.reporting.headerFrequency;
+ outputFrequencyInSeconds = settings.reporting.outputFrequency;
}
public void start()
{
@@ -263,7 +268,12 @@
opInterval.reset();
}
- printRow("", "total", totalCurrentInterval, totalSummaryInterval, gcStats, rowRateUncertainty, output);
+ ++outputLines;
+ if (outputFrequencyInSeconds == 0 || outputLines % outputFrequencyInSeconds == 0)
+ printRow("", "total", totalCurrentInterval, totalSummaryInterval, gcStats, rowRateUncertainty, output);
+ if (headerFrequencyInSeconds != 0 && outputLines % headerFrequencyInSeconds == 0)
+ printHeader("\n", output);
+
totalCurrentInterval.reset();
}
}
diff --git a/tools/stress/src/org/apache/cassandra/stress/settings/CliOption.java b/tools/stress/src/org/apache/cassandra/stress/settings/CliOption.java
index 3d721f3..5504671 100644
--- a/tools/stress/src/org/apache/cassandra/stress/settings/CliOption.java
+++ b/tools/stress/src/org/apache/cassandra/stress/settings/CliOption.java
@@ -40,7 +40,8 @@
JMX("JMX credentials", SettingsJMX.helpPrinter()),
GRAPH("-graph", "Graph recorded metrics", SettingsGraph.helpPrinter()),
TOKENRANGE("Token range settings", SettingsTokenRange.helpPrinter()),
- CREDENTIALS_FILE("Credentials file for CQL, JMX and transport", SettingsCredentials.helpPrinter());
+ CREDENTIALS_FILE("Credentials file for CQL, JMX and transport", SettingsCredentials.helpPrinter()),
+ REPORTING("Frequency of printing statistics and header for stress output", SettingsReporting.helpPrinter());
;
private static final Map<String, CliOption> LOOKUP;
diff --git a/tools/stress/src/org/apache/cassandra/stress/settings/SettingsReporting.java b/tools/stress/src/org/apache/cassandra/stress/settings/SettingsReporting.java
new file mode 100644
index 0000000..1fa2154
--- /dev/null
+++ b/tools/stress/src/org/apache/cassandra/stress/settings/SettingsReporting.java
@@ -0,0 +1,116 @@
+/*
+ * 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.stress.settings;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cassandra.config.DurationSpec;
+import org.apache.cassandra.stress.util.ResultLogger;
+
+public class SettingsReporting implements Serializable
+{
+ public final int outputFrequency;
+ private final String outputFrequencyString;
+ public final int headerFrequency;
+ private final String headerFrequencyString;
+
+ public SettingsReporting(SettingsReporting.Options reporting)
+ {
+ if (reporting.headerFrequency.present())
+ {
+ headerFrequencyString = reporting.headerFrequency.value();
+ headerFrequency = new DurationSpec.IntSecondsBound(headerFrequencyString).toSeconds();
+ }
+ else
+ {
+ headerFrequency = 0;
+ headerFrequencyString = "*not set*";
+ }
+
+ if (reporting.outputFrequency.present())
+ {
+ outputFrequencyString = reporting.outputFrequency.value();
+ outputFrequency = new DurationSpec.IntSecondsBound(outputFrequencyString).toSeconds();
+ }
+ else
+ {
+ outputFrequency = 0;
+ outputFrequencyString = "*not set*";
+ }
+ }
+
+ // Option Declarations
+
+ public static final class Options extends GroupedOptions
+ {
+ final OptionSimple outputFrequency = new OptionSimple("output-frequency=",
+ ".*",
+ "1s",
+ "Frequency each line of output will be printed out when running a stress test, defaults to '1s'.",
+ false);
+
+ final OptionSimple headerFrequency = new OptionSimple("header-frequency=",
+ ".*",
+ null,
+ "Frequency the header for the statistics will be printed out. " +
+ "If not specified, the header will be printed at the beginning of the test only.",
+ false);
+
+ @Override
+ public List<? extends Option> options()
+ {
+ return Arrays.asList(outputFrequency, headerFrequency);
+ }
+ }
+
+ public static SettingsReporting get(Map<String, String[]> clArgs)
+ {
+ String[] params = clArgs.remove("-reporting");
+ if (params == null)
+ return new SettingsReporting(new SettingsReporting.Options());
+
+ GroupedOptions options = GroupedOptions.select(params, new SettingsReporting.Options());
+ if (options == null)
+ {
+ printHelp();
+ System.out.println("Invalid -reporting options provided, see output for valid options");
+ System.exit(1);
+ }
+ return new SettingsReporting((SettingsReporting.Options) options);
+ }
+
+ public void printSettings(ResultLogger out)
+ {
+ out.printf(" Output frequency: %s%n", outputFrequencyString);
+ out.printf(" Header frequency: %s%n", headerFrequencyString);
+ }
+
+ public static void printHelp()
+ {
+ GroupedOptions.printOptions(System.out, "-reporting", new SettingsReporting.Options());
+ }
+
+ public static Runnable helpPrinter()
+ {
+ return SettingsReporting::printHelp;
+ }
+}
diff --git a/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java b/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
index 9b83118..12d731e 100644
--- a/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
+++ b/tools/stress/src/org/apache/cassandra/stress/settings/StressSettings.java
@@ -47,6 +47,7 @@
public final SettingsJMX jmx;
public final SettingsGraph graph;
public final SettingsTokenRange tokenRange;
+ public final SettingsReporting reporting;
public StressSettings(SettingsCommand command,
SettingsRate rate,
@@ -63,7 +64,8 @@
SettingsPort port,
SettingsJMX jmx,
SettingsGraph graph,
- SettingsTokenRange tokenRange)
+ SettingsTokenRange tokenRange,
+ SettingsReporting reporting)
{
this.command = command;
this.rate = rate;
@@ -81,6 +83,7 @@
this.jmx = jmx;
this.graph = graph;
this.tokenRange = tokenRange;
+ this.reporting = reporting;
}
public SimpleClient getSimpleNativeClient()
@@ -207,6 +210,7 @@
SettingsTransport transport = SettingsTransport.get(clArgs, credentials);
SettingsJMX jmx = SettingsJMX.get(clArgs, credentials);
SettingsGraph graph = SettingsGraph.get(clArgs, command);
+ SettingsReporting reporting = SettingsReporting.get(clArgs);
if (!clArgs.isEmpty())
{
printHelp();
@@ -224,7 +228,7 @@
System.exit(1);
}
- return new StressSettings(command, rate, generate, insert, columns, errors, log, credentials, mode, node, schema, transport, port, jmx, graph, tokenRange);
+ return new StressSettings(command, rate, generate, insert, columns, errors, log, credentials, mode, node, schema, transport, port, jmx, graph, tokenRange, reporting);
}
private static Map<String, String[]> parseMap(String[] args)
@@ -306,6 +310,8 @@
tokenRange.printSettings(out);
out.println("Credentials file:");
credentials.printSettings(out);
+ out.println("Reporting:");
+ reporting.printSettings(out);
if (command.type == Command.USER)
{