summaryrefslogtreecommitdiffstats
path: root/metrics-proxy
diff options
context:
space:
mode:
authorgjoranv <gv@verizonmedia.com>2019-12-14 03:43:20 +0100
committergjoranv <gv@verizonmedia.com>2019-12-19 12:05:04 +0100
commit1a1762f3c5e34f81e0f33152de1f9633624e39ff (patch)
tree7afb523449998130704901239259c2cb9111cf3e /metrics-proxy
parent2a8ba2d5710bf139343356367f934f5d0d02b095 (diff)
Allow conversion from GenericJsonModel to MetricsPackets
Diffstat (limited to 'metrics-proxy')
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java77
-rw-r--r--metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java44
-rw-r--r--metrics-proxy/src/test/resources/generic-sample.json10
3 files changed, 124 insertions, 7 deletions
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
index aadcc1418af..363077d28b7 100644
--- 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
@@ -7,13 +7,24 @@ package ai.vespa.metricsproxy.metric.model.json;
import ai.vespa.metricsproxy.metric.model.MetricsPacket;
import ai.vespa.metricsproxy.metric.model.ServiceId;
import ai.vespa.metricsproxy.metric.model.StatusCode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.logging.Logger;
import java.util.stream.Collectors;
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 java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.logging.Level.WARNING;
import static java.util.stream.Collectors.toList;
/**
@@ -22,17 +33,19 @@ import static java.util.stream.Collectors.toList;
* @author gjoranv
*/
public class GenericJsonUtil {
+ private static final Logger log = Logger.getLogger(GenericJsonUtil.class.getName());
private GenericJsonUtil() { }
public static GenericJsonModel toGenericJsonModel(List<MetricsPacket> metricsPackets) {
Map<ServiceId, List<MetricsPacket>> packetsByService = metricsPackets.stream()
- .collect(Collectors.groupingBy(packet -> packet.service));
+ .collect(Collectors.groupingBy(packet -> packet.service, LinkedHashMap::new, toList()));
var jsonModel = new GenericJsonModel();
var genericServices = new ArrayList<GenericService>();
packetsByService.forEach((serviceId, packets) -> {
var genericMetricsList = packets.stream()
+ .filter(packet -> ! (packet.metrics().isEmpty() && packet.dimensions().isEmpty()))
.map(packet -> new GenericMetrics(packet.metrics(), packet.dimensions()))
.collect(toList());
var genericService = packets.stream().findFirst()
@@ -54,4 +67,66 @@ public class GenericJsonUtil {
return jsonModel;
}
+ public static List<MetricsPacket.Builder> toMetricsPackets(String jsonString) {
+ try {
+ ObjectMapper mapper = createObjectMapper();
+ GenericJsonModel jsonModel = mapper.readValue(jsonString, GenericJsonModel.class);
+ return toMetricsPackets(jsonModel);
+ } catch (IOException e) {
+ log.log(WARNING, "Could not create metrics packet from string:\n" + jsonString, e);
+ return emptyList();
+ }
+ }
+
+ public static List<MetricsPacket.Builder> toMetricsPackets(GenericJsonModel jsonModel) {
+ var packets = toNodePackets(jsonModel.node);
+ jsonModel.services.forEach(genericService -> packets.addAll(toServicePackets(genericService)));
+
+ return packets;
+ }
+
+ private static List<MetricsPacket.Builder> toNodePackets(GenericNode node) {
+ List<MetricsPacket.Builder> packets = new ArrayList<>();
+ if (node.metrics == null || node.metrics.isEmpty()) {
+ return singletonList(new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
+ .statusCode(StatusCode.UP.ordinal())
+ .timestamp(node.timestamp));
+ }
+
+ for (var genericMetrics : node.metrics) {
+ var packet = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
+ .statusCode(StatusCode.UP.ordinal())
+ .timestamp(node.timestamp);
+ addMetrics(genericMetrics, packet);
+ packets.add(packet);
+ }
+ return packets;
+ }
+
+ private static List<MetricsPacket.Builder> toServicePackets(GenericService service) {
+ List<MetricsPacket.Builder> packets = new ArrayList<>();
+ if (service.metrics == null || service.metrics.isEmpty())
+ return singletonList(newServicePacket(service));
+
+ for (var genericMetrics : service.metrics) {
+ var packet = newServicePacket(service);
+ addMetrics(genericMetrics, packet);
+ packets.add(packet);
+ }
+ return packets;
+
+ }
+
+ private static MetricsPacket.Builder newServicePacket(GenericService service) {
+ return new MetricsPacket.Builder(toServiceId(service.name))
+ .statusCode(StatusCode.fromString(service.status.code).ordinal())
+ .statusMessage(service.status.description)
+ .timestamp(service.timestamp);
+ }
+
+ private static void addMetrics(GenericMetrics genericMetrics, MetricsPacket.Builder packet) {
+ genericMetrics.values.forEach((id, value) -> packet.putMetric(toMetricId(id), value));
+ genericMetrics.dimensions.forEach((id, value) -> packet.putDimension(toDimensionId(id), value));
+ }
+
}
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
index 5d248db8b18..ad11a82e547 100644
--- 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
@@ -18,9 +18,9 @@ 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 java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
/**
* @author gjoranv
@@ -37,12 +37,26 @@ public class GenericJsonModelTest {
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+", "");;
+ assertThatSerializedModelEqualsTestFile(jsonModel);
+ }
- String serialized = jsonModel.serialize();
- String trimmed = serialized.trim().replaceAll("\\s+", "");
+ @Test
+ public void deserialize_serialize_roundtrip_with_metrics_packets() throws IOException {
+ GenericJsonModel modelFromFile = genericJsonModelFromTestFile();
+ List<MetricsPacket> metricsPackets = GenericJsonUtil.toMetricsPackets(modelFromFile).stream()
+ .map(MetricsPacket.Builder::build)
+ .collect(toList());
- assertEquals(expected, trimmed);
+ assertEquals(4, metricsPackets.size());
+
+ GenericJsonModel modelFromPackets = GenericJsonUtil.toGenericJsonModel(metricsPackets);
+
+ // Do some sanity checking
+ assertEquals(2, modelFromFile.services.size());
+ assertEquals(2, modelFromFile.node.metrics.size());
+ assertEquals(16.222, modelFromFile.node.metrics.get(0).values.get("cpu.util"), 0.01d);
+
+ assertThatSerializedModelEqualsTestFile(modelFromPackets);
}
@Test
@@ -84,6 +98,26 @@ public class GenericJsonModelTest {
System.out.println(createObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(jsonModel));
}
+ @Test
+ public void generic_json_string_can_be_converted_to_metrics_packets() {
+ String genericJson = getFileContents(TEST_FILE);
+ List<MetricsPacket> metricsPackets = GenericJsonUtil.toMetricsPackets(genericJson).stream()
+ .map(MetricsPacket.Builder::build)
+ .collect(toList());
+
+ assertEquals(4, metricsPackets.size());
+ GenericJsonModel modelFromPackets = GenericJsonUtil.toGenericJsonModel(metricsPackets);
+
+ assertThatSerializedModelEqualsTestFile(modelFromPackets);
+ }
+
+ private void assertThatSerializedModelEqualsTestFile(GenericJsonModel modelFromPackets) {
+ String serialized = modelFromPackets.serialize();
+ String trimmed = serialized.trim().replaceAll("\\s+", "");
+
+ String expected = getFileContents(TEST_FILE).trim().replaceAll("\\s+", "");
+ assertEquals(expected, trimmed);
+ }
private GenericJsonModel genericJsonModelFromTestFile() throws IOException {
ObjectMapper mapper = createObjectMapper();
diff --git a/metrics-proxy/src/test/resources/generic-sample.json b/metrics-proxy/src/test/resources/generic-sample.json
index 684b297e768..de617895f86 100644
--- a/metrics-proxy/src/test/resources/generic-sample.json
+++ b/metrics-proxy/src/test/resources/generic-sample.json
@@ -44,7 +44,15 @@
"status": {
"code": "unknown",
"description": "Unable to fetch metrics from service 'slobrok'"
- }
+ },
+ "metrics": [
+ {
+ "values": {},
+ "dimensions": {
+ "instance": "slobrok0"
+ }
+ }
+ ]
}
]
} \ No newline at end of file