com.yahoo.vespa.model.admin.monitoring.builder.xml.MetricsBuilder Maven / Gradle / Ivy
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.admin.monitoring.builder.xml;
import ai.vespa.metrics.set.Metric;
import ai.vespa.metrics.set.MetricSet;
import com.yahoo.config.model.ConfigModelContext.ApplicationType;
import com.yahoo.text.XML;
import com.yahoo.vespa.model.admin.monitoring.MetricsConsumer;
import com.yahoo.vespa.model.admin.monitoring.builder.Metrics;
import org.w3c.dom.Element;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static ai.vespa.metrics.set.DefaultVespaMetrics.defaultVespaMetricSet;
import static ai.vespa.metrics.set.SystemMetrics.systemMetricSet;
/**
* @author gjoranv
*/
public class MetricsBuilder {
private static final String ID_ATTRIBUTE = "id";
private static final String DISPLAY_NAME_ATTRIBUTE = "display-name";
private final ApplicationType applicationType;
private final Map availableMetricSets;
public MetricsBuilder(ApplicationType applicationType, Map availableMetricSets) {
this.applicationType = applicationType;
this.availableMetricSets = availableMetricSets;
}
public Metrics buildMetrics(Element metricsElement) {
Metrics metrics = new Metrics();
for (Element consumerElement : XML.getChildren(metricsElement, "consumer")) {
String consumerId = consumerElement.getAttribute(ID_ATTRIBUTE);
throwIfIllegalConsumerId(metrics, consumerId);
MetricSet metricSet = buildMetricSet(consumerId, consumerElement);
var consumer = new MetricsConsumer(consumerId, metricSet);
metrics.addConsumer(consumer);
}
return metrics;
}
private static Metric metricFromElement(Element elem) {
String m_id = elem.getAttribute(ID_ATTRIBUTE);
String m_dn = elem.getAttribute(DISPLAY_NAME_ATTRIBUTE);
if (m_dn == null || "".equals(m_dn)) {
return new Metric(m_id);
}
return new Metric(m_id, m_dn);
}
private MetricSet buildMetricSet(String consumerId, Element consumerElement) {
List metrics = XML.getChildren(consumerElement, "metric").stream()
.map(MetricsBuilder::metricFromElement)
.collect(Collectors.toCollection(LinkedList::new));
List metricSets = XML.getChildren(consumerElement, "metric-set").stream()
.map(metricSetElement -> getMetricSetOrThrow(metricSetElement.getAttribute(ID_ATTRIBUTE)))
.collect(Collectors.toCollection(LinkedList::new));
metricSets.add(defaultVespaMetricSet);
metricSets.add(systemMetricSet);
return new MetricSet(metricSetId(consumerId), metrics, metricSets);
}
private static String metricSetId(String consumerName) {
return "user-metrics-" + consumerName;
}
private MetricSet getMetricSetOrThrow(String id) {
if (! availableMetricSets.containsKey(id)) throw new IllegalArgumentException("No such metric-set: " + id);
return availableMetricSets.get(id);
}
private void throwIfIllegalConsumerId(Metrics metrics, String consumerId) {
if (consumerId.equalsIgnoreCase(MetricsConsumer.vespa.id()) && applicationType != ApplicationType.HOSTED_INFRASTRUCTURE)
throw new IllegalArgumentException("'Vespa' is not allowed as metrics consumer id (case is ignored.)");
if (consumerId.equalsIgnoreCase(MetricsConsumer.defaultConsumer.id()))
throw new IllegalArgumentException("'" + MetricsConsumer.defaultConsumer.id() + "' is not allowed as metrics consumer id (case is ignored.)");
if (consumerId.equalsIgnoreCase(MetricsConsumer.autoscaling.id()))
throw new IllegalArgumentException("'" + MetricsConsumer.autoscaling.id() + " is not allowed as metrics consumer id (case is ignored.)");
if (consumerId.equalsIgnoreCase(MetricsConsumer.vespaCloud.id()))
throw new IllegalArgumentException("'" + MetricsConsumer.vespaCloud.id() + " is not allowed as metrics consumer id (case is ignored.)");
if (metrics.hasConsumerIgnoreCase(consumerId))
throw new IllegalArgumentException("'" + consumerId + "' is used as id for two metrics consumers (case is ignored.)");
}
}