aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne H Juul <arnej27959@users.noreply.github.com>2024-04-18 16:52:13 +0200
committerGitHub <noreply@github.com>2024-04-18 16:52:13 +0200
commitb6e16d125c73aeaf974298fdf89c9e55132fb2ad (patch)
treea5cf7a354f646690bb48ad2d36287dac821493d6
parent328f0f15f8750753da31554d265d323cfa7d1fc2 (diff)
parent6dc58b99e12472ec864016db06969179326fb501 (diff)
Merge pull request #30964 from vespa-engine/arnej/use-json-as-yaml
generate JSON with state ports
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryCollector.java14
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGenerator.java214
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java22
4 files changed, 217 insertions, 35 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryCollector.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryCollector.java
index 73275a36804..fcd587622da 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryCollector.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryCollector.java
@@ -3,7 +3,9 @@ package com.yahoo.vespa.model.admin.otel;
import com.yahoo.cloud.config.OpenTelemetryConfig;
import com.yahoo.config.model.ApplicationConfigProducerRoot;
+import com.yahoo.config.model.deploy.DeployState;
import com.yahoo.config.model.producer.TreeConfigProducer;
+import com.yahoo.config.provision.Zone;
import com.yahoo.vespa.model.AbstractService;
import com.yahoo.vespa.model.PortAllocBridge;
@@ -14,8 +16,18 @@ import java.util.Optional;
public class OpenTelemetryCollector extends AbstractService implements OpenTelemetryConfig.Producer {
+ private final Zone zone;
+
public OpenTelemetryCollector(TreeConfigProducer<?> parent) {
super(parent, "otelcol");
+ this.zone = null;
+ setProp("clustertype", "admin");
+ setProp("clustername", "admin");
+ }
+
+ public OpenTelemetryCollector(TreeConfigProducer<?> parent, DeployState deployState) {
+ super(parent, "otelcol");
+ this.zone = deployState.zone();
setProp("clustertype", "admin");
setProp("clustername", "admin");
}
@@ -38,7 +50,7 @@ public class OpenTelemetryCollector extends AbstractService implements OpenTelem
@Override
public void getConfig(OpenTelemetryConfig.Builder builder) {
- var generator = new OpenTelemetryConfigGenerator();
+ var generator = new OpenTelemetryConfigGenerator(zone);
AnyConfigProducer pp = this;
AnyConfigProducer p = pp.getParent();
while (p != null && p != pp) {
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGenerator.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGenerator.java
index ebf692fd6ff..36eab6a04b3 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGenerator.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGenerator.java
@@ -1,58 +1,206 @@
// 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.otel;
+import com.fasterxml.jackson.core.JsonEncoding;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
import com.yahoo.config.model.ApplicationConfigProducerRoot.StatePortInfo;
+import com.yahoo.config.provision.Zone;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.List;
+import static com.yahoo.vespa.defaults.Defaults.getDefaults;
+
/**
* @author olaa
*/
public class OpenTelemetryConfigGenerator {
- // For now - just create dummy config
+ private final boolean useTls;
+ private final String ca_file;
+ private final String cert_file;
+ private final String key_file;
+ private List<StatePortInfo> statePorts = new ArrayList<>();
+
+ OpenTelemetryConfigGenerator(Zone zone) {
+ boolean isCd = true;
+ boolean isPublic = true;
+ if (zone != null) {
+ isCd = zone.system().isCd();
+ isPublic = zone.system().isPublic();
+ this.useTls = true;
+ } else {
+ // for manual testing
+ this.useTls = false;
+ }
+ if (isCd) {
+ if (isPublic) {
+ this.ca_file = "/opt/vespa/var/vespa/trust-store.pem";
+ this.cert_file = "/var/lib/sia/certs/vespa.external.cd.tenant.cert.pem";
+ this.key_file = "/var/lib/sia/keys/vespa.external.cd.tenant.key.pem";
+ } else {
+ this.ca_file = "/opt/yahoo/share/ssl/certs/athenz_certificate_bundle.pem";
+ this.cert_file = "/var/lib/sia/certs/vespa.vespa.cd.tenant.cert.pem";
+ this.key_file = "/var/lib/sia/keys/vespa.vespa.cd.tenant.key.pem";
+ }
+ } else {
+ if (isPublic) {
+ this.ca_file = "/opt/vespa/var/vespa/trust-store.pem";
+ this.cert_file = "/var/lib/sia/certs/vespa.external.tenant.cert.pem";
+ this.key_file = "/var/lib/sia/keys/vespa.external.tenant.key.pem";
+ } else {
+ this.ca_file = "/opt/yahoo/share/ssl/certs/athenz_certificate_bundle.pem";
+ this.cert_file = "/var/lib/sia/certs/vespa.vespa.tenant.cert.pem";
+ this.key_file = "/var/lib/sia/keys/vespa.vespa.tenant.key.pem";
+ }
+ }
+ }
+
+ String receiverName(int index) {
+ return "prometheus_simple/s" + index;
+ }
+
+ private void addReceivers(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("receivers");
+ g.writeStartObject();
+ int counter = 0;
+ for (var statePort : statePorts) {
+ addReceiver(g, ++counter, statePort);
+ }
+ g.writeEndObject(); // receivers
+ }
+ private void addReceiver(JsonGenerator g, int index, StatePortInfo statePort) throws java.io.IOException {
+ g.writeFieldName(receiverName(index));
+ g.writeStartObject();
+ g.writeStringField("collection_interval", "60s");
+ g.writeStringField("endpoint", statePort.hostName() + ":" + statePort.portNumber());
+ addUrlInfo(g);
+ if (useTls) addTls(g);
+ {
+ g.writeFieldName("labels");
+ g.writeStartObject();
+ g.writeStringField("service_type", statePort.serviceType());
+ g.writeEndObject();
+ }
+ g.writeEndObject();
+ }
+ private void addTls(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("tls");
+ g.writeStartObject();
+ g.writeStringField("ca_file", ca_file);
+ g.writeStringField("cert_file", cert_file);
+ g.writeBooleanField("insecure_skip_verify", true);
+ g.writeStringField("key_file", key_file);
+ g.writeEndObject(); // tls
+ }
+ private void addUrlInfo(JsonGenerator g) throws java.io.IOException {
+ g.writeStringField("metrics_path", "/state/v1/metrics");
+ g.writeFieldName("params");
+ g.writeStartObject();
+ g.writeStringField("format", "prometheus");
+ g.writeEndObject();
+ }
+ private void addExporters(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("exporters");
+ g.writeStartObject();
+ addFileExporter(g);
+ g.writeEndObject(); // exporters
+ }
+ private void addFileExporter(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("file");
+ g.writeStartObject();
+ g.writeStringField("path", getDefaults().underVespaHome("logs/vespa/otel-test.json"));
+ {
+ g.writeFieldName("rotation");
+ g.writeStartObject();
+ g.writeNumberField("max_megabytes", 10);
+ g.writeNumberField("max_days", 3);
+ g.writeNumberField("max_backups", 1);
+ g.writeEndObject(); // rotation
+ }
+ g.writeEndObject(); // file
+ }
+ private void addServiceBlock(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("service");
+ g.writeStartObject();
+ {
+ g.writeFieldName("telemetry");
+ g.writeStartObject();
+ {
+ g.writeFieldName("logs");
+ g.writeStartObject();
+ g.writeStringField("level", "debug");
+ g.writeEndObject();
+ }
+ g.writeEndObject();
+ }
+ {
+ g.writeFieldName("pipelines");
+ g.writeStartObject();
+ addMetricsPipelines(g);
+ g.writeEndObject(); // pipelines
+ }
+ g.writeEndObject(); // service
+ }
+ private void addMetricsPipelines(JsonGenerator g) throws java.io.IOException {
+ g.writeFieldName("metrics");
+ g.writeStartObject();
+ {
+ g.writeFieldName("receivers");
+ g.writeStartArray();
+ int counter = 0;
+ for (var statePort : statePorts) {
+ g.writeString(receiverName(++counter));
+ }
+ g.writeEndArray();
+ }
+ g.writeFieldName("processors");
+ g.writeStartArray();
+ g.writeEndArray();
+ {
+ g.writeFieldName("exporters");
+ g.writeStartArray();
+ g.writeString("file");
+ g.writeEndArray();
+ }
+ g.writeEndObject(); // metrics
+ }
+
+ // For now - mostly dummy config
/*
TODO: Create config
- 1. polling /state/v1 handler of every service
+ 1. polling /state/v1 handler of every service (mostly done)
2. Processing with mapping/filtering from metric sets
3. Exporter to correct endpoint (alternatively amended)
*/
public String generate() {
-
- return """
- receivers:
- prometheus_simple:
- collection_interval: 60s
- endpoint: 'localhost:4080'
- metrics_path: '/state/v1/metrics'
- params:
- format: 'prometheus'
- tls:
- ca_file: '/opt/vespa/var/vespa/trust-store.pem'
- cert_file: '/var/lib/sia/certs/vespa.external.cd.tenant.cert.pem'
- insecure_skip_verify: true
- key_file: '/var/lib/sia/keys/vespa.external.cd.tenant.key.pem'
- exporters:
- file:
- path: /opt/vespa/logs/vespa/otel-test.json
- rotation:
- max_megabytes: 10
- max_days: 3
- max_backups: 1
- service:
- pipelines:
- metrics:
- receivers: [ prometheus_simple ]
- processors: [ ]
- exporters: [ file ]
- """;
+ if (statePorts.isEmpty()) {
+ return "";
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try {
+ JsonGenerator g = new JsonFactory().createGenerator(out, JsonEncoding.UTF8);
+ g.writeStartObject();
+ addReceivers(g);
+ addExporters(g);
+ addServiceBlock(g);
+ g.writeEndObject(); // root
+ g.close();
+ } catch (java.io.IOException e) {
+ System.err.println("unexpected error: " + e);
+ return "";
+ }
+ return out.toString(StandardCharsets.UTF_8);
}
void addStatePorts(List<StatePortInfo> portList) {
- // XXX not used yet
+ this.statePorts = portList;
}
List<String> referencedPaths() {
- return List.of("/var/lib/sia/certs/vespa.external.cd.tenant.cert.pem",
- "/var/lib/sia/keys/vespa.external.cd.tenant.key.pem");
+ return List.of(ca_file, cert_file, key_file);
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
index 23a46b3e065..347bb504857 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java
@@ -123,7 +123,7 @@ public class DomAdminV4Builder extends DomAdminBuilderBase {
private void addOtelcol(TreeConfigProducer<?> parent, DeployState deployState, HostResource hostResource) {
- var otelcol = new OpenTelemetryCollector(parent);
+ var otelcol = new OpenTelemetryCollector(parent, deployState);
otelcol.setHostResource(hostResource);
otelcol.initService(deployState);
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java
new file mode 100644
index 00000000000..7c4968aac84
--- /dev/null
+++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/otel/OpenTelemetryConfigGeneratorTest.java
@@ -0,0 +1,22 @@
+// 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.otel;
+
+import com.yahoo.config.model.ApplicationConfigProducerRoot.StatePortInfo;
+import org.junit.jupiter.api.Test;
+import java.util.List;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author arnej
+ */
+public class OpenTelemetryConfigGeneratorTest {
+
+ @Test
+ void testBuildsYaml() {
+ var generator = new OpenTelemetryConfigGenerator(null);
+ generator.addStatePorts(List.of(new StatePortInfo("localhost", 19098, "config-sentinel", "sentinel")));
+ String yaml = generator.generate();
+ assertTrue(yaml.contains("sentinel"));
+ }
+
+}