diff options
author | Ola Aunrønning <olaa@verizonmedia.com> | 2019-08-30 11:00:10 +0200 |
---|---|---|
committer | Ola Aunrønning <olaa@verizonmedia.com> | 2019-08-30 11:00:10 +0200 |
commit | 27de6084e585507dd0f253f4d20fcca9a9a325d4 (patch) | |
tree | 1ec629b57f4c9feea7924a9a606fd334e42cfbc2 /metrics-proxy/src/test | |
parent | 6d1f6a5589ae52e1c58fd9c28927562dbda3f468 (diff) | |
parent | c232a31df58fd153ff08b5a209556f4151861558 (diff) |
Merge branch 'gjoranv/prometheus-handler' of github.com:vespa-engine/vespa into metrics-proxy-gather-node-metrics
Diffstat (limited to 'metrics-proxy/src/test')
4 files changed, 220 insertions, 79 deletions
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java new file mode 100644 index 00000000000..bd6fba84e35 --- /dev/null +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java @@ -0,0 +1,100 @@ +/* + * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + */ + +package ai.vespa.metricsproxy.http; + +import ai.vespa.metricsproxy.TestUtil; +import ai.vespa.metricsproxy.core.ConsumersConfig; +import ai.vespa.metricsproxy.core.MetricsConsumers; +import ai.vespa.metricsproxy.core.MetricsManager; +import ai.vespa.metricsproxy.metric.HealthMetric; +import ai.vespa.metricsproxy.metric.Metric; +import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensions; +import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensionsConfig; +import ai.vespa.metricsproxy.metric.dimensions.NodeDimensions; +import ai.vespa.metricsproxy.metric.dimensions.NodeDimensionsConfig; +import ai.vespa.metricsproxy.metric.model.MetricsPacket; +import ai.vespa.metricsproxy.service.DownService; +import ai.vespa.metricsproxy.service.DummyService; +import ai.vespa.metricsproxy.service.VespaService; +import ai.vespa.metricsproxy.service.VespaServices; +import com.google.common.collect.ImmutableList; +import com.yahoo.container.jdisc.RequestHandlerTestDriver; + +import java.time.Instant; +import java.util.List; + +import static ai.vespa.metricsproxy.http.ValuesFetcher.DEFAULT_PUBLIC_CONSUMER_ID; +import static ai.vespa.metricsproxy.metric.ExternalMetrics.VESPA_NODE_SERVICE_ID; +import static ai.vespa.metricsproxy.service.DummyService.METRIC_1; + +/** + * Base class for http handler tests. + * + * @author gjoranv + */ +@SuppressWarnings("UnstableApiUsage") +public class HttpHandlerTestBase { + + protected static final List<VespaService> testServices = ImmutableList.of( + new DummyService(0, ""), + new DummyService(1, ""), + new DownService(HealthMetric.getDown("No response"))); + + protected static final VespaServices vespaServices = new VespaServices(testServices); + + protected static final String DEFAULT_CONSUMER = "default"; + protected static final String CUSTOM_CONSUMER = "custom-consumer"; + + protected static final String CPU_METRIC = "cpu"; + + protected static final String URI_BASE = "http://localhost"; + + protected static RequestHandlerTestDriver testDriver; + + + protected static MetricsManager getMetricsManager() { + MetricsManager metricsManager = TestUtil.createMetricsManager(vespaServices, getMetricsConsumers(), getApplicationDimensions(), getNodeDimensions()); + metricsManager.setExtraMetrics(ImmutableList.of( + new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) + .timestamp(Instant.now().getEpochSecond()) + .putMetrics(ImmutableList.of(new Metric(CPU_METRIC, 12.345))))); + return metricsManager; + } + + protected static MetricsConsumers getMetricsConsumers() { + var defaultConsumerDimension = new ConsumersConfig.Consumer.Metric.Dimension.Builder() + .key("consumer-dim").value("default-val"); + + var customConsumerDimension = new ConsumersConfig.Consumer.Metric.Dimension.Builder() + .key("consumer-dim").value("custom-val"); + + return new MetricsConsumers(new ConsumersConfig.Builder() + .consumer(new ConsumersConfig.Consumer.Builder() + .name(DEFAULT_PUBLIC_CONSUMER_ID.id) + .metric(new ConsumersConfig.Consumer.Metric.Builder() + .name(CPU_METRIC) + .outputname(CPU_METRIC)) + .metric(new ConsumersConfig.Consumer.Metric.Builder() + .name(METRIC_1) + .outputname(METRIC_1) + .dimension(defaultConsumerDimension))) + .consumer(new ConsumersConfig.Consumer.Builder() + .name(CUSTOM_CONSUMER) + .metric(new ConsumersConfig.Consumer.Metric.Builder() + .name(METRIC_1) + .outputname(METRIC_1) + .dimension(customConsumerDimension))) + .build()); + } + + protected static ApplicationDimensions getApplicationDimensions() { + return new ApplicationDimensions(new ApplicationDimensionsConfig.Builder().build()); + } + + protected static NodeDimensions getNodeDimensions() { + return new NodeDimensions(new NodeDimensionsConfig.Builder().build()); + } + +} diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java index 66220464e3e..83cd97bbeda 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/MetricsHandlerTest.java @@ -4,27 +4,11 @@ package ai.vespa.metricsproxy.http; -import ai.vespa.metricsproxy.TestUtil; -import ai.vespa.metricsproxy.core.ConsumersConfig; -import ai.vespa.metricsproxy.core.ConsumersConfig.Consumer; -import ai.vespa.metricsproxy.core.MetricsConsumers; -import ai.vespa.metricsproxy.core.MetricsManager; -import ai.vespa.metricsproxy.metric.HealthMetric; -import ai.vespa.metricsproxy.metric.Metric; -import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensions; -import ai.vespa.metricsproxy.metric.dimensions.ApplicationDimensionsConfig; -import ai.vespa.metricsproxy.metric.dimensions.NodeDimensions; -import ai.vespa.metricsproxy.metric.dimensions.NodeDimensionsConfig; -import ai.vespa.metricsproxy.metric.model.MetricsPacket; import ai.vespa.metricsproxy.metric.model.json.GenericJsonModel; import ai.vespa.metricsproxy.metric.model.json.GenericMetrics; import ai.vespa.metricsproxy.metric.model.json.GenericService; import ai.vespa.metricsproxy.service.DownService; -import ai.vespa.metricsproxy.service.DummyService; -import ai.vespa.metricsproxy.service.VespaService; -import ai.vespa.metricsproxy.service.VespaServices; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.ImmutableList; import com.yahoo.container.jdisc.RequestHandlerTestDriver; import org.json.JSONArray; import org.json.JSONObject; @@ -33,15 +17,11 @@ import org.junit.Ignore; import org.junit.Test; import java.io.IOException; -import java.time.Instant; -import java.util.List; import java.util.concurrent.Executors; import static ai.vespa.metricsproxy.core.VespaMetrics.INSTANCE_DIMENSION_ID; import static ai.vespa.metricsproxy.http.MetricsHandler.V1_PATH; import static ai.vespa.metricsproxy.http.MetricsHandler.VALUES_PATH; -import static ai.vespa.metricsproxy.http.ValuesFetcher.DEFAULT_PUBLIC_CONSUMER_ID; -import static ai.vespa.metricsproxy.metric.ExternalMetrics.VESPA_NODE_SERVICE_ID; import static ai.vespa.metricsproxy.metric.model.StatusCode.DOWN; import static ai.vespa.metricsproxy.metric.model.json.JacksonUtil.createObjectMapper; import static ai.vespa.metricsproxy.service.DummyService.METRIC_1; @@ -56,35 +36,17 @@ import static org.junit.Assert.fail; * @author gjoranv */ @SuppressWarnings("UnstableApiUsage") -public class MetricsHandlerTest { +public class MetricsHandlerTest extends HttpHandlerTestBase { - private static final List<VespaService> testServices = ImmutableList.of( - new DummyService(0, ""), - new DummyService(1, ""), - new DownService(HealthMetric.getDown("No response"))); - - private static final VespaServices vespaServices = new VespaServices(testServices); - - private static final String DEFAULT_CONSUMER = "default"; - private static final String CUSTOM_CONSUMER = "custom-consumer"; - - private static final String CPU_METRIC = "cpu"; - - private static final String URI_BASE = "http://localhost"; private static final String V1_URI = URI_BASE + V1_PATH; private static final String VALUES_URI = URI_BASE + VALUES_PATH; - - private static RequestHandlerTestDriver testDriver; - @BeforeClass public static void setup() { - MetricsManager metricsManager = TestUtil.createMetricsManager(vespaServices, getMetricsConsumers(), getApplicationDimensions(), getNodeDimensions()); - metricsManager.setExtraMetrics(ImmutableList.of( - new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) - .timestamp(Instant.now().getEpochSecond()) - .putMetrics(ImmutableList.of(new Metric(CPU_METRIC, 12.345))))); - MetricsHandler handler = new MetricsHandler(Executors.newSingleThreadExecutor(), metricsManager, vespaServices, getMetricsConsumers()); + MetricsHandler handler = new MetricsHandler(Executors.newSingleThreadExecutor(), + getMetricsManager(), + vespaServices, + getMetricsConsumers()); testDriver = new RequestHandlerTestDriver(handler); } @@ -113,7 +75,7 @@ public class MetricsHandlerTest { @Ignore @Test - public void visually_inspect_values_response() throws Exception{ + public void visually_inspect_values_response() throws Exception { String response = testDriver.sendRequest(VALUES_URI).readAll(); ObjectMapper mapper = createObjectMapper(); var jsonModel = mapper.readValue(response, GenericJsonModel.class); @@ -199,6 +161,13 @@ public class MetricsHandlerTest { assertEquals("custom-val", dummy1Metrics.dimensions.get("consumer-dim")); } + @Test + public void invalid_path_yields_error_response() throws Exception { + String response = testDriver.sendRequest(V1_URI + "/invalid").readAll(); + JSONObject root = new JSONObject(response); + assertTrue(root.has("error")); + } + private void assertDownServiceHealth(String consumer) { GenericJsonModel jsonModel = getResponseAsJsonModel(consumer); @@ -226,38 +195,4 @@ public class MetricsHandlerTest { throw new RuntimeException(); } - private static MetricsConsumers getMetricsConsumers() { - var defaultConsumerDimension = new Consumer.Metric.Dimension.Builder() - .key("consumer-dim").value("default-val"); - - var customConsumerDimension = new Consumer.Metric.Dimension.Builder() - .key("consumer-dim").value("custom-val"); - - return new MetricsConsumers(new ConsumersConfig.Builder() - .consumer(new Consumer.Builder() - .name(DEFAULT_PUBLIC_CONSUMER_ID.id) - .metric(new Consumer.Metric.Builder() - .name(CPU_METRIC) - .outputname(CPU_METRIC)) - .metric(new Consumer.Metric.Builder() - .name(METRIC_1) - .outputname(METRIC_1) - .dimension(defaultConsumerDimension))) - .consumer(new Consumer.Builder() - .name(CUSTOM_CONSUMER) - .metric(new Consumer.Metric.Builder() - .name(METRIC_1) - .outputname(METRIC_1) - .dimension(customConsumerDimension))) - .build()); - } - - private static ApplicationDimensions getApplicationDimensions() { - return new ApplicationDimensions(new ApplicationDimensionsConfig.Builder().build()); - } - - private static NodeDimensions getNodeDimensions() { - return new NodeDimensions(new NodeDimensionsConfig.Builder().build()); - } - } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java new file mode 100644 index 00000000000..69cdd9954e4 --- /dev/null +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + */ + +package ai.vespa.metricsproxy.http.prometheus; + +import ai.vespa.metricsproxy.http.HttpHandlerTestBase; +import ai.vespa.metricsproxy.service.DummyService; +import com.yahoo.container.jdisc.RequestHandlerTestDriver; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.concurrent.Executors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @author gjoranv + */ +@SuppressWarnings("UnstableApiUsage") +public class PrometheusHandlerTest extends HttpHandlerTestBase { + + private static final String V1_URI = URI_BASE + PrometheusHandler.V1_PATH; + private static final String VALUES_URI = URI_BASE + PrometheusHandler.VALUES_PATH; + + private static String valuesResponse; + + @BeforeClass + public static void setup() { + PrometheusHandler handler = new PrometheusHandler(Executors.newSingleThreadExecutor(), + getMetricsManager(), + vespaServices, + getMetricsConsumers()); + testDriver = new RequestHandlerTestDriver(handler); + valuesResponse = testDriver.sendRequest(VALUES_URI).readAll(); + } + + @Test + public void v1_response_contains_values_uri() throws Exception { + String response = testDriver.sendRequest(V1_URI).readAll(); + JSONObject root = new JSONObject(response); + assertTrue(root.has("resources")); + + JSONArray resources = root.getJSONArray("resources"); + assertEquals(1, resources.length()); + + JSONObject valuesUrl = resources.getJSONObject(0); + assertEquals(VALUES_URI, valuesUrl.getString("url")); + } + + @Ignore + @Test + public void visually_inspect_values_response() { + System.out.println(valuesResponse); + } + + @Test + public void response_contains_node_status() { + assertTrue(valuesResponse.contains("vespa_node_status 1.0")); + } + + @Test + public void response_contains_node_metrics() { + String cpu = getLine(valuesResponse, CPU_METRIC + "{"); + assertTrue(cpu.contains("} 12.345")); // metric value + assertTrue(cpu.contains("{vespaVersion=")); + } + + @Test + public void response_contains_service_status() { + assertTrue(valuesResponse.contains("vespa_dummy_status 1.0")); + assertTrue(valuesResponse.contains("vespa_down_service_status 0.0")); + } + + @Test + public void response_contains_service_metrics() { + String dummy0 = getLine(valuesResponse, DummyService.NAME + "0"); + assertTrue(dummy0.contains("c_test")); // metric name + assertTrue(dummy0.contains("} 1.0")); // metric value + } + + @Test + public void service_metrics_have_configured_dimensions() { + String dummy0 = getLine(valuesResponse, DummyService.NAME + "0"); + assertTrue(dummy0.contains("consumer_dim=\"default-val\"")); + } + + @Test + public void service_metrics_have_vespa_service_dimension() { + String dummy0 = getLine(valuesResponse, DummyService.NAME + "0"); + assertTrue(dummy0.contains("vespa_service=\"vespa_dummy\"")); + } + + // Find the first line that contains the given string + private String getLine(String raw, String searchString) { + for (var s : raw.split("\\n")) { + if (s.contains(searchString)) + return s; + } + throw new IllegalArgumentException("No line containing string: " + searchString); + } +} diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/DummyService.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/DummyService.java index 380a992aead..cf559628490 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/DummyService.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/DummyService.java @@ -11,7 +11,7 @@ import ai.vespa.metricsproxy.metric.Metrics; * @author Unknown */ public class DummyService extends VespaService { - static final String NAME = "dummy"; + public static final String NAME = "dummy"; public static final String METRIC_1 = "c.test"; public static final String METRIC_2 = "val"; |