aboutsummaryrefslogtreecommitdiffstats
path: root/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java')
-rw-r--r--metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java152
1 files changed, 86 insertions, 66 deletions
diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
index 602879aa0b6..b5b8e30a218 100644
--- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
+++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java
@@ -5,21 +5,21 @@ import ai.vespa.metricsproxy.metric.model.ConsumerId;
import ai.vespa.metricsproxy.metric.model.MetricsPacket;
import ai.vespa.metricsproxy.metric.model.ServiceId;
import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.StreamWriteFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.yahoo.concurrent.CopyOnWriteHashMap;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import static ai.vespa.metricsproxy.http.ValuesFetcher.defaultMetricsConsumerId;
-import static com.yahoo.stream.CustomCollectors.toLinkedMap;
import static java.util.Collections.emptyList;
import static java.util.logging.Level.WARNING;
@@ -28,10 +28,12 @@ import static java.util.logging.Level.WARNING;
*/
public class YamasJsonUtil {
private static final Logger log = Logger.getLogger(YamasJsonUtil.class.getName());
+ private static final JsonFactory factory = JsonFactory.builder()
+ .enable(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN)
+ .build();
static final String YAMAS_ROUTING = "yamas";
- private static final Map<Set<ConsumerId>, Map<String, YamasJsonModel.YamasJsonNamespace>> globalNameSpaces = new CopyOnWriteHashMap<>();
public static MetricsPacket.Builder toMetricsPacketBuilder(YamasJsonModel jsonModel) {
if (jsonModel.application == null)
throw new IllegalArgumentException("Service id cannot be null");
@@ -45,21 +47,6 @@ public class YamasJsonUtil {
.addConsumers(jsonModel.getYamasConsumers());
}
- public static YamasArrayJsonModel toYamasArray(Collection<MetricsPacket> metricsPackets) {
- YamasArrayJsonModel yamasArray = toYamasArray(metricsPackets, false);
-
- // Add a single status object at the end
- yamasArray.metrics.stream().findFirst().map(YamasJsonModel::getYamasConsumers)
- .ifPresent(consumers -> yamasArray.add(getStatusYamasModel("Data collected successfully", 0, consumers)));
- return yamasArray;
- }
-
- public static YamasArrayJsonModel toYamasArray(Collection<MetricsPacket> metricsPackets, boolean addStatus) {
- YamasArrayJsonModel yamasArray = new YamasArrayJsonModel();
- metricsPackets.forEach(packet -> yamasArray.add(toYamasModel(packet, addStatus)));
- return yamasArray;
- }
-
/**
* Converts the given json formatted string to a list of metrics packet builders.
* Note that this method returns an empty list if an IOException occurs,
@@ -81,58 +68,91 @@ public class YamasJsonUtil {
}
}
- private static YamasJsonModel getStatusYamasModel(String statusMessage, int statusCode, Set<ConsumerId> consumers) {
- YamasJsonModel model = new YamasJsonModel();
- model.status_code = statusCode;
- model.status_msg = statusMessage;
- model.application = "yms_check_vespa";
- model.routing = computeIfAbsent(consumers);
- return model;
+ public static List<MetricsPacket> appendOptionalStatusPacket(List<MetricsPacket> packets) {
+ if (packets.isEmpty()) return packets;
+
+ Set<ConsumerId> consumers = extractSetForRouting(packets.get(0).consumers());
+ if (consumers.isEmpty()) return packets;
+ List<MetricsPacket> withStatus = new ArrayList<>(packets);
+ withStatus.add(new MetricsPacket.Builder(ServiceId.toServiceId("yms_check_vespa"))
+ .statusCode(0)
+ .statusMessage("Data collected successfully")
+ .addConsumers(consumers).build());
+ return withStatus;
}
- private static YamasJsonModel toYamasModel(MetricsPacket packet, boolean addStatus) {
- YamasJsonModel model = new YamasJsonModel();
-
- if (addStatus) {
- model.status_code = packet.statusCode;
- model.status_msg = packet.statusMessage;
+ public static String toJson(List<MetricsPacket> metrics, boolean addStatus) {
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
+ toJson(metrics, output, addStatus);
+ output.flush();
+ return output.toString();
+ } catch (IOException e) {
+ return "{}";
}
-
- model.application = packet.service.id;
- model.timestamp = (packet.timestamp == 0L) ? null : packet.timestamp;
-
- model.metrics = (packet.metrics().isEmpty())
- ? null
- : packet.metrics().entrySet().stream().collect(
- toLinkedMap(id2metric -> id2metric.getKey().id,
- id2metric -> id2metric.getValue().doubleValue()));
-
- model.dimensions = (packet.dimensions().isEmpty())
- ? null
- : packet.dimensions().entrySet()
- .stream()
- .filter(entry -> entry.getKey() != null && entry.getValue() != null)
- .collect(toLinkedMap(id2dim -> id2dim.getKey().id, Map.Entry::getValue));
-
- model.routing = computeIfAbsent(packet.consumers());
-
- return model;
}
-
- private static Map<String, YamasJsonModel.YamasJsonNamespace> computeIfAbsent(Set<ConsumerId> consumers) {
- return globalNameSpaces.computeIfAbsent(consumers, YamasJsonUtil::createYamasJson);
+ private static Set<ConsumerId> extractSetForRouting(Set<ConsumerId> consumers) {
+ return consumers.stream()
+ .filter(consumerId -> consumerId != defaultMetricsConsumerId)
+ .collect(Collectors.toSet());
+ }
+ public static void toJson(List<MetricsPacket> metrics, OutputStream outputStream, boolean addStatus) throws IOException {
+ JsonGenerator generator = factory.createGenerator(outputStream);
+ generator.writeStartObject();
+ if (metrics.isEmpty()) {
+ generator.writeEndObject();
+ return;
+ }
+ generator.writeArrayFieldStart("metrics");
+ for (int i = 0; i < metrics.size() - 1; i++) {
+ toJson(metrics.get(i), generator, addStatus);
+ }
+ toJson(metrics.get(metrics.size() - 1), generator, true);
+ generator.writeEndArray();
+ generator.writeEndObject();
+ generator.close();
}
- private static Map<String, YamasJsonModel.YamasJsonNamespace> createYamasJson(Set<ConsumerId> consumers) {
- List<String> namespaces = consumers.stream()
- .filter(consumerId -> consumerId != defaultMetricsConsumerId)
- .map(consumer -> consumer.id)
- .collect(Collectors.toList());
- if (namespaces.isEmpty()) return null;
+ private static void toJson(MetricsPacket metric, JsonGenerator generator, boolean addStatus) throws IOException {
+ generator.writeStartObject();
+ if (addStatus) {
+ generator.writeNumberField("status_code", metric.statusCode);
+ }
+ if (metric.timestamp != 0) {
+ generator.writeNumberField("timestamp", metric.timestamp);
+ }
+ generator.writeStringField("application", metric.service.id);
- YamasJsonModel.YamasJsonNamespace yamasJsonNamespace = new YamasJsonModel.YamasJsonNamespace();
- yamasJsonNamespace.namespaces = namespaces;
- return Map.of(YAMAS_ROUTING, yamasJsonNamespace);
- }
+ if ( ! metric.metrics().isEmpty()) {
+ generator.writeObjectFieldStart("metrics");
+ for (var m : metric.metrics().entrySet()) {
+ generator.writeFieldName(m.getKey().id);
+ JacksonUtil.writeDouble(generator, m.getValue().doubleValue());
+ }
+ generator.writeEndObject();
+ }
+ if ( ! metric.dimensions().isEmpty()) {
+ generator.writeObjectFieldStart("dimensions");
+ for (var m : metric.dimensions().entrySet()) {
+ generator.writeStringField(m.getKey().id, m.getValue());
+ }
+ generator.writeEndObject();
+ }
+ Set<ConsumerId> routing = extractSetForRouting(metric.consumers());
+ if (!routing.isEmpty()) {
+ generator.writeObjectFieldStart("routing");
+ generator.writeObjectFieldStart(YAMAS_ROUTING);
+ generator.writeArrayFieldStart("namespaces");
+ for (ConsumerId consumer : routing) {
+ generator.writeString(consumer.id);
+ }
+ generator.writeEndArray();
+ generator.writeEndObject();
+ generator.writeEndObject();
+ }
+ if (addStatus) {
+ generator.writeStringField("status_msg", metric.statusMessage);
+ }
+ generator.writeEndObject();
+ }
}