All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ai.vespa.metricsproxy.metric.model.json.GenericJsonUtil Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
// Copyright Vespa.ai. 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.http.application.Node;
import ai.vespa.metricsproxy.metric.model.MetricsPacket;
import ai.vespa.metricsproxy.metric.model.ServiceId;
import ai.vespa.metricsproxy.metric.model.StatusCode;

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.json.JacksonUtil.objectMapper;

import static java.util.logging.Level.WARNING;
import static java.util.stream.Collectors.toList;

/**
 * Utilities for converting between metrics packets and the generic json format.
 *
 * @author gjoranv
 */
public class GenericJsonUtil {
    private static final Logger log = Logger.getLogger(GenericJsonUtil.class.getName());

    private GenericJsonUtil() {
    }

    public static GenericApplicationModel toGenericApplicationModel(Map> metricsByNode) {
        var applicationModel = new GenericApplicationModel();

        var genericJsonModels = new ArrayList();
        metricsByNode.forEach(
                (node, metrics) -> genericJsonModels.add(toGenericJsonModel(metrics, node)));

        applicationModel.nodes = genericJsonModels;
        return applicationModel;
    }

    public static GenericJsonModel toGenericJsonModel(List metricsPackets) {
        return toGenericJsonModel(metricsPackets, null);
    }

    public static GenericJsonModel toGenericJsonModel(List metricsPackets, Node node) {
        Map> packetsByService = metricsPackets.stream()
                .collect(Collectors.groupingBy(MetricsPacket::service, LinkedHashMap::new, toList()));

        var jsonModel = new GenericJsonModel();
        if (node != null) {
            jsonModel.hostname = node.hostname;
            jsonModel.role = node.role;
        }

        var genericServices = new ArrayList();
        packetsByService.forEach((serviceId, packets) -> {
            var genericMetricsList = packets.stream()
                    .filter(packet -> ! (packet.metrics().isEmpty() && packet.dimensions().isEmpty()))
                    .map(packet -> new GenericMetrics(packet.metrics(), packet.dimensions()))
                    .toList();
            var genericService = packets.stream().findFirst()
                    .map(firstPacket -> new GenericService(serviceId.id,
                                                           firstPacket.timestamp(),
                                                           StatusCode.values()[firstPacket.statusCode()],
                                                           firstPacket.statusMessage(),
                                                           genericMetricsList))
                    .get();
            if (VESPA_NODE_SERVICE_ID.equals(serviceId)) {
                jsonModel.node = new GenericNode(genericService.timeAsInstant(), genericService.metrics);
            } else {
                genericServices.add(genericService);

            }
        });

        jsonModel.services = genericServices;
        return jsonModel;
    }

    public static List toMetricsPackets(String jsonString) {
        try {
            GenericJsonModel jsonModel = objectMapper().readValue(jsonString, GenericJsonModel.class);
            return toMetricsPackets(jsonModel);
        } catch (IOException e) {
            log.log(WARNING, "Could not create metrics packet from string:\n" + jsonString, e);
            return List.of();
        }
    }

    public static List toMetricsPackets(GenericJsonModel jsonModel) {
        var packets = toNodePackets(jsonModel.node);
        jsonModel.services.forEach(genericService -> packets.addAll(toServicePackets(genericService)));

        return packets;
    }

    private static List toNodePackets(GenericNode node) {
        List packets = new ArrayList<>();
        if (node == null) return packets;

        if (node.metrics == null || node.metrics.isEmpty()) {
            return List.of(new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
                                         .statusCode(StatusCode.UP.ordinal())
                                         .timestamp(node.timeAsInstant()));
        }

        for (var genericMetrics : node.metrics) {
            var packet = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID)
                    .statusCode(StatusCode.UP.ordinal())
                    .timestamp(node.timeAsInstant());
            addMetrics(genericMetrics, packet);
            packets.add(packet);
        }
        return packets;
    }

    private static List toServicePackets(GenericService service) {
        List packets = new ArrayList<>();
        if (service.metrics == null || service.metrics.isEmpty())
            return List.of(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(ServiceId.toServiceId(service.name))
                .statusCode(StatusCode.fromString(service.status.code).ordinal())
                .statusMessage(service.status.description)
                .timestamp(service.timeAsInstant());
    }

    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));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy