aboutsummaryrefslogtreecommitdiffstats
path: root/vespa-feed-client-cli
diff options
context:
space:
mode:
authorJon Marius Venstad <venstad@gmail.com>2021-06-24 17:01:13 +0200
committerJon Marius Venstad <venstad@gmail.com>2021-06-24 20:11:49 +0200
commit3c123c3a50ad792a41411ca30edb6f10964622c5 (patch)
tree5876ecd830fc8c4ad8ca17b5d35f3eec4be5669d /vespa-feed-client-cli
parent6e3e12c60e1d8435bd651019e9c34dcd1cea2691 (diff)
More CLI print options
Diffstat (limited to 'vespa-feed-client-cli')
-rw-r--r--vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java28
-rw-r--r--vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java61
-rw-r--r--vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java5
3 files changed, 75 insertions, 19 deletions
diff --git a/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java
index 18c1c6a22fa..0f6d125f764 100644
--- a/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java
+++ b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliArguments.java
@@ -49,6 +49,9 @@ class CliArguments {
private static final String TIMEOUT_OPTION = "timeout";
private static final String TRACE_OPTION = "trace";
private static final String VERBOSE_OPTION = "verbose";
+ private static final String SHOW_ERRORS_OPTION = "show-errors";
+ private static final String SHOW_ALL_OPTION = "show-all";
+ private static final String SILENT_OPTION = "silent";
private static final String VERSION_OPTION = "version";
private static final String STDIN_OPTION = "stdin";
@@ -136,6 +139,12 @@ class CliArguments {
boolean benchmarkModeEnabled() { return has(BENCHMARK_OPTION); }
+ boolean showProgress() { return ! has(SILENT_OPTION); }
+
+ boolean showErrors() { return has(SHOW_ERRORS_OPTION) || has(SHOW_ALL_OPTION); }
+
+ boolean showSuccesses() { return has(SHOW_ALL_OPTION); }
+
Optional<String> route() { return stringValue(ROUTE_OPTION); }
OptionalInt traceLevel() throws CliArgumentsException { return intValue(TRACE_OPTION); }
@@ -222,7 +231,7 @@ class CliArguments {
.build())
.addOption(Option.builder()
.longOpt(MAX_STREAMS_PER_CONNECTION)
- .desc("Number of concurrent streams per HTTP/2 connection")
+ .desc("Maximum number of concurrent streams per HTTP/2 connection")
.hasArg()
.type(Number.class)
.build())
@@ -274,11 +283,24 @@ class CliArguments {
.desc("Read JSON input from standard input")
.build())
.addOption(Option.builder()
+ .longOpt(DRYRUN_OPTION)
+ .desc("Enable dryrun mode where each operation succeeds after " + DryrunCluster.DELAY.toMillis() + "ms")
+ .build())
+ .addOption(Option.builder()
.longOpt(VERBOSE_OPTION)
+ .desc("Print stack traces on errors")
.build())
.addOption(Option.builder()
- .longOpt(DRYRUN_OPTION)
- .desc("Enable dryrun mode where each operation succeeds after " + DryrunCluster.DELAY.toMillis() + "ms")
+ .longOpt(SILENT_OPTION)
+ .desc("Disable periodic status printing")
+ .build())
+ .addOption(Option.builder()
+ .longOpt(SHOW_ERRORS_OPTION)
+ .desc("Print every feed operation failure")
+ .build())
+ .addOption(Option.builder()
+ .longOpt(SHOW_ALL_OPTION)
+ .desc("Print the result of every feed operation")
.build());
}
diff --git a/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java
index 1c20f6b5c1b..881194a8490 100644
--- a/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java
+++ b/vespa-feed-client-cli/src/main/java/ai/vespa/feed/client/CliClient.java
@@ -1,6 +1,7 @@
// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.feed.client;
+import ai.vespa.feed.client.JsonFeeder.ResultCallback;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
@@ -12,8 +13,10 @@ import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.Map;
-import java.util.Optional;
import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Main method for CLI interface
@@ -27,6 +30,7 @@ public class CliClient {
private final InputStream systemIn;
private final Properties systemProperties;
private final Map<String, String> environmentVariables;
+ private final Object printMonitor = new Object();
private CliClient(PrintStream systemOut, PrintStream systemError, InputStream systemIn,
Properties systemProperties, Map<String, String> environmentVariables) {
@@ -44,9 +48,10 @@ public class CliClient {
}
private int run(String[] rawArgs) {
- CliArguments cliArgs = null;
+ boolean verbose = false;
try {
- cliArgs = CliArguments.fromRawArgs(rawArgs);
+ CliArguments cliArgs = CliArguments.fromRawArgs(rawArgs);
+ verbose = cliArgs.verboseSpecified();
if (cliArgs.helpSpecified()) {
cliArgs.printHelp(systemOut);
return 0;
@@ -58,22 +63,55 @@ public class CliClient {
try (InputStream in = createFeedInputStream(cliArgs);
FeedClient feedClient = createFeedClient(cliArgs);
JsonFeeder feeder = createJsonFeeder(feedClient, cliArgs)) {
+ CountDownLatch latch = new CountDownLatch(1);
+ AtomicReference<FeedException> fatal = new AtomicReference<>();
long startNanos = System.nanoTime();
- feeder.feedMany(in).join();
+ feeder.feedMany(in, new ResultCallback() {
+ @Override public void onNextResult(Result result, FeedException error) { handleResult(result, error, cliArgs); }
+ @Override public void onError(FeedException error) { fatal.set(error); }
+ @Override public void onComplete() { latch.countDown(); }
+ });
+ if (cliArgs.showProgress()) {
+ new Thread(() -> {
+ try {
+ while ( ! latch.await(10, TimeUnit.SECONDS)) {
+ synchronized (printMonitor) { printBenchmarkResult(System.nanoTime() - startNanos, feedClient.stats(), systemError);}
+ }
+ }
+ catch (InterruptedException | IOException ignored) { } // doesn't happen
+ }).start();
+ }
+ latch.await();
if (cliArgs.benchmarkModeEnabled()) {
printBenchmarkResult(System.nanoTime() - startNanos, feedClient.stats(), systemOut);
}
+ if (fatal.get() != null) throw fatal.get();
}
return 0;
- } catch (CliArguments.CliArgumentsException | IOException e) {
- boolean verbose = cliArgs != null && cliArgs.verboseSpecified();
+ } catch (CliArguments.CliArgumentsException | IOException | FeedException e) {
return handleException(verbose, e);
} catch (Exception e) {
- boolean verbose = cliArgs != null && cliArgs.verboseSpecified();
return handleException(verbose, "Unknown failure: " + e.getMessage(), e);
}
}
+ private void handleResult(Result result, FeedException error, CliArguments args) {
+ if (error != null) {
+ if (args.showErrors()) synchronized (printMonitor) {
+ systemError.println(error.getMessage());
+ if (error instanceof ResultException) ((ResultException) error).getTrace().ifPresent(systemError::println);
+ if (args.verboseSpecified()) error.printStackTrace(systemError);
+ }
+ }
+ else {
+ if (args.showSuccesses()) synchronized (printMonitor) {
+ systemError.println(result.documentId() + ": " + result.type());
+ result.traceMessage().ifPresent(systemError::println);
+ result.resultMessage().ifPresent(systemError::println);
+ }
+ }
+ }
+
private static FeedClient createFeedClient(CliArguments cliArgs) throws CliArguments.CliArgumentsException {
FeedClientBuilder builder = FeedClientBuilder.create(cliArgs.endpoint());
cliArgs.connections().ifPresent(builder::setConnectionsPerEndpoint);
@@ -104,19 +142,12 @@ public class CliClient {
private int handleException(boolean verbose, String message, Exception exception) {
systemError.println(message);
- if (debugMode() || verbose) {
+ if (verbose) {
exception.printStackTrace(systemError);
}
return 1;
}
- private boolean debugMode() {
- boolean enabledWithSystemProperty = Boolean.parseBoolean(systemProperties.getProperty("VESPA_DEBUG", Boolean.FALSE.toString()));
- boolean enabledWithEnvironmentVariable = Optional.ofNullable(environmentVariables.get("VESPA_DEBUG"))
- .map(Boolean::parseBoolean).orElse(false);
- return enabledWithSystemProperty || enabledWithEnvironmentVariable;
- }
-
private static class AcceptAllHostnameVerifier implements HostnameVerifier {
static final AcceptAllHostnameVerifier INSTANCE = new AcceptAllHostnameVerifier();
@Override public boolean verify(String hostname, SSLSession session) { return true; }
diff --git a/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java b/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java
index a99399e638d..5300329656e 100644
--- a/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java
+++ b/vespa-feed-client-cli/src/test/java/ai/vespa/feed/client/CliArgumentsTest.java
@@ -23,7 +23,7 @@ class CliArgumentsTest {
"--max-streams-per-connection=128", "--certificate=cert.pem", "--private-key=key.pem",
"--ca-certificates=ca-certs.pem", "--disable-ssl-hostname-verification",
"--header=\"My-Header: my-value\"", "--header", "Another-Header: another-value", "--benchmark",
- "--route=myroute", "--timeout=0.125", "--trace=9", "--verbose"});
+ "--route=myroute", "--timeout=0.125", "--trace=9", "--verbose", "--silent", "--show-errors", "--show-all"});
assertEquals(URI.create("https://vespa.ai:4443/"), args.endpoint());
assertEquals(Paths.get("feed.json"), args.inputFile().get());
assertEquals(10, args.connections().getAsInt());
@@ -42,6 +42,9 @@ class CliArgumentsTest {
assertEquals(Duration.ofMillis(125), args.timeout().get());
assertEquals(9, args.traceLevel().getAsInt());
assertTrue(args.verboseSpecified());
+ assertTrue(args.showErrors());
+ assertTrue(args.showSuccesses());
+ assertFalse(args.showProgress());
}
@Test