From 9d309b2ec8db1868d3695e8f9fc36ce763e8926c Mon Sep 17 00:00:00 2001 From: Ola Aunrønning Date: Tue, 14 May 2019 11:02:13 +0200 Subject: Refactoring --- .../vespa/config/server/ApplicationRepository.java | 7 +- .../config/server/http/v2/MetricsResponse.java | 21 ++-- .../yahoo/vespa/config/server/metrics/Metrics.java | 90 -------------- .../config/server/metrics/MetricsAggregator.java | 137 +++++++++------------ .../config/server/metrics/MetricsRetriever.java | 101 +++++++++++++++ .../server/http/v2/ApplicationHandlerTest.java | 2 - .../server/metrics/MetricsAggregatorTest.java | 95 -------------- .../server/metrics/MetricsRetrieverTest.java | 99 +++++++++++++++ .../maintenance/DeploymentMetricsMaintainer.java | 11 -- 9 files changed, 274 insertions(+), 289 deletions(-) delete mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/metrics/Metrics.java create mode 100644 configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsRetriever.java delete mode 100644 configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsAggregatorTest.java create mode 100644 configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsRetrieverTest.java diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java index 4268782b446..7e2fa440bd5 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/ApplicationRepository.java @@ -43,8 +43,7 @@ import com.yahoo.vespa.config.server.http.CompressedApplicationInputStream; import com.yahoo.vespa.config.server.http.LogRetriever; import com.yahoo.vespa.config.server.http.SimpleHttpFetcher; import com.yahoo.vespa.config.server.http.v2.PrepareResult; -import com.yahoo.vespa.config.server.metrics.Metrics; -import com.yahoo.vespa.config.server.metrics.MetricsAggregator; +import com.yahoo.vespa.config.server.metrics.MetricsRetriever; import com.yahoo.vespa.config.server.provision.HostProvisionerProvider; import com.yahoo.vespa.config.server.session.LocalSession; import com.yahoo.vespa.config.server.session.LocalSessionRepo; @@ -588,9 +587,9 @@ public class ApplicationRepository implements com.yahoo.config.provision.Deploye // ---------------- Metrics ------------------------------------------------------------------------ public HttpResponse getMetrics() { - MetricsAggregator metricsAggregator = new MetricsAggregator(); + MetricsRetriever metricsRetriever = new MetricsRetriever(); Map>> applicationHosts = getHostsPerApplication(); - return metricsAggregator.aggregateAllMetrics(applicationHosts); + return metricsRetriever.retrieveAllMetrics(applicationHosts); } // ---------------- Misc operations ---------------------------------------------------------------- diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/MetricsResponse.java b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/MetricsResponse.java index 237a1e6dccb..c18608f5f64 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/MetricsResponse.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/http/v2/MetricsResponse.java @@ -7,7 +7,7 @@ import com.yahoo.slime.Cursor; import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; import com.yahoo.vespa.config.server.http.HttpConfigResponse; -import com.yahoo.vespa.config.server.metrics.Metrics; +import com.yahoo.vespa.config.server.metrics.MetricsAggregator; import java.io.IOException; import java.io.OutputStream; @@ -20,23 +20,24 @@ public class MetricsResponse extends HttpResponse { private final Slime slime = new Slime(); - public MetricsResponse(int status, Map> aggregatedMetrics) { + public MetricsResponse(int status, Map> aggregatedMetrics) { super(status); Cursor array = slime.setArray(); - for (Map.Entry> entry : aggregatedMetrics.entrySet()) { + for (Map.Entry> entry : aggregatedMetrics.entrySet()) { Cursor object = array.addObject(); object.setString("applicationId", entry.getKey().serializedForm()); Cursor clusterArray = object.setArray("clusters"); - for (Map.Entry clusterMetrics : entry.getValue().entrySet()) { + for (Map.Entry clusterMetrics : entry.getValue().entrySet()) { Cursor clusterCursor = clusterArray.addObject(); - Metrics metrics = clusterMetrics.getValue(); + MetricsAggregator metrics = clusterMetrics.getValue(); clusterCursor.setString("clusterName", clusterMetrics.getKey()); - metrics.aggregateQueryRate().ifPresent(queryrate -> clusterCursor.setDouble("queriesPerSecond", queryrate)); - metrics.aggregateFeedRate().ifPresent(feedRate -> clusterCursor.setDouble("writesPerSecond", feedRate)); - metrics.aggregateDocumentCount().ifPresent(documentCount -> clusterCursor.setDouble("documentCount", documentCount)); - metrics.aggregateQueryLatency().ifPresent(queryLatency -> clusterCursor.setDouble("queryLatencyMillis",queryLatency)); - metrics.aggregateFeedLatency().ifPresent(feedLatency -> clusterCursor.setDouble("feedLatency", feedLatency)); + Cursor metricsCursor = clusterCursor.setObject("metrics"); + metrics.aggregateQueryRate().ifPresent(queryrate -> metricsCursor.setDouble("queriesPerSecond", queryrate)); + metrics.aggregateFeedRate().ifPresent(feedRate -> metricsCursor.setDouble("writesPerSecond", feedRate)); + metrics.aggregateDocumentCount().ifPresent(documentCount -> metricsCursor.setDouble("documentCount", documentCount)); + metrics.aggregateQueryLatency().ifPresent(queryLatency -> metricsCursor.setDouble("queryLatencyMillis",queryLatency)); + metrics.aggregateFeedLatency().ifPresent(feedLatency -> metricsCursor.setDouble("feedLatency", feedLatency)); clusterCursor.setLong("timestamp", metrics.getTimestamp().getEpochSecond()); } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/Metrics.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/Metrics.java deleted file mode 100644 index 2fcfbf013bc..00000000000 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/Metrics.java +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.config.server.metrics; - -import java.time.Instant; -import java.util.Optional; - -/** - * @author olaa - */ -public class Metrics { - - double feedLatencySum; - double feedLatencyCount; - double qrQueryLatencySum; - double qrQueryLatencyCount; - double containerQueryLatencySum; - double containerQueryLatencyCount; - double documentCount; - Instant timestamp; - - public void addFeedLatencySum(double feedLatencySum) { - this.feedLatencySum += feedLatencySum; - } - - public void addFeedLatencyCount(double feedLatencyCount) { - this.feedLatencyCount += feedLatencyCount; - } - - public void addQrQueryLatencyCount(double qrQueryLatencyCount) { - this.qrQueryLatencyCount += qrQueryLatencyCount; - } - - public void addQrQueryLatencySum(double qrQueryLatencySum) { - this.qrQueryLatencySum += qrQueryLatencySum; - } - - public void addContainerQueryLatencyCount(double containerQueryLatencyCount) { - this.containerQueryLatencyCount += containerQueryLatencyCount; - } - - public void addContainerQueryLatencySum(double containerQueryLatencySum) { - this.containerQueryLatencySum += containerQueryLatencySum; - } - - public void addDocumentCount(double documentCount) { - this.documentCount += documentCount; - } - - public Optional aggregateFeedLatency() { - if (isZero(feedLatencySum) || isZero(feedLatencyCount)) return Optional.empty(); - return Optional.of(feedLatencySum / feedLatencyCount); - } - - public Optional aggregateFeedRate() { - if (isZero(feedLatencyCount)) return Optional.empty(); - return Optional.of(feedLatencyCount / 60); - } - - public Optional aggregateQueryLatency() { - if (isZero(containerQueryLatencyCount, containerQueryLatencySum) && isZero(qrQueryLatencyCount, qrQueryLatencySum)) return Optional.empty(); - return Optional.of((containerQueryLatencySum + qrQueryLatencySum) / (containerQueryLatencyCount + qrQueryLatencyCount)); - } - - public Optional aggregateQueryRate() { - if (isZero(containerQueryLatencyCount) && isZero(qrQueryLatencyCount)) return Optional.empty(); - return Optional.of((containerQueryLatencyCount + qrQueryLatencyCount) / 60); - } - - public Optional aggregateDocumentCount() { - if (isZero(documentCount)) return Optional.empty(); - return Optional.of(documentCount); - } - - public void setTimestamp(Instant timestamp) { - this.timestamp = timestamp; - } - - public Instant getTimestamp() { - return timestamp; - } - - private boolean isZero(double... values) { - boolean isZero = false; - for (double value : values) { - isZero |= Math.abs(value) < 0.001; - } - return isZero; - } - -} diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsAggregator.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsAggregator.java index b1a3d0601d7..9c8712c6f1e 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsAggregator.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsAggregator.java @@ -1,107 +1,90 @@ // Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.config.server.metrics; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.slime.ArrayTraverser; -import com.yahoo.slime.Inspector; -import com.yahoo.slime.Slime; -import com.yahoo.vespa.config.SlimeUtils; -import com.yahoo.vespa.config.server.http.v2.MetricsResponse; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.HttpClientBuilder; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.net.URI; import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.util.stream.Collectors; - +import java.util.Optional; /** * @author olaa */ public class MetricsAggregator { - private static final Logger logger = Logger.getLogger(MetricsAggregator.class.getName()); - HttpClient httpClient = HttpClientBuilder.create().build(); + double feedLatencySum; + double feedLatencyCount; + double qrQueryLatencySum; + double qrQueryLatencyCount; + double containerQueryLatencySum; + double containerQueryLatencyCount; + double documentCount; + Instant timestamp; + + public void addFeedLatencySum(double feedLatencySum) { + this.feedLatencySum += feedLatencySum; + } - public MetricsResponse aggregateAllMetrics(Map>> applicationHosts) { - Map> aggregatedMetrics = applicationHosts.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - e -> aggregateMetricsByCluster(e.getValue()))); - return new MetricsResponse(200, aggregatedMetrics); + public void addFeedLatencyCount(double feedLatencyCount) { + this.feedLatencyCount += feedLatencyCount; } - private Map aggregateMetricsByCluster(Map> clusterHosts) { - return clusterHosts.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - e -> aggregateMetrics(e.getValue()) - ) - ); + public void addQrQueryLatencyCount(double qrQueryLatencyCount) { + this.qrQueryLatencyCount += qrQueryLatencyCount; } - private Metrics aggregateMetrics(List hosts) { - Metrics clusterMetrics = new Metrics(); - hosts.stream() - .forEach(host -> accumulateMetrics(host, clusterMetrics)); - return clusterMetrics; + public void addQrQueryLatencySum(double qrQueryLatencySum) { + this.qrQueryLatencySum += qrQueryLatencySum; } - private void accumulateMetrics(URI hostURI, Metrics metrics) { - Slime responseBody = doMetricsRequest(hostURI); - Inspector services = responseBody.get().field("services"); - services.traverse((ArrayTraverser) (i, servicesInspector) -> { - parseService(servicesInspector, metrics); + public void addContainerQueryLatencyCount(double containerQueryLatencyCount) { + this.containerQueryLatencyCount += containerQueryLatencyCount; + } - }); + public void addContainerQueryLatencySum(double containerQueryLatencySum) { + this.containerQueryLatencySum += containerQueryLatencySum; + } + public void addDocumentCount(double documentCount) { + this.documentCount += documentCount; } - private Slime doMetricsRequest(URI hostURI) { - HttpGet get = new HttpGet(hostURI); - try { - HttpResponse response = httpClient.execute(get); - InputStream is = response.getEntity().getContent(); - Slime slime = SlimeUtils.jsonToSlime(is.readAllBytes()); - is.close(); - return slime; - } catch (IOException e) { - throw new UncheckedIOException(e); - } + public Optional aggregateFeedLatency() { + if (isZero(feedLatencySum) || isZero(feedLatencyCount)) return Optional.empty(); + return Optional.of(feedLatencySum / feedLatencyCount); + } + + public Optional aggregateFeedRate() { + if (isZero(feedLatencyCount)) return Optional.empty(); + return Optional.of(feedLatencyCount / 60); } - private void parseService(Inspector service, Metrics metrics) { - String serviceName = service.field("name").asString(); - Instant timestamp = Instant.ofEpochSecond(service.field("timestamp").asLong()); - metrics.setTimestamp(timestamp); - service.field("metrics").traverse((ArrayTraverser) (i, m) -> { - Inspector values = m.field("values"); - switch (serviceName) { - case "container": - metrics.addContainerQueryLatencyCount(values.field("query_latency.count").asDouble()); - metrics.addContainerQueryLatencySum(values.field("query_latency.sum").asDouble()); - metrics.addFeedLatencyCount(values.field("feed_latency.count").asDouble()); - metrics.addFeedLatencySum(values.field("feed_latency.sum").asDouble()); - case "qrserver": - metrics.addQrQueryLatencyCount(values.field("query_latency.count").asDouble()); - metrics.addQrQueryLatencySum(values.field("query_latency.sum").asDouble()); - case "distributor": - metrics.addDocumentCount(values.field("vds.distributor.docsstored.average").asDouble()); - } - }); + public Optional aggregateQueryLatency() { + if (isZero(containerQueryLatencyCount, containerQueryLatencySum) && isZero(qrQueryLatencyCount, qrQueryLatencySum)) return Optional.empty(); + return Optional.of((containerQueryLatencySum + qrQueryLatencySum) / (containerQueryLatencyCount + qrQueryLatencyCount)); + } + + public Optional aggregateQueryRate() { + if (isZero(containerQueryLatencyCount) && isZero(qrQueryLatencyCount)) return Optional.empty(); + return Optional.of((containerQueryLatencyCount + qrQueryLatencyCount) / 60); + } + public Optional aggregateDocumentCount() { + if (isZero(documentCount)) return Optional.empty(); + return Optional.of(documentCount); } - private void parseContainerMetrics(Inspector containerInspector, Metrics metrics) { + public void setTimestamp(Instant timestamp) { + this.timestamp = timestamp; + } + public Instant getTimestamp() { + return timestamp; + } + + private boolean isZero(double... values) { + boolean isZero = false; + for (double value : values) { + isZero |= Math.abs(value) < 0.001; + } + return isZero; } } diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsRetriever.java b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsRetriever.java new file mode 100644 index 00000000000..d305650a2bb --- /dev/null +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/metrics/MetricsRetriever.java @@ -0,0 +1,101 @@ +// Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.config.server.metrics; + +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.slime.ArrayTraverser; +import com.yahoo.slime.Inspector; +import com.yahoo.slime.Slime; +import com.yahoo.vespa.config.SlimeUtils; +import com.yahoo.vespa.config.server.http.v2.MetricsResponse; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URI; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Collectors; + + +/** + * @author olaa + */ +public class MetricsRetriever { + + private static final Logger logger = Logger.getLogger(MetricsRetriever.class.getName()); + HttpClient httpClient = HttpClientBuilder.create().build(); + + public MetricsResponse retrieveAllMetrics(Map>> applicationHosts) { + Map> allMetrics = applicationHosts.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> getMetricsByCluster(e.getValue()))); + return new MetricsResponse(200, allMetrics); + } + + private Map getMetricsByCluster(Map> clusterHosts) { + return clusterHosts.entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + e -> getClusterMetrics(e.getValue()) + ) + ); + } + + private MetricsAggregator getClusterMetrics(List hosts) { + MetricsAggregator clusterMetrics = new MetricsAggregator(); + hosts.stream() + .forEach(host -> getHostMetrics(host, clusterMetrics)); + return clusterMetrics; + } + + private void getHostMetrics(URI hostURI, MetricsAggregator metrics) { + Slime responseBody = doMetricsRequest(hostURI); + Inspector services = responseBody.get().field("services"); + services.traverse((ArrayTraverser) (i, servicesInspector) -> { + parseService(servicesInspector, metrics); + }); + } + + private Slime doMetricsRequest(URI hostURI) { + HttpGet get = new HttpGet(hostURI); + try { + HttpResponse response = httpClient.execute(get); + InputStream is = response.getEntity().getContent(); + Slime slime = SlimeUtils.jsonToSlime(is.readAllBytes()); + is.close(); + return slime; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private void parseService(Inspector service, MetricsAggregator metrics) { + String serviceName = service.field("name").asString(); + Instant timestamp = Instant.ofEpochSecond(service.field("timestamp").asLong()); + metrics.setTimestamp(timestamp); + service.field("metrics").traverse((ArrayTraverser) (i, m) -> { + Inspector values = m.field("values"); + switch (serviceName) { + case "container": + metrics.addContainerQueryLatencyCount(values.field("query_latency.count").asDouble()); + metrics.addContainerQueryLatencySum(values.field("query_latency.sum").asDouble()); + metrics.addFeedLatencyCount(values.field("feed_latency.count").asDouble()); + metrics.addFeedLatencySum(values.field("feed_latency.sum").asDouble()); + case "qrserver": + metrics.addQrQueryLatencyCount(values.field("query_latency.count").asDouble()); + metrics.addQrQueryLatencySum(values.field("query_latency.sum").asDouble()); + case "distributor": + metrics.addDocumentCount(values.field("vds.distributor.docsstored.average").asDouble()); + } + }); + + } + +} diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java index f1891430ccd..a843212927b 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/http/v2/ApplicationHandlerTest.java @@ -35,8 +35,6 @@ import java.io.File; import java.io.IOException; import java.net.URI; import java.time.Clock; -import java.util.logging.Level; -import java.util.logging.Logger; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsAggregatorTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsAggregatorTest.java deleted file mode 100644 index f317322343f..00000000000 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsAggregatorTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.yahoo.vespa.config.server.metrics; - -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import com.yahoo.config.provision.ApplicationId; -import com.yahoo.vespa.config.server.http.v2.MetricsResponse; -import org.junit.Rule; -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static org.junit.Assert.*; - - -/** - * @author olaa - */ -public class MetricsAggregatorTest { - - @Rule - public final WireMockRule wireMock = new WireMockRule(options().port(8080), true); - - @Test - public void testMetricAggregation() throws IOException { - MetricsAggregator metricsAggregator = new MetricsAggregator(); - - ApplicationId applicationId = ApplicationId.from("tenant", "app", "default"); - Map> clusterHosts = Map.of( - "cluster1", List.of(URI.create("http://localhost:8080/1"), URI.create("http://localhost:8080/2")), - "cluster2", List.of(URI.create("http://localhost:8080/3")) - ); - Map>> applications = Map.of(applicationId, clusterHosts); - - stubFor(get(urlEqualTo("/1")) - .willReturn(aResponse() - .withStatus(200) - .withBody(metricsString(10,20,33,40,50)))); - - stubFor(get(urlEqualTo("/2")) - .willReturn(aResponse() - .withStatus(200) - .withBody(metricsString(1,2,3,4,5)))); - - stubFor(get(urlEqualTo("/3")) - .willReturn(aResponse() - .withStatus(200) - .withBody(metricsString(1,2,3,4,5)))); - - MetricsResponse metricsResponse = metricsAggregator.aggregateAllMetrics(applications); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - metricsResponse.render(bos); - String expectedResponse = "[\n" + - " {\n" + - " \"applicationId\": \"tenant:app:default\",\n" + - " \"clusters\": [\n" + - " {\n" + - " \"clusterName\": \"cluster1\",\n" + - " \"queriesPerSecond\": 2.8666666666666667,\n" + - " \"writesPerSecond\": 1.4333333333333333,\n" + - " \"documentCount\": 6000.0,\n" + - " \"queryLatencyMillis\": 116.27906976744185,\n" + - " \"feedLatency\": 69.76744186046511,\n" + - " \"timestamp\": 1557306075\n" + - " },\n" + - " {\n" + - " \"clusterName\": \"cluster2\",\n" + - " \"queriesPerSecond\": 1.4333333333333333,\n" + - " \"writesPerSecond\": 0.7166666666666667,\n" + - " \"documentCount\": 3000.0,\n" + - " \"queryLatencyMillis\": 116.27906976744185,\n" + - " \"feedLatency\": 69.76744186046511,\n" + - " \"timestamp\": 1557306075\n" + - " }\n" + - " ]\n" + - " }\n" + - "]\n"; - assertEquals(expectedResponse, bos.toString()); - wireMock.stop(); - } - - private String metricsString(double queriesPerSecond, double writesPerSecond, double documentCount, double queryLatencyMillis, double writeLatencyMills) throws IOException { - String responseBody = Files.readString(Path.of("src/test/resources/metrics_response")); - return String.format(responseBody, queriesPerSecond, writesPerSecond, documentCount, queryLatencyMillis, writeLatencyMills); - } -} \ No newline at end of file diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsRetrieverTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsRetrieverTest.java new file mode 100644 index 00000000000..e296b3a44c8 --- /dev/null +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/metrics/MetricsRetrieverTest.java @@ -0,0 +1,99 @@ +package com.yahoo.vespa.config.server.metrics; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.yahoo.config.provision.ApplicationId; +import com.yahoo.vespa.config.server.http.v2.MetricsResponse; +import org.junit.Rule; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; +import static org.junit.Assert.*; + + +/** + * @author olaa + */ +public class MetricsRetrieverTest { + + @Rule + public final WireMockRule wireMock = new WireMockRule(options().port(8080), true); + + @Test + public void testMetricAggregation() throws IOException { + MetricsRetriever metricsRetriever = new MetricsRetriever(); + + ApplicationId applicationId = ApplicationId.from("tenant", "app", "default"); + Map> clusterHosts = Map.of( + "cluster1", List.of(URI.create("http://localhost:8080/1"), URI.create("http://localhost:8080/2")), + "cluster2", List.of(URI.create("http://localhost:8080/3")) + ); + Map>> applications = Map.of(applicationId, clusterHosts); + + stubFor(get(urlEqualTo("/1")) + .willReturn(aResponse() + .withStatus(200) + .withBody(metricsString(10,20,33,40,50)))); + + stubFor(get(urlEqualTo("/2")) + .willReturn(aResponse() + .withStatus(200) + .withBody(metricsString(1,2,3,4,5)))); + + stubFor(get(urlEqualTo("/3")) + .willReturn(aResponse() + .withStatus(200) + .withBody(metricsString(1,2,3,4,5)))); + + MetricsResponse metricsResponse = metricsRetriever.retrieveAllMetrics(applications); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + metricsResponse.render(bos); + String expectedResponse = "[\n" + + " {\n" + + " \"applicationId\": \"tenant:app:default\",\n" + + " \"clusters\": [\n" + + " {\n" + + " \"clusterName\": \"cluster1\",\n" + + " \"metrics\": {\n" + + " \"queriesPerSecond\": 2.8666666666666667,\n" + + " \"writesPerSecond\": 1.4333333333333333,\n" + + " \"documentCount\": 6000.0,\n" + + " \"queryLatencyMillis\": 116.27906976744185,\n" + + " \"feedLatency\": 69.76744186046511\n" + + " },\n" + + " \"timestamp\": 1557306075\n" + + " },\n" + + " {\n" + + " \"clusterName\": \"cluster2\",\n" + + " \"metrics\": {\n" + + " \"queriesPerSecond\": 1.4333333333333333,\n" + + " \"writesPerSecond\": 0.7166666666666667,\n" + + " \"documentCount\": 3000.0,\n" + + " \"queryLatencyMillis\": 116.27906976744185,\n" + + " \"feedLatency\": 69.76744186046511\n" + + " },\n" + + " \"timestamp\": 1557306075\n" + + " }\n" + + " ]\n" + + " }\n" + + "]\n"; + assertEquals(expectedResponse, bos.toString()); + wireMock.stop(); + } + + private String metricsString(double queriesPerSecond, double writesPerSecond, double documentCount, double queryLatencyMillis, double writeLatencyMills) throws IOException { + String responseBody = Files.readString(Path.of("src/test/resources/metrics_response")); + return String.format(responseBody, queriesPerSecond, writesPerSecond, documentCount, queryLatencyMillis, writeLatencyMills); + } +} \ No newline at end of file diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java index dd390daaeb0..0cf89d798a7 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/DeploymentMetricsMaintainer.java @@ -97,7 +97,6 @@ public class DeploymentMetricsMaintainer extends Maintainer { } catch (InterruptedException e) { throw new RuntimeException(e); } - newMaintain(); } /** Get global rotation status for application */ @@ -121,14 +120,4 @@ public class DeploymentMetricsMaintainer extends Maintainer { } } - private void newMaintain() { - controller().zoneRegistry() - .zones() - .reachable() - .ids() - .stream() - .forEach(zoneId -> { - - }); - } } -- cgit v1.2.3