diff options
9 files changed, 121 insertions, 100 deletions
diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/BenchmarkingCluster.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/BenchmarkingCluster.java index a7d4e79356c..3e70bd94648 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/BenchmarkingCluster.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/BenchmarkingCluster.java @@ -64,7 +64,7 @@ public class BenchmarkingCluster implements Cluster { } @Override - public Stats stats() { + public OperationStats stats() { try { try { return executor.submit(this::getStats).get(); @@ -79,21 +79,21 @@ public class BenchmarkingCluster implements Cluster { } } - private Stats getStats() { + private OperationStats getStats() { Map<Integer, Long> responses = new HashMap<>(); for (int code = 0; code < responsesByCode.length; code++) if (responsesByCode[code] > 0) responses.put(code, responsesByCode[code]); - return new Stats(requests.get(), - responses, - exceptions, + return new OperationStats(requests.get(), + responses, + exceptions, requests.get() - results, totalLatencyMillis / this.responses, - minLatencyMillis, - maxLatencyMillis, - bytesSent, - bytesReceived); + minLatencyMillis, + maxLatencyMillis, + bytesSent, + bytesReceived); } @Override diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/Cluster.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/Cluster.java index 9ffccd740e8..da7d04830ad 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/Cluster.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/Cluster.java @@ -6,7 +6,6 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import java.io.Closeable; import java.util.Collections; -import java.util.Map; import java.util.concurrent.CompletableFuture; /** @@ -20,89 +19,6 @@ interface Cluster extends Closeable { @Override default void close() { } - default Stats stats() { return new Stats(0, Collections.emptyMap(), 0, 0, 0, 0, 0, 0, 0); } - - class Stats { - - private final long requests; - private final Map<Integer, Long> responsesByCode; - private final long inflight; - private final long exceptions; - private final long averageLatencyMillis; - private final long minLatencyMillis; - private final long maxLatencyMillis; - private final long bytesSent; - private final long bytesReceived; - - public Stats(long requests, Map<Integer, Long> responsesByCode, long exceptions, long inflight, - long averageLatencyMillis, long minLatencyMillis, long maxLatencyMillis, - long bytesSent, long bytesReceived) { - this.requests = requests; - this.responsesByCode = responsesByCode; - this.exceptions = exceptions; - this.inflight = inflight; - this.averageLatencyMillis = averageLatencyMillis; - this.minLatencyMillis = minLatencyMillis; - this.maxLatencyMillis = maxLatencyMillis; - this.bytesSent = bytesSent; - this.bytesReceived = bytesReceived; - } - - public long requests() { - return requests; - } - - public long responses() { - return requests - inflight; - } - - public Map<Integer, Long> responsesByCode() { - return responsesByCode; - } - - public long exceptions() { - return exceptions; - } - - public long inflight() { - return inflight; - } - - public long averageLatencyMillis() { - return averageLatencyMillis; - } - - public long minLatencyMillis() { - return minLatencyMillis; - } - - public long maxLatencyMillis() { - return maxLatencyMillis; - } - - public long bytesSent() { - return bytesSent; - } - - public long bytesReceived() { - return bytesReceived; - } - - @Override - public String toString() { - return "Stats{" + - "requests=" + requests + - ", responsesByCode=" + responsesByCode + - ", exceptions=" + exceptions + - ", inflight=" + inflight + - ", averageLatencyMillis=" + averageLatencyMillis + - ", minLatencyMillis=" + minLatencyMillis + - ", maxLatencyMillis=" + maxLatencyMillis + - ", bytesSent=" + bytesSent + - ", bytesReceived=" + bytesReceived + - '}'; - } - - } + default OperationStats stats() { return new OperationStats(0, Collections.emptyMap(), 0, 0, 0, 0, 0, 0, 0); } } diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClient.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClient.java index 2ac75a948d9..d4cd53daecc 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClient.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/FeedClient.java @@ -19,6 +19,9 @@ public interface FeedClient extends Closeable { /** Send a document remove with the given parameters, returning a future with the result of the operation. */ CompletableFuture<Result> remove(DocumentId documentId, OperationParameters params); + /** Returns a snapshot of the stats for this feed client, such as requests made, and responses by status. */ + OperationStats stats(); + /** Shut down, and reject new operations. Operations in flight are allowed to complete normally if graceful. */ void close(boolean graceful); diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java index 9b89595db25..6e7e20ae121 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpFeedClient.java @@ -64,6 +64,11 @@ class HttpFeedClient implements FeedClient { } @Override + public OperationStats stats() { + return requestStrategy.stats(); + } + + @Override public void close(boolean graceful) { closed.set(true); if (graceful) diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpRequestStrategy.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpRequestStrategy.java index e11358e4bf4..9754679f238 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpRequestStrategy.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/HttpRequestStrategy.java @@ -76,6 +76,10 @@ class HttpRequestStrategy implements RequestStrategy { dispatcher.start(); } + public OperationStats stats() { + return cluster.stats(); + } + private void dispatch() { try { while (breaker.state() != OPEN && ! destroyed.get()) { diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/OperationStats.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/OperationStats.java new file mode 100644 index 00000000000..9305709d873 --- /dev/null +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/OperationStats.java @@ -0,0 +1,92 @@ +// 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 java.util.Map; + +/** + * Statistics for feed operations over HTTP against a Vespa cluster. + * + * @author jonmv + */ +public class OperationStats { + + private final long requests; + private final Map<Integer, Long> responsesByCode; + private final long inflight; + private final long exceptions; + private final long averageLatencyMillis; + private final long minLatencyMillis; + private final long maxLatencyMillis; + private final long bytesSent; + private final long bytesReceived; + + public OperationStats(long requests, Map<Integer, Long> responsesByCode, long exceptions, long inflight, + long averageLatencyMillis, long minLatencyMillis, long maxLatencyMillis, + long bytesSent, long bytesReceived) { + this.requests = requests; + this.responsesByCode = responsesByCode; + this.exceptions = exceptions; + this.inflight = inflight; + this.averageLatencyMillis = averageLatencyMillis; + this.minLatencyMillis = minLatencyMillis; + this.maxLatencyMillis = maxLatencyMillis; + this.bytesSent = bytesSent; + this.bytesReceived = bytesReceived; + } + + public long requests() { + return requests; + } + + public long responses() { + return requests - inflight; + } + + public Map<Integer, Long> responsesByCode() { + return responsesByCode; + } + + public long exceptions() { + return exceptions; + } + + public long inflight() { + return inflight; + } + + public long averageLatencyMillis() { + return averageLatencyMillis; + } + + public long minLatencyMillis() { + return minLatencyMillis; + } + + public long maxLatencyMillis() { + return maxLatencyMillis; + } + + public long bytesSent() { + return bytesSent; + } + + public long bytesReceived() { + return bytesReceived; + } + + @Override + public String toString() { + return "Stats{" + + "requests=" + requests + + ", responsesByCode=" + responsesByCode + + ", exceptions=" + exceptions + + ", inflight=" + inflight + + ", averageLatencyMillis=" + averageLatencyMillis + + ", minLatencyMillis=" + minLatencyMillis + + ", maxLatencyMillis=" + maxLatencyMillis + + ", bytesSent=" + bytesSent + + ", bytesReceived=" + bytesReceived + + '}'; + } + +} diff --git a/vespa-feed-client/src/main/java/ai/vespa/feed/client/RequestStrategy.java b/vespa-feed-client/src/main/java/ai/vespa/feed/client/RequestStrategy.java index bda214405b5..bc2707bc490 100644 --- a/vespa-feed-client/src/main/java/ai/vespa/feed/client/RequestStrategy.java +++ b/vespa-feed-client/src/main/java/ai/vespa/feed/client/RequestStrategy.java @@ -15,6 +15,9 @@ import java.util.function.BiConsumer; */ interface RequestStrategy { + /** Stats for operations sent through this. */ + OperationStats stats(); + /** Whether this has failed fatally, and we should cease sending further operations. */ boolean hasFailed(); diff --git a/vespa-feed-client/src/test/java/ai/vespa/feed/client/HttpRequestStrategyTest.java b/vespa-feed-client/src/test/java/ai/vespa/feed/client/HttpRequestStrategyTest.java index cee292a41e0..4cc15465bd5 100644 --- a/vespa-feed-client/src/test/java/ai/vespa/feed/client/HttpRequestStrategyTest.java +++ b/vespa-feed-client/src/test/java/ai/vespa/feed/client/HttpRequestStrategyTest.java @@ -7,14 +7,9 @@ import org.apache.hc.core5.http.ContentType; import org.junit.jupiter.api.Test; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,7 +36,7 @@ class HttpRequestStrategyTest { strategy.await(); executor.shutdown(); cluster.close(); - Cluster.Stats stats = cluster.stats(); + OperationStats stats = cluster.stats(); long successes = stats.responsesByCode().get(200); System.err.println(successes + " successes in " + (System.nanoTime() - startNanos) * 1e-9 + " seconds"); System.err.println(stats); diff --git a/vespa-feed-client/src/test/java/ai/vespa/feed/client/JsonFeederTest.java b/vespa-feed-client/src/test/java/ai/vespa/feed/client/JsonFeederTest.java index f29f61482f3..e2ae5bc7155 100644 --- a/vespa-feed-client/src/test/java/ai/vespa/feed/client/JsonFeederTest.java +++ b/vespa-feed-client/src/test/java/ai/vespa/feed/client/JsonFeederTest.java @@ -72,6 +72,9 @@ class JsonFeederTest { } @Override + public OperationStats stats() { return null; } + + @Override public void close(boolean graceful) { } private CompletableFuture<Result> createSuccessResult(DocumentId documentId) { |