Skip to content

Commit ea6e3dd

Browse files
authored
Add file configuration ComponentProvider support for exporters (#6493)
1 parent 6fc1d21 commit ea6e3dd

File tree

32 files changed

+1137
-511
lines changed

32 files changed

+1137
-511
lines changed

exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
99
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
10+
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
1011
import io.opentelemetry.sdk.common.export.MemoryMode;
1112
import java.net.URI;
1213
import java.net.URISyntaxException;
@@ -54,5 +55,21 @@ public static void configureExporterMemoryMode(
5455
memoryModeConsumer.accept(memoryMode);
5556
}
5657

58+
/** Invoke the {@code memoryModeConsumer} with the configured {@link MemoryMode}. */
59+
public static void configureExporterMemoryMode(
60+
StructuredConfigProperties config, Consumer<MemoryMode> memoryModeConsumer) {
61+
String memoryModeStr = config.getString("memory_mode");
62+
if (memoryModeStr == null) {
63+
return;
64+
}
65+
MemoryMode memoryMode;
66+
try {
67+
memoryMode = MemoryMode.valueOf(memoryModeStr.toUpperCase(Locale.ROOT));
68+
} catch (IllegalArgumentException e) {
69+
throw new ConfigurationException("Unrecognized memory_mode: " + memoryModeStr, e);
70+
}
71+
memoryModeConsumer.accept(memoryMode);
72+
}
73+
5774
private ExporterBuilderUtil() {}
5875
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.logging.internal;
7+
8+
import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter;
9+
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
10+
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
11+
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
12+
13+
/**
14+
* File configuration SPI implementation for {@link SystemOutLogRecordExporter}.
15+
*
16+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
17+
* at any time.
18+
*/
19+
public final class ConsoleLogRecordExporterComponentProvider
20+
implements ComponentProvider<LogRecordExporter> {
21+
22+
@Override
23+
public Class<LogRecordExporter> getType() {
24+
return LogRecordExporter.class;
25+
}
26+
27+
@Override
28+
public String getName() {
29+
return "console";
30+
}
31+
32+
@Override
33+
public LogRecordExporter create(StructuredConfigProperties config) {
34+
return SystemOutLogRecordExporter.create();
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.logging.internal;
7+
8+
import io.opentelemetry.exporter.logging.LoggingMetricExporter;
9+
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
10+
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
11+
import io.opentelemetry.sdk.metrics.export.MetricExporter;
12+
13+
/**
14+
* File configuration SPI implementation for {@link LoggingMetricExporter}.
15+
*
16+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
17+
* at any time.
18+
*/
19+
public final class ConsoleMetricExporterComponentProvider
20+
implements ComponentProvider<MetricExporter> {
21+
22+
@Override
23+
public Class<MetricExporter> getType() {
24+
return MetricExporter.class;
25+
}
26+
27+
@Override
28+
public String getName() {
29+
return "console";
30+
}
31+
32+
@Override
33+
public MetricExporter create(StructuredConfigProperties config) {
34+
return LoggingMetricExporter.create();
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.exporter.logging.internal;
7+
8+
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
9+
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
10+
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
11+
import io.opentelemetry.sdk.trace.export.SpanExporter;
12+
13+
/**
14+
* File configuration SPI implementation for {@link LoggingSpanExporter}.
15+
*
16+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
17+
* at any time.
18+
*/
19+
public final class ConsoleSpanExporterComponentProvider implements ComponentProvider<SpanExporter> {
20+
21+
@Override
22+
public Class<SpanExporter> getType() {
23+
return SpanExporter.class;
24+
}
25+
26+
@Override
27+
public String getName() {
28+
return "console";
29+
}
30+
31+
@Override
32+
public SpanExporter create(StructuredConfigProperties config) {
33+
return LoggingSpanExporter.create();
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
io.opentelemetry.exporter.logging.internal.ConsoleMetricExporterComponentProvider
2+
io.opentelemetry.exporter.logging.internal.ConsoleSpanExporterComponentProvider
3+
io.opentelemetry.exporter.logging.internal.ConsoleLogRecordExporterComponentProvider

exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/internal/OtlpConfigUtil.java

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
1111
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1212
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
13+
import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties;
1314
import io.opentelemetry.sdk.common.export.MemoryMode;
1415
import io.opentelemetry.sdk.common.export.RetryPolicy;
1516
import io.opentelemetry.sdk.metrics.Aggregation;
@@ -54,6 +55,11 @@ public static String getOtlpProtocol(String dataType, ConfigProperties config) {
5455
return config.getString("otel.exporter.otlp.protocol", PROTOCOL_GRPC);
5556
}
5657

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+
5763
/** Invoke the setters with the OTLP configuration for the {@code dataType}. */
5864
@SuppressWarnings("TooManyParameters")
5965
public static void configureOtlpExporterBuilder(
@@ -134,9 +140,11 @@ public static void configureOtlpExporterBuilder(
134140
determinePropertyByType(config, "otel.exporter.otlp", dataType, "client.certificate"));
135141

136142
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");
138145
} 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");
140148
}
141149

142150
byte[] certificateBytes = readFileBytes(certificatePath);
@@ -166,6 +174,81 @@ public static void configureOtlpExporterBuilder(
166174
ExporterBuilderUtil.configureExporterMemoryMode(config, setMemoryMode);
167175
}
168176

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+
169252
/**
170253
* Invoke the {@code aggregationTemporalitySelectorConsumer} with the configured {@link
171254
* AggregationTemporality}.
@@ -194,6 +277,30 @@ public static void configureOtlpAggregationTemporality(
194277
aggregationTemporalitySelectorConsumer.accept(temporalitySelector);
195278
}
196279

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+
197304
/**
198305
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
199306
* DefaultAggregationSelector}.
@@ -218,6 +325,29 @@ public static void configureOtlpHistogramDefaultAggregation(
218325
}
219326
}
220327

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+
221351
private static URL createUrl(URL context, String spec) {
222352
try {
223353
return new URL(context, spec);

0 commit comments

Comments
 (0)