summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgjoranv <gv@verizonmedia.com>2019-05-28 20:28:22 +0200
committerGitHub <noreply@github.com>2019-05-28 20:28:22 +0200
commit566e6fece1717a03af4f03eeadb50abff3d13031 (patch)
tree5b8a62e6526efdc0a0791b208f4ba5482408739d
parent4f789ec7057a8aaa1340dd470b0d33e238384af0 (diff)
parent2adca76e13e14e0c3c56c152ede68f7fb9cde414 (diff)
Merge pull request #9597 from vespa-engine/gjoranv/generic-metrics-model
Gjoranv/generic metrics model
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/ExternalMetrics.java2
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModel.java45
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java52
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericMetrics.java43
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java36
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java64
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JacksonUtil.java47
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasArrayJsonModel.java27
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java (renamed from metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonUtil.java)4
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/rpc/RpcServer.java7
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/TestUtil.java2
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java87
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java4
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java (renamed from metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonUtilTest.java)12
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcHealthMetricsTest.java8
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcMetricsTest.java4
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/ContainerServiceTest.java4
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/MetricsFetcherTest.java4
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/VespaServiceTest.java6
-rw-r--r--metrics-proxy/src/test/resources/generic-sample.json50
20 files changed, 451 insertions, 57 deletions
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/ExternalMetrics.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/ExternalMetrics.java
index 62465909798..26ae177d767 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/ExternalMetrics.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/ExternalMetrics.java
@@ -39,7 +39,7 @@ public class ExternalMetrics {
public static final DimensionId STATE_DIMENSION = toDimensionId("state");
public static final DimensionId ORCHESTRATOR_STATE_DIMENSION = toDimensionId("orchestratorState");
- static final ServiceId VESPA_NODE_SERVICE_ID = toServiceId("vespa.node");
+ public static final ServiceId VESPA_NODE_SERVICE_ID = toServiceId("vespa.node");
private volatile List<MetricsPacket.Builder> metrics = new ArrayList<>();
private final MetricsConsumers consumers;
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModel.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModel.java
new file mode 100644
index 00000000000..dd8858ff99e
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModel.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
+
+/**
+ * @author gjoranv
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(NON_ABSENT)
+@JsonPropertyOrder({ "node", "services" })
+public class GenericJsonModel {
+ private static Logger log = Logger.getLogger(GenericJsonModel.class.getName());
+
+ @JsonProperty("node")
+ public GenericNode node;
+
+ @JsonProperty("services")
+ public List<GenericService> services;
+
+ public String serialize() {
+ ObjectMapper mapper = JacksonUtil.createObjectMapper();
+ try {
+ return mapper.writeValueAsString(this);
+ } catch (IOException e) {
+ log.log(Level.WARNING, "Got exception when rendering metrics:", e);
+ throw new RuntimeException("Could not render metrics. Check the log for details.");
+ }
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java
new file mode 100644
index 00000000000..495e3ec1f7d
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import ai.vespa.metricsproxy.metric.model.MetricsPacket;
+import ai.vespa.metricsproxy.metric.model.ServiceId;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static ai.vespa.metricsproxy.metric.ExternalMetrics.VESPA_NODE_SERVICE_ID;
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Utilities for converting between metrics packets and the generic json format.
+ *
+ * @author gjoranv
+ */
+public class GenericJsonUtil {
+
+ private GenericJsonUtil() { }
+
+ public static GenericJsonModel toGenericJsonModel(List<MetricsPacket> metricsPackets) {
+ Map<ServiceId, List<MetricsPacket>> packetsByService = metricsPackets.stream()
+ .collect(Collectors.groupingBy(packet -> packet.service));
+
+ var jsonModel = new GenericJsonModel();
+ var genericServices = new ArrayList<GenericService>();
+ packetsByService.forEach((serviceId, packets) -> {
+ var genericMetricsList = packets.stream()
+ .map(packet -> new GenericMetrics(packet.metrics(), packet.dimensions()))
+ .collect(toList());
+ var genericService = new GenericService(serviceId.id,
+ packets.get(0).timestamp,
+ genericMetricsList);
+ if (VESPA_NODE_SERVICE_ID.equals(serviceId)) {
+ jsonModel.node = new GenericNode(genericService.timestamp, genericService.metrics);
+ } else {
+ genericServices.add(genericService);
+
+ }
+ });
+
+ jsonModel.services = genericServices;
+ return jsonModel;
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericMetrics.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericMetrics.java
new file mode 100644
index 00000000000..46f515bfb47
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericMetrics.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import ai.vespa.metricsproxy.metric.model.DimensionId;
+import ai.vespa.metricsproxy.metric.model.MetricId;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.google.common.base.Functions;
+import com.yahoo.stream.CustomCollectors;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
+import static com.yahoo.stream.CustomCollectors.toLinkedMap;
+
+/**
+ * @author gjoranv
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(NON_ABSENT)
+@JsonPropertyOrder({ "values", "dimensions" })
+public class GenericMetrics {
+
+ @JsonProperty("values")
+ public Map<String, Double> values;
+
+ @JsonProperty("dimensions")
+ public Map<String, String> dimensions;
+
+ public GenericMetrics() { }
+
+ GenericMetrics(Map<MetricId, Number> values, Map<DimensionId, String> dimensions) {
+ this.values = values.entrySet().stream().collect(toLinkedMap(entry -> entry.getKey().id, entry -> entry.getValue().doubleValue()));
+ this.dimensions = dimensions.entrySet().stream().collect(toLinkedMap(entry -> entry.getKey().id, Map.Entry::getValue));
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java
new file mode 100644
index 00000000000..6b6f8d4d9cb
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.util.List;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
+
+/**
+ * @author gjoranv
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(NON_ABSENT)
+@JsonPropertyOrder({ "timestamp", "metrics" })
+public class GenericNode {
+
+ @JsonProperty("timestamp")
+ public Long timestamp;
+
+ @JsonProperty("metrics")
+ public List<GenericMetrics> metrics;
+
+ public GenericNode() { }
+
+ GenericNode(Long timestamp, List<GenericMetrics> metrics) {
+ this.timestamp = timestamp;
+ this.metrics = metrics;
+ }
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java
new file mode 100644
index 00000000000..bd3dbf935ed
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
+import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY;
+
+/**
+ * @author gjoranv
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(NON_ABSENT)
+@JsonPropertyOrder({ "name", "timestamp", "status", "metrics" })
+public class GenericService {
+
+ @JsonProperty("name")
+ public String name;
+
+ @JsonProperty("timestamp")
+ public Long timestamp;
+
+ @JsonProperty("status")
+ public Status status;
+
+ @JsonProperty("metrics")
+ public List<GenericMetrics> metrics;
+
+ public GenericService() { }
+
+ GenericService(String name, Long timestamp, List<GenericMetrics> metrics) {
+ this.name = name;
+ this.timestamp = timestamp;
+ status = new Status("up");
+ this.metrics = metrics;
+ }
+
+
+ @JsonInclude(NON_EMPTY)
+ @JsonPropertyOrder({ "code", "description" })
+ public static class Status {
+ public Status() { }
+
+ Status(String code) {
+ this.code = code;
+ }
+
+ @JsonProperty("code")
+ public String code;
+
+ @JsonProperty("description")
+ public String description;
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JacksonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JacksonUtil.java
new file mode 100644
index 00000000000..5c04f933c4a
--- /dev/null
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JacksonUtil.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+/**
+ * @author smorgrav
+ * @author gjoranv
+ */
+class JacksonUtil {
+
+ /**
+ * Returns an object mapper with a custom floating point serializer to avoid scientific notation
+ */
+ static ObjectMapper createObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule("DoubleSerializer",
+ new Version(1, 0, 0, "", null, null));
+ module.addSerializer(Double.class, new DoubleSerializer());
+ mapper.registerModule(module);
+ return mapper;
+ }
+
+ public static class DoubleSerializer extends JsonSerializer<Double> {
+ @Override
+ public void serialize(Double value, JsonGenerator jgen,
+ SerializerProvider provider) throws IOException {
+ DecimalFormat df = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.ENGLISH));
+ df.setMaximumFractionDigits(13);
+ jgen.writeNumber(df.format(value));
+ }
+ }
+
+}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasArrayJsonModel.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasArrayJsonModel.java
index fdac0521256..86249ba6e31 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasArrayJsonModel.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasArrayJsonModel.java
@@ -7,20 +7,11 @@ package ai.vespa.metricsproxy.metric.model.json;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.Version;
-import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-import java.io.IOException;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
/**
* Datamodel for the metricsproxy representation of multiple yamas checks.
@@ -51,11 +42,7 @@ public class YamasArrayJsonModel {
* @return Serialized json
*/
public String serialize() {
- ObjectMapper mapper = new ObjectMapper();
- SimpleModule module = new SimpleModule("DoubleSerializer",
- new Version(1, 0, 0, "", null, null));
- module.addSerializer(Double.class, new DoubleSerializer());
- mapper.registerModule(module);
+ ObjectMapper mapper = JacksonUtil.createObjectMapper();
if (metrics.size() > 0) {
try {
@@ -64,17 +51,7 @@ public class YamasArrayJsonModel {
e.printStackTrace();
}
}
-
- return "{}"; // Backwards compatability
+ return "{}"; // Backwards compatibility
}
- public class DoubleSerializer extends JsonSerializer<Double> {
- @Override
- public void serialize(Double value, JsonGenerator jgen,
- SerializerProvider provider) throws IOException, JsonProcessingException {
- DecimalFormat df = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.ENGLISH));
- df.setMaximumFractionDigits(13);
- jgen.writeNumber(df.format(value));
- }
- }
}
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
index f48e5759528..7c1539d1c55 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/JsonUtil.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
@@ -27,8 +27,8 @@ import static java.util.logging.Level.WARNING;
/**
* @author gjoranv
*/
-public class JsonUtil {
- private static final Logger log = Logger.getLogger(JsonUtil.class.getName());
+public class YamasJsonUtil {
+ private static final Logger log = Logger.getLogger(YamasJsonUtil.class.getName());
static final String YAMAS_ROUTING = "yamas";
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/rpc/RpcServer.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/rpc/RpcServer.java
index e0e0e7a3f87..7157e3c40a0 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/rpc/RpcServer.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/rpc/RpcServer.java
@@ -12,10 +12,7 @@ import ai.vespa.metricsproxy.service.VespaServices;
import com.yahoo.jrt.ErrorCode;
import com.yahoo.jrt.Method;
import com.yahoo.jrt.Request;
-import com.yahoo.jrt.Spec;
import com.yahoo.jrt.StringValue;
-import com.yahoo.jrt.Supervisor;
-import com.yahoo.jrt.Transport;
import java.time.Instant;
import java.util.List;
@@ -23,8 +20,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import static ai.vespa.metricsproxy.metric.model.ConsumerId.toConsumerId;
-import static ai.vespa.metricsproxy.metric.model.json.JsonUtil.toMetricsPackets;
-import static ai.vespa.metricsproxy.metric.model.json.JsonUtil.toYamasArray;
+import static ai.vespa.metricsproxy.metric.model.json.YamasJsonUtil.toMetricsPackets;
+import static ai.vespa.metricsproxy.metric.model.json.YamasJsonUtil.toYamasArray;
import static com.yahoo.collections.CollectionUtil.mkString;
import static com.yahoo.log.LogLevel.DEBUG;
import static java.util.logging.Level.INFO;
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/TestUtil.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/TestUtil.java
index 5997f85a46f..e18bd38f97a 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/TestUtil.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/TestUtil.java
@@ -17,7 +17,7 @@ import java.util.stream.Collectors;
*/
public class TestUtil {
- public static String getContents(String filename) {
+ public static String getFileContents(String filename) {
InputStream in = TestUtil.class.getClassLoader().getResourceAsStream(filename);
if (in == null) {
throw new RuntimeException("File not found: " + filename);
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java
new file mode 100644
index 00000000000..44fe383839f
--- /dev/null
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+ */
+
+package ai.vespa.metricsproxy.metric.model.json;
+
+import ai.vespa.metricsproxy.metric.model.MetricsPacket;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.List;
+
+import static ai.vespa.metricsproxy.TestUtil.getFileContents;
+import static ai.vespa.metricsproxy.metric.ExternalMetrics.VESPA_NODE_SERVICE_ID;
+import static ai.vespa.metricsproxy.metric.model.DimensionId.toDimensionId;
+import static ai.vespa.metricsproxy.metric.model.MetricId.toMetricId;
+import static ai.vespa.metricsproxy.metric.model.ServiceId.toServiceId;
+import static ai.vespa.metricsproxy.metric.model.json.JacksonUtil.createObjectMapper;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author gjoranv
+ */
+public class GenericJsonModelTest {
+ private static final String TEST_FILE = "generic-sample.json";
+
+ @Test
+ public void deserialize_serialize_roundtrip() throws IOException {
+ GenericJsonModel jsonModel = genericJsonModelFromTestFile();
+
+ // Do some sanity checking
+ assertEquals(2, jsonModel.services.size());
+ assertEquals(2, jsonModel.node.metrics.size());
+ assertEquals(16.222, jsonModel.node.metrics.get(0).values.get("cpu.util"), 0.01d);
+
+ String expected = getFileContents(TEST_FILE).trim().replaceAll("\\s+", "");;
+
+ String serialized = jsonModel.serialize();
+ String trimmed = serialized.trim().replaceAll("\\s+", "");
+
+ assertEquals(expected, trimmed);
+ }
+
+ @Test
+ public void metrics_packets_can_be_converted_to_generic_json_model() throws Exception {
+ var nodePacket = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
+ .timestamp(123456L)
+ .putMetric(toMetricId("node-metric"), 1.234)
+ .putDimension(toDimensionId("node-dim"), "node-dim-value")
+ .build();
+
+ var servicePacket = new MetricsPacket.Builder(toServiceId("my-service"))
+ .timestamp(123456L)
+ .putMetric(toMetricId("service-metric"), 1234)
+ .putDimension(toDimensionId("service-dim"), "service-dim-value")
+ .build();
+
+ var metricsPackets = List.of(servicePacket, nodePacket);
+
+ GenericJsonModel jsonModel = GenericJsonUtil.toGenericJsonModel(metricsPackets);
+
+ assertNotNull(jsonModel.node);
+ assertEquals(1, jsonModel.node.metrics.size());
+ GenericMetrics nodeMetrics = jsonModel.node.metrics.get(0);
+ assertEquals(1.234, jsonModel.node.metrics.get(0).values.get("node-metric"), 0.001d);
+ assertEquals("node-dim-value", nodeMetrics.dimensions.get("node-dim"));
+
+ assertEquals(1, jsonModel.services.size());
+ GenericService service = jsonModel.services.get(0);
+ assertEquals(1, service.metrics.size());
+ GenericMetrics serviceMetrics = service.metrics.get(0);
+ assertEquals(1234L, serviceMetrics.values.get("service-metric").longValue());
+ assertEquals("service-dim-value", serviceMetrics.dimensions.get("service-dim"));
+
+ // Visual inspection
+ System.out.println(createObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(jsonModel));
+ }
+
+
+ private GenericJsonModel genericJsonModelFromTestFile() throws IOException {
+ ObjectMapper mapper = createObjectMapper();
+ return mapper.readValue(getFileContents(TEST_FILE), GenericJsonModel.class);
+ }
+
+}
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java
index e91ff32e3b4..a73d15e8be3 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java
@@ -59,7 +59,7 @@ public class YamasJsonModelTest {
@Test
public void deserialize_serialize_roundtrip_with_metrics_packet() throws IOException {
YamasJsonModel jsonModel = getYamasJsonModel("yamas-array.json");
- MetricsPacket metricsPacket = JsonUtil.toMetricsPacketBuilder(jsonModel).build();
+ MetricsPacket metricsPacket = YamasJsonUtil.toMetricsPacketBuilder(jsonModel).build();
// Do some sanity checking
assertEquals(toServiceId("vespa.searchnode"), metricsPacket.service);
@@ -67,7 +67,7 @@ public class YamasJsonModelTest {
assertEquals(5.555555555E9, metricsPacket.metrics().get(toMetricId("memory_rss")).doubleValue(), 0.1d); //Not using custom double rendrer
// Serialize and verify
- YamasArrayJsonModel yamasArray = JsonUtil.toYamasArray(Collections.singleton(metricsPacket), true);
+ YamasArrayJsonModel yamasArray = YamasJsonUtil.toYamasArray(Collections.singleton(metricsPacket), true);
String string = yamasArray.serialize();
assertEquals(EXPECTED_JSON, string);
}
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonUtilTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java
index 28912293fdb..b5b5ba9eaa5 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/JsonUtilTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java
@@ -10,7 +10,7 @@ import org.junit.Test;
import java.util.List;
import static ai.vespa.metricsproxy.metric.model.ServiceId.toServiceId;
-import static ai.vespa.metricsproxy.metric.model.json.JsonUtil.toMetricsPackets;
+import static ai.vespa.metricsproxy.metric.model.json.YamasJsonUtil.toMetricsPackets;
import static java.util.Collections.singleton;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -19,12 +19,12 @@ import static org.junit.Assert.assertTrue;
/**
* @author gjoranv
*/
-public class JsonUtilTest {
+public class YamasJsonUtilTest {
@Test
public void json_model_gets_null_status_by_default() {
MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo"))
.build();
- YamasJsonModel jsonModel = JsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
+ YamasJsonModel jsonModel = YamasJsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
assertNull(jsonModel.status_code);
assertNull(jsonModel.status_msg);
}
@@ -33,7 +33,7 @@ public class JsonUtilTest {
public void status_is_included_in_json_model_when_explicitly_asked_for() {
MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo"))
.build();
- YamasJsonModel jsonModel = JsonUtil.toYamasArray(singleton(packet), true).metrics.get(0);
+ YamasJsonModel jsonModel = YamasJsonUtil.toYamasArray(singleton(packet), true).metrics.get(0);
assertNotNull(jsonModel.status_code);
assertNotNull(jsonModel.status_msg);
}
@@ -43,7 +43,7 @@ public class JsonUtilTest {
MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo"))
.timestamp(0L)
.build();
- YamasJsonModel jsonModel = JsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
+ YamasJsonModel jsonModel = YamasJsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
assertNull(jsonModel.timestamp);
}
@@ -51,7 +51,7 @@ public class JsonUtilTest {
public void empty_consumers_is_translated_to_null_routing_in_json_model() {
MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo"))
.build();
- YamasJsonModel jsonModel = JsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
+ YamasJsonModel jsonModel = YamasJsonUtil.toYamasArray(singleton(packet)).metrics.get(0);
assertNull(jsonModel.routing);
}
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcHealthMetricsTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcHealthMetricsTest.java
index 20fb69e410e..c882de349c8 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcHealthMetricsTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcHealthMetricsTest.java
@@ -4,7 +4,6 @@
package ai.vespa.metricsproxy.rpc;
-import ai.vespa.metricsproxy.TestUtil;
import ai.vespa.metricsproxy.metric.HealthMetric;
import ai.vespa.metricsproxy.service.MockHttpServer;
import ai.vespa.metricsproxy.service.VespaService;
@@ -18,6 +17,7 @@ import org.junit.Test;
import java.util.List;
+import static ai.vespa.metricsproxy.TestUtil.getFileContents;
import static ai.vespa.metricsproxy.rpc.IntegrationTester.SERVICE_1_CONFIG_ID;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
@@ -30,11 +30,11 @@ import static org.junit.Assert.assertThat;
public class RpcHealthMetricsTest {
private static final String HEALTH_OK_RESPONSE =
- TestUtil.getContents("health-check.response.json");
+ getFileContents("health-check.response.json");
private static final String HEALTH_FAILED_RESPONSE =
- TestUtil.getContents("health-check-failed.response.json");
+ getFileContents("health-check-failed.response.json");
private static final String WANTED_RPC_RESPONSE =
- TestUtil.getContents("rpc-json-output-check.json").trim();
+ getFileContents("rpc-json-output-check.json").trim();
// see factory/doc/port-ranges.txt
private static final int httpPort = 18635;
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcMetricsTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcMetricsTest.java
index f264fd13ddc..6d1b4f3d3b7 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcMetricsTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/rpc/RpcMetricsTest.java
@@ -4,7 +4,6 @@
package ai.vespa.metricsproxy.rpc;
-import ai.vespa.metricsproxy.TestUtil;
import ai.vespa.metricsproxy.metric.Metric;
import ai.vespa.metricsproxy.metric.Metrics;
import ai.vespa.metricsproxy.metric.model.ConsumerId;
@@ -22,6 +21,7 @@ import org.junit.Test;
import java.util.List;
+import static ai.vespa.metricsproxy.TestUtil.getFileContents;
import static ai.vespa.metricsproxy.core.VespaMetrics.VESPA_CONSUMER_ID;
import static ai.vespa.metricsproxy.metric.model.DimensionId.toDimensionId;
import static ai.vespa.metricsproxy.rpc.IntegrationTester.CUSTOM_CONSUMER_ID;
@@ -42,7 +42,7 @@ import static org.junit.Assert.assertThat;
public class RpcMetricsTest {
private static final String METRICS_RESPONSE_CCL =
- TestUtil.getContents("metrics-storage-simple.json").trim();
+ getFileContents("metrics-storage-simple.json").trim();
// see factory/doc/port-ranges.txt
private static final int httpPort = 18633;
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/ContainerServiceTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/ContainerServiceTest.java
index 4174b18f3a7..0a84c03acec 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/ContainerServiceTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/ContainerServiceTest.java
@@ -4,7 +4,6 @@
package ai.vespa.metricsproxy.service;
-import ai.vespa.metricsproxy.TestUtil;
import ai.vespa.metricsproxy.metric.Metric;
import org.json.JSONException;
import org.junit.After;
@@ -12,6 +11,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import static ai.vespa.metricsproxy.TestUtil.getFileContents;
import static ai.vespa.metricsproxy.metric.model.DimensionId.toDimensionId;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@@ -33,7 +33,7 @@ public class ContainerServiceTest {
public void setupHTTPServer() {
csPort = 18637; // see factory/doc/port-ranges.txt
try {
- String response = TestUtil.getContents("metrics-container-state-multi-chain.json");
+ String response = getFileContents("metrics-container-state-multi-chain.json");
service = new MockHttpServer(csPort, response, HttpMetricFetcher.METRICS_PATH);
} catch (Exception e) {
e.printStackTrace();
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/MetricsFetcherTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/MetricsFetcherTest.java
index 27e1bb97943..278b2a3143a 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/MetricsFetcherTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/MetricsFetcherTest.java
@@ -8,8 +8,6 @@ import ai.vespa.metricsproxy.TestUtil;
import ai.vespa.metricsproxy.metric.Metrics;
import org.junit.Test;
-import java.io.File;
-
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@@ -21,7 +19,7 @@ public class MetricsFetcherTest {
@Test
public void testStateFormatMetricsParse() {
- String jsonData = TestUtil.getContents("metrics-state.json");
+ String jsonData = TestUtil.getFileContents("metrics-state.json");
RemoteMetricsFetcher fetcher = new RemoteMetricsFetcher(new DummyService(0, "dummy/id/0"), port);
Metrics metrics = fetcher.createMetrics(jsonData, 0);
assertThat("Wrong number of metrics", metrics.size(), is(10));
diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/VespaServiceTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/VespaServiceTest.java
index 13be98db23a..702f741c41f 100644
--- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/VespaServiceTest.java
+++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/service/VespaServiceTest.java
@@ -4,14 +4,12 @@
package ai.vespa.metricsproxy.service;
-import ai.vespa.metricsproxy.TestUtil;
import ai.vespa.metricsproxy.metric.Metrics;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import java.io.File;
-
+import static ai.vespa.metricsproxy.TestUtil.getFileContents;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@@ -24,7 +22,7 @@ public class VespaServiceTest {
private static final String response;
static {
- response = TestUtil.getContents("metrics-state.json");
+ response = getFileContents("metrics-state.json");
HttpMetricFetcher.CONNECTION_TIMEOUT = 60000; // 60 secs in unit tests
}
diff --git a/metrics-proxy/src/test/resources/generic-sample.json b/metrics-proxy/src/test/resources/generic-sample.json
new file mode 100644
index 00000000000..684b297e768
--- /dev/null
+++ b/metrics-proxy/src/test/resources/generic-sample.json
@@ -0,0 +1,50 @@
+{
+ "node": {
+ "timestamp": 1234,
+ "metrics": [
+ {
+ "values": {
+ "cpu.util": 16.222
+ },
+ "dimensions": {
+ "state": "active"
+ }
+ },
+ {
+ "values": {
+ "network.in.bytes": 123123123
+ },
+ "dimensions": {
+ "interface": "eth0"
+ }
+ }
+ ]
+ },
+ "services": [
+ {
+ "name": "searchnode",
+ "timestamp": 1234,
+ "status": {
+ "code": "up"
+ },
+ "metrics": [
+ {
+ "values": {
+ "queries.count": 4
+ },
+ "dimensions": {
+ "documentType": "music"
+ }
+ }
+ ]
+ },
+ {
+ "name": "slobrok",
+ "timestamp": 1234,
+ "status": {
+ "code": "unknown",
+ "description": "Unable to fetch metrics from service 'slobrok'"
+ }
+ }
+ ]
+} \ No newline at end of file