diff options
author | gjoranv <gv@verizonmedia.com> | 2019-12-14 03:43:20 +0100 |
---|---|---|
committer | gjoranv <gv@verizonmedia.com> | 2019-12-19 12:05:04 +0100 |
commit | 1a1762f3c5e34f81e0f33152de1f9633624e39ff (patch) | |
tree | 7afb523449998130704901239259c2cb9111cf3e /metrics-proxy/src | |
parent | 2a8ba2d5710bf139343356367f934f5d0d02b095 (diff) |
Allow conversion from GenericJsonModel to MetricsPackets
Diffstat (limited to 'metrics-proxy/src')
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 |