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}