001package io.prometheus.metrics.config;
002
003import java.util.HashMap;
004import java.util.Map;
005
006// TODO: JavaDoc is currently only in OpenTelemetryExporter.Builder. Look there for reference.
007public class ExporterOpenTelemetryProperties {
008
009    // See https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md
010    private static String PROTOCOL = "protocol"; // otel.exporter.otlp.protocol
011    private static String ENDPOINT = "endpoint"; // otel.exporter.otlp.endpoint
012    private static String HEADERS = "headers"; // otel.exporter.otlp.headers
013    private static String INTERVAL_SECONDS = "intervalSeconds"; // otel.metric.export.interval
014    private static String TIMEOUT_SECONDS = "timeoutSeconds"; // otel.exporter.otlp.timeout
015    private static String SERVICE_NAME = "serviceName"; // otel.service.name
016    private static String SERVICE_NAMESPACE = "serviceNamespace";
017    private static String SERVICE_INSTANCE_ID = "serviceInstanceId";
018    private static String SERVICE_VERSION = "serviceVersion";
019    private static String RESOURCE_ATTRIBUTES = "resourceAttributes"; // otel.resource.attributes
020
021    private final String protocol;
022    private final String endpoint;
023    private final Map<String, String> headers;
024    private final Integer intervalSeconds;
025    private final Integer timeoutSeconds;
026    private final String serviceName;
027    private final String serviceNamespace;
028    private final String serviceInstanceId;
029    private final String serviceVersion;
030    private final Map<String, String> resourceAttributes;
031
032    private ExporterOpenTelemetryProperties(String protocol, String endpoint, Map<String, String> headers, Integer intervalSeconds, Integer timeoutSeconds, String serviceName, String serviceNamespace, String serviceInstanceId, String serviceVersion, Map<String, String> resourceAttributes) {
033        this.protocol = protocol;
034        this.endpoint = endpoint;
035        this.headers = headers;
036        this.intervalSeconds = intervalSeconds;
037        this.timeoutSeconds = timeoutSeconds;
038        this.serviceName = serviceName;
039        this.serviceNamespace = serviceNamespace;
040        this.serviceInstanceId = serviceInstanceId;
041        this.serviceVersion = serviceVersion;
042        this.resourceAttributes = resourceAttributes;
043    }
044
045    public String getProtocol() {
046        return protocol;
047    }
048
049    public String getEndpoint() {
050        return endpoint;
051    }
052
053    public Map<String, String> getHeaders() {
054        return headers;
055    }
056
057    public Integer getIntervalSeconds() {
058        return intervalSeconds;
059    }
060
061    public Integer getTimeoutSeconds() {
062        return timeoutSeconds;
063    }
064
065    public String getServiceName() {
066        return serviceName;
067    }
068
069    public String getServiceNamespace() {
070        return serviceNamespace;
071    }
072
073    public String getServiceInstanceId() {
074        return serviceInstanceId;
075    }
076
077    public String getServiceVersion() {
078        return serviceVersion;
079    }
080
081    public Map<String, String> getResourceAttributes() {
082        return resourceAttributes;
083    }
084
085    /**
086     * Note that this will remove entries from {@code properties}.
087     * This is because we want to know if there are unused properties remaining after all properties have been loaded.
088     */
089    static ExporterOpenTelemetryProperties load(String prefix, Map<Object, Object> properties) throws PrometheusPropertiesException {
090        String protocol = Util.loadString(prefix + "." + PROTOCOL, properties);
091        String endpoint = Util.loadString(prefix + "." + ENDPOINT, properties);
092        Map<String, String> headers = Util.loadMap(prefix + "." + HEADERS, properties);
093        Integer intervalSeconds = Util.loadInteger(prefix + "." + INTERVAL_SECONDS, properties);
094        Integer timeoutSeconds = Util.loadInteger(prefix + "." + TIMEOUT_SECONDS, properties);
095        String serviceName = Util.loadString(prefix + "." + SERVICE_NAME, properties);
096        String serviceNamespace = Util.loadString(prefix + "." + SERVICE_NAMESPACE, properties);
097        String serviceInstanceId = Util.loadString(prefix + "." + SERVICE_INSTANCE_ID, properties);
098        String serviceVersion = Util.loadString(prefix + "." + SERVICE_VERSION, properties);
099        Map<String, String> resourceAttributes = Util.loadMap(prefix + "." + RESOURCE_ATTRIBUTES, properties);
100        Util.assertValue(intervalSeconds, t -> t > 0, "Expecting value > 0", prefix, INTERVAL_SECONDS);
101        Util.assertValue(timeoutSeconds, t -> t > 0, "Expecting value > 0", prefix, TIMEOUT_SECONDS);
102        if (protocol != null && !protocol.equals("grpc") && !protocol.equals("http/protobuf")) {
103            throw new PrometheusPropertiesException(protocol + ": Unsupported OpenTelemetry exporter protocol. Expecting grpc or http/protobuf");
104        }
105        return new ExporterOpenTelemetryProperties(protocol, endpoint, headers, intervalSeconds, timeoutSeconds, serviceName, serviceNamespace, serviceInstanceId, serviceVersion, resourceAttributes);
106    }
107
108    public static Builder builder() {
109        return new Builder();
110    }
111
112    public static class Builder {
113
114        private String protocol;
115        private String endpoint;
116        private Map<String, String> headers = new HashMap<>();
117        private Integer intervalSeconds;
118        private Integer timeoutSeconds;
119        private String serviceName;
120        private String serviceNamespace;
121        private String serviceInstanceId;
122        private String serviceVersion;
123        private Map<String, String> resourceAttributes = new HashMap<>();
124
125        private Builder() {}
126
127        public Builder protocol(String protocol) {
128            if (!protocol.equals("grpc") && !protocol.equals("http/protobuf")) {
129                throw new IllegalArgumentException(protocol + ": Unsupported protocol. Expecting grpc or http/protobuf");
130            }
131            this.protocol = protocol;
132            return this;
133        }
134
135        public Builder endpoint(String endpoint) {
136            this.endpoint = endpoint;
137            return this;
138        }
139
140        /**
141         * Add a request header. Call multiple times to add multiple headers.
142         */
143        public Builder header(String name, String value) {
144            this.headers.put(name, value);
145            return this;
146        }
147
148        public Builder intervalSeconds(int intervalSeconds) {
149            if (intervalSeconds <= 0) {
150                throw new IllegalArgumentException(intervalSeconds + ": Expecting intervalSeconds > 0");
151            }
152            this.intervalSeconds = intervalSeconds;
153            return this;
154        }
155
156        public Builder timeoutSeconds(int timeoutSeconds) {
157            if (timeoutSeconds <= 0) {
158                throw new IllegalArgumentException(timeoutSeconds + ": Expecting timeoutSeconds > 0");
159            }
160            this.timeoutSeconds = timeoutSeconds;
161            return this;
162        }
163
164        public Builder serviceName(String serviceName) {
165            this.serviceName = serviceName;
166            return this;
167        }
168
169        public Builder serviceNamespace(String serviceNamespace) {
170            this.serviceNamespace = serviceNamespace;
171            return this;
172        }
173
174        public Builder serviceInstanceId(String serviceInstanceId) {
175            this.serviceInstanceId = serviceInstanceId;
176            return this;
177        }
178
179        public Builder serviceVersion(String serviceVersion) {
180            this.serviceVersion = serviceVersion;
181            return this;
182        }
183
184        public Builder resourceAttribute(String name, String value) {
185            this.resourceAttributes.put(name, value);
186            return this;
187        }
188
189        public ExporterOpenTelemetryProperties build() {
190            return new ExporterOpenTelemetryProperties(protocol, endpoint, headers, intervalSeconds, timeoutSeconds, serviceName, serviceNamespace, serviceInstanceId, serviceVersion, resourceAttributes);
191        }
192    }
193}