10
10
import io .opentelemetry .exporter .internal .ExporterBuilderUtil ;
11
11
import io .opentelemetry .sdk .autoconfigure .spi .ConfigProperties ;
12
12
import io .opentelemetry .sdk .autoconfigure .spi .ConfigurationException ;
13
+ import io .opentelemetry .sdk .autoconfigure .spi .internal .StructuredConfigProperties ;
13
14
import io .opentelemetry .sdk .common .export .MemoryMode ;
14
15
import io .opentelemetry .sdk .common .export .RetryPolicy ;
15
16
import io .opentelemetry .sdk .metrics .Aggregation ;
@@ -54,6 +55,11 @@ public static String getOtlpProtocol(String dataType, ConfigProperties config) {
54
55
return config .getString ("otel.exporter.otlp.protocol" , PROTOCOL_GRPC );
55
56
}
56
57
58
+ /** Determine the configured OTLP protocol for the {@code dataType}. */
59
+ public static String getStructuredConfigOtlpProtocol (StructuredConfigProperties config ) {
60
+ return config .getString ("protocol" , PROTOCOL_GRPC );
61
+ }
62
+
57
63
/** Invoke the setters with the OTLP configuration for the {@code dataType}. */
58
64
@ SuppressWarnings ("TooManyParameters" )
59
65
public static void configureOtlpExporterBuilder (
@@ -134,9 +140,11 @@ public static void configureOtlpExporterBuilder(
134
140
determinePropertyByType (config , "otel.exporter.otlp" , dataType , "client.certificate" ));
135
141
136
142
if (clientKeyPath != null && clientKeyChainPath == null ) {
137
- throw new ConfigurationException ("Client key provided but certification chain is missing" );
143
+ throw new ConfigurationException (
144
+ "client key provided without client certificate - both client key and client certificate must be set" );
138
145
} else if (clientKeyPath == null && clientKeyChainPath != null ) {
139
- throw new ConfigurationException ("Client key chain provided but key is missing" );
146
+ throw new ConfigurationException (
147
+ "client certificate provided without client key - both client key and client_certificate must be set" );
140
148
}
141
149
142
150
byte [] certificateBytes = readFileBytes (certificatePath );
@@ -166,6 +174,81 @@ public static void configureOtlpExporterBuilder(
166
174
ExporterBuilderUtil .configureExporterMemoryMode (config , setMemoryMode );
167
175
}
168
176
177
+ /** Invoke the setters with the OTLP configuration for the {@code dataType}. */
178
+ @ SuppressWarnings ("TooManyParameters" )
179
+ public static void configureOtlpExporterBuilder (
180
+ String dataType ,
181
+ StructuredConfigProperties config ,
182
+ Consumer <String > setEndpoint ,
183
+ BiConsumer <String , String > addHeader ,
184
+ Consumer <String > setCompression ,
185
+ Consumer <Duration > setTimeout ,
186
+ Consumer <byte []> setTrustedCertificates ,
187
+ BiConsumer <byte [], byte []> setClientTls ,
188
+ Consumer <RetryPolicy > setRetryPolicy ,
189
+ Consumer <MemoryMode > setMemoryMode ) {
190
+ String protocol = getStructuredConfigOtlpProtocol (config );
191
+ boolean isHttpProtobuf = protocol .equals (PROTOCOL_HTTP_PROTOBUF );
192
+ URL endpoint = validateEndpoint (config .getString ("endpoint" ), isHttpProtobuf );
193
+ if (endpoint != null && isHttpProtobuf ) {
194
+ String path = endpoint .getPath ();
195
+ if (!path .endsWith ("/" )) {
196
+ path += "/" ;
197
+ }
198
+ path += signalPath (dataType );
199
+ endpoint = createUrl (endpoint , path );
200
+ }
201
+ if (endpoint != null ) {
202
+ setEndpoint .accept (endpoint .toString ());
203
+ }
204
+
205
+ StructuredConfigProperties headers = config .getStructured ("headers" );
206
+ if (headers != null ) {
207
+ headers
208
+ .getPropertyKeys ()
209
+ .forEach (
210
+ header -> {
211
+ String value = headers .getString (header );
212
+ if (value != null ) {
213
+ addHeader .accept (header , value );
214
+ }
215
+ });
216
+ }
217
+
218
+ String compression = config .getString ("compression" );
219
+ if (compression != null ) {
220
+ setCompression .accept (compression );
221
+ }
222
+
223
+ Integer timeoutMs = config .getInt ("timeout" );
224
+ if (timeoutMs != null ) {
225
+ setTimeout .accept (Duration .ofMillis (timeoutMs ));
226
+ }
227
+
228
+ String certificatePath = config .getString ("certificate" );
229
+ String clientKeyPath = config .getString ("client_key" );
230
+ String clientKeyChainPath = config .getString ("client_certificate" );
231
+
232
+ if (clientKeyPath != null && clientKeyChainPath == null ) {
233
+ throw new ConfigurationException (
234
+ "client_key provided without client_certificate - both client_key and client_certificate must be set" );
235
+ } else if (clientKeyPath == null && clientKeyChainPath != null ) {
236
+ throw new ConfigurationException (
237
+ "client_certificate provided without client_key - both client_key and client_certificate must be set" );
238
+ }
239
+ byte [] certificateBytes = readFileBytes (certificatePath );
240
+ if (certificateBytes != null ) {
241
+ setTrustedCertificates .accept (certificateBytes );
242
+ }
243
+ byte [] clientKeyBytes = readFileBytes (clientKeyPath );
244
+ byte [] clientKeyChainBytes = readFileBytes (clientKeyChainPath );
245
+ if (clientKeyBytes != null && clientKeyChainBytes != null ) {
246
+ setClientTls .accept (clientKeyBytes , clientKeyChainBytes );
247
+ }
248
+
249
+ ExporterBuilderUtil .configureExporterMemoryMode (config , setMemoryMode );
250
+ }
251
+
169
252
/**
170
253
* Invoke the {@code aggregationTemporalitySelectorConsumer} with the configured {@link
171
254
* AggregationTemporality}.
@@ -194,6 +277,30 @@ public static void configureOtlpAggregationTemporality(
194
277
aggregationTemporalitySelectorConsumer .accept (temporalitySelector );
195
278
}
196
279
280
+ public static void configureOtlpAggregationTemporality (
281
+ StructuredConfigProperties config ,
282
+ Consumer <AggregationTemporalitySelector > aggregationTemporalitySelectorConsumer ) {
283
+ String temporalityStr = config .getString ("temporality_preference" );
284
+ if (temporalityStr == null ) {
285
+ return ;
286
+ }
287
+ AggregationTemporalitySelector temporalitySelector ;
288
+ switch (temporalityStr .toLowerCase (Locale .ROOT )) {
289
+ case "cumulative" :
290
+ temporalitySelector = AggregationTemporalitySelector .alwaysCumulative ();
291
+ break ;
292
+ case "delta" :
293
+ temporalitySelector = AggregationTemporalitySelector .deltaPreferred ();
294
+ break ;
295
+ case "lowmemory" :
296
+ temporalitySelector = AggregationTemporalitySelector .lowMemory ();
297
+ break ;
298
+ default :
299
+ throw new ConfigurationException ("Unrecognized temporality_preference: " + temporalityStr );
300
+ }
301
+ aggregationTemporalitySelectorConsumer .accept (temporalitySelector );
302
+ }
303
+
197
304
/**
198
305
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
199
306
* DefaultAggregationSelector}.
@@ -218,6 +325,29 @@ public static void configureOtlpHistogramDefaultAggregation(
218
325
}
219
326
}
220
327
328
+ /**
329
+ * Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
330
+ * DefaultAggregationSelector}.
331
+ */
332
+ public static void configureOtlpHistogramDefaultAggregation (
333
+ StructuredConfigProperties config ,
334
+ Consumer <DefaultAggregationSelector > defaultAggregationSelectorConsumer ) {
335
+ String defaultHistogramAggregation = config .getString ("default_histogram_aggregation" );
336
+ if (defaultHistogramAggregation == null ) {
337
+ return ;
338
+ }
339
+ if (AggregationUtil .aggregationName (Aggregation .base2ExponentialBucketHistogram ())
340
+ .equalsIgnoreCase (defaultHistogramAggregation )) {
341
+ defaultAggregationSelectorConsumer .accept (
342
+ DefaultAggregationSelector .getDefault ()
343
+ .with (InstrumentType .HISTOGRAM , Aggregation .base2ExponentialBucketHistogram ()));
344
+ } else if (!AggregationUtil .aggregationName (explicitBucketHistogram ())
345
+ .equalsIgnoreCase (defaultHistogramAggregation )) {
346
+ throw new ConfigurationException (
347
+ "Unrecognized default_histogram_aggregation: " + defaultHistogramAggregation );
348
+ }
349
+ }
350
+
221
351
private static URL createUrl (URL context , String spec ) {
222
352
try {
223
353
return new URL (context , spec );
0 commit comments