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 newBuilder() { 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 withProtocol(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 withEndpoint(String endpoint) { 136 this.endpoint = endpoint; 137 return this; 138 } 139 140 public Builder addHeader(String name, String value) { 141 this.headers.put(name, value); 142 return this; 143 } 144 145 public Builder withIntervalSeconds(int intervalSeconds) { 146 if (intervalSeconds <= 0) { 147 throw new IllegalArgumentException(intervalSeconds + ": Expecting intervalSeconds > 0"); 148 } 149 this.intervalSeconds = intervalSeconds; 150 return this; 151 } 152 153 public Builder withTimeoutSeconds(int timeoutSeconds) { 154 if (timeoutSeconds <= 0) { 155 throw new IllegalArgumentException(timeoutSeconds + ": Expecting timeoutSeconds > 0"); 156 } 157 this.timeoutSeconds = timeoutSeconds; 158 return this; 159 } 160 161 public Builder withServiceName(String serviceName) { 162 this.serviceName = serviceName; 163 return this; 164 } 165 166 public Builder withServiceNamespace(String serviceNamespace) { 167 this.serviceNamespace = serviceNamespace; 168 return this; 169 } 170 171 public Builder withServiceInstanceId(String serviceInstanceId) { 172 this.serviceInstanceId = serviceInstanceId; 173 return this; 174 } 175 176 public Builder withServiceVersion(String serviceVersion) { 177 this.serviceVersion = serviceVersion; 178 return this; 179 } 180 181 public Builder addResourceAttribute(String name, String value) { 182 this.resourceAttributes.put(name, value); 183 return this; 184 } 185 186 public ExporterOpenTelemetryProperties build() { 187 return new ExporterOpenTelemetryProperties(protocol, endpoint, headers, intervalSeconds, timeoutSeconds, serviceName, serviceNamespace, serviceInstanceId, serviceVersion, resourceAttributes); 188 } 189 } 190}