From f715a189bf65f7de943e6a6b5b5c55cbff531b93 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 6 Feb 2024 05:44:37 +0100 Subject: [PATCH] re-use sdk logic for configuring otlp exporters (#10292) Co-authored-by: Trask Stalnaker --- .../OpenTelemetryAutoConfiguration.java | 23 +- .../logging/LoggingExporterProperties.java | 49 --- ...oggingMetricExporterAutoConfiguration.java | 2 - .../LoggingSpanExporterAutoConfiguration.java | 2 - .../otlp/OtlpExporterProperties.java | 97 +---- .../exporters/otlp/OtlpExporterUtil.java | 119 ------ ...lpLogRecordExporterAutoConfiguration.java} | 33 +- .../OtlpMetricExporterAutoConfiguration.java | 28 +- .../OtlpSpanExporterAutoConfiguration.java | 36 +- .../zipkin/ZipkinSpanExporterProperties.java | 9 - .../resources/SpringConfigProperties.java | 111 ++++++ .../SpringResourceConfigProperties.java | 75 ---- ...itional-spring-configuration-metadata.json | 349 +++++++++++++++++- .../main/resources/META-INF/spring.factories | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 2 +- .../MetricExporterAutoConfigurationTest.java | 2 + .../SpanExporterAutoConfigurationTest.java | 2 + .../otlp/OtlpExporterPropertiesTest.java | 95 +++++ .../OtlpLogExporterAutoConfigurationTest.java | 41 +- ...lpMetricExporterAutoConfigurationTest.java | 32 -- ...OtlpSpanExporterAutoConfigurationTest.java | 105 ------ ...t.java => SpringConfigPropertiesTest.java} | 8 +- 22 files changed, 599 insertions(+), 623 deletions(-) delete mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingExporterProperties.java delete mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java rename instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/{OtlpLoggerExporterAutoConfiguration.java => OtlpLogRecordExporterAutoConfiguration.java} (57%) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigProperties.java delete mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigProperties.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterPropertiesTest.java rename instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/{SpringResourceConfigPropertiesTest.java => SpringConfigPropertiesTest.java} (81%) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java index 2b79292d8ae4..8ef6865c5588 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfiguration.java @@ -8,12 +8,13 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.context.propagation.ContextPropagators; -import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration; +import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpExporterProperties; +import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLogRecordExporterAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.MapConverter; import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration; -import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringResourceConfigProperties; +import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringConfigProperties; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; @@ -55,7 +56,11 @@ *

Updates the sampler probability for the configured {@link TracerProvider}. */ @Configuration -@EnableConfigurationProperties({MetricExportProperties.class, SamplerProperties.class}) +@EnableConfigurationProperties({ + MetricExportProperties.class, + SamplerProperties.class, + OtlpExporterProperties.class +}) public class OpenTelemetryAutoConfiguration { public OpenTelemetryAutoConfiguration() {} @@ -81,7 +86,7 @@ public MapConverterCondition() { @ConditionalOnBean(OtelResourceAutoConfiguration.class) static class Resource {} - @ConditionalOnBean(OtlpLoggerExporterAutoConfiguration.class) + @ConditionalOnBean(OtlpLogRecordExporterAutoConfiguration.class) static class Logger {} @ConditionalOnBean(OtlpSpanExporterAutoConfiguration.class) @@ -91,6 +96,13 @@ static class Span {} static class Metric {} } + @Bean + @ConditionalOnMissingBean + ConfigProperties configProperties( + Environment env, OtlpExporterProperties otlpExporterProperties) { + return new SpringConfigProperties(env, new SpelExpressionParser(), otlpExporterProperties); + } + @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance @ConditionalOnMissingBean public SdkTracerProvider sdkTracerProvider( @@ -156,8 +168,7 @@ private static PeriodicMetricReader createPeriodicMetricReader( @Bean @ConditionalOnMissingBean public Resource otelResource( - Environment env, ObjectProvider> resourceProviders) { - ConfigProperties config = new SpringResourceConfigProperties(env, new SpelExpressionParser()); + ConfigProperties config, ObjectProvider> resourceProviders) { Resource resource = Resource.getDefault(); for (ResourceProvider resourceProvider : resourceProviders.getIfAvailable(Collections::emptyList)) { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingExporterProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingExporterProperties.java deleted file mode 100644 index c0e8402f6b91..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingExporterProperties.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Configuration for {@link io.opentelemetry.exporter.logging.LoggingSpanExporter} and {@link - * io.opentelemetry.exporter.logging.LoggingMetricExporter}. - */ -@ConfigurationProperties(prefix = "otel.exporter.logging") -public final class LoggingExporterProperties { - - private boolean enabled = false; - private final SignalProperties traces = new SignalProperties(); - private final SignalProperties metrics = new SignalProperties(); - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public SignalProperties getTraces() { - return traces; - } - - public SignalProperties getMetrics() { - return metrics; - } - - public static class SignalProperties { - - private boolean enabled = false; - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingMetricExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingMetricExporterAutoConfiguration.java index eab905471033..0b7829b071d1 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingMetricExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingMetricExporterAutoConfiguration.java @@ -11,7 +11,6 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @@ -19,7 +18,6 @@ /** Configures {@link LoggingMetricExporter} bean for tracing. */ @Configuration -@EnableConfigurationProperties(LoggingExporterProperties.class) @AutoConfigureBefore(OpenTelemetryAutoConfiguration.class) @Conditional(LoggingMetricExporterAutoConfiguration.CustomCondition.class) @ConditionalOnClass(LoggingMetricExporter.class) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingSpanExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingSpanExporterAutoConfiguration.java index 3d3038312e84..09b7234b1a79 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingSpanExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/logging/LoggingSpanExporterAutoConfiguration.java @@ -11,7 +11,6 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @@ -19,7 +18,6 @@ /** Configures {@link LoggingSpanExporter} bean for tracing. */ @Configuration -@EnableConfigurationProperties(LoggingExporterProperties.class) @AutoConfigureBefore(OpenTelemetryAutoConfiguration.class) @Conditional(LoggingSpanExporterAutoConfiguration.CustomCondition.class) @ConditionalOnClass(LoggingSpanExporter.class) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java index e4f678213d6a..9ec65498e71e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterProperties.java @@ -5,76 +5,24 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; -import java.time.Duration; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nullable; import org.springframework.boot.context.properties.ConfigurationProperties; -/** - * Configuration for {@link io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter} and {@link - * io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter}. - * - *

Get Exporter Service Name - * - *

Get Exporter Endpoint - * - *

Get max wait time for Collector to process Span Batches - */ +/** Configuration for OLTP exporters. */ @ConfigurationProperties(prefix = "otel.exporter.otlp") public final class OtlpExporterProperties { - private boolean enabled = true; - @Nullable private String endpoint; - - @Nullable private String protocol; - private final Map headers = new HashMap<>(); - @Nullable private Duration timeout; private final SignalProperties traces = new SignalProperties(); private final SignalProperties metrics = new SignalProperties(); private final SignalProperties logs = new SignalProperties(); - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - @Nullable - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } - - @Nullable - public String getProtocol() { - return protocol; - } - - public void setProtocol(@Nullable String protocol) { - this.protocol = protocol; - } - public Map getHeaders() { return headers; } - @Nullable - public Duration getTimeout() { - return timeout; - } - - public void setTimeout(Duration timeout) { - this.timeout = timeout; - } - public SignalProperties getTraces() { return traces; } @@ -88,53 +36,10 @@ public SignalProperties getLogs() { } public static class SignalProperties { - - private boolean enabled = true; - @Nullable private String endpoint; - - @Nullable private String protocol; - private final Map headers = new HashMap<>(); - @Nullable private Duration timeout; - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - @Nullable - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(@Nullable String endpoint) { - this.endpoint = endpoint; - } - - @Nullable - public String getProtocol() { - return protocol; - } - - public void setProtocol(@Nullable String protocol) { - this.protocol = protocol; - } - public Map getHeaders() { return headers; } - - @Nullable - public Duration getTimeout() { - return timeout; - } - - public void setTimeout(@Nullable Duration timeout) { - this.timeout = timeout; - } } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java deleted file mode 100644 index 151862501bc8..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterUtil.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; - -import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; -import java.time.Duration; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class OtlpExporterUtil { - private OtlpExporterUtil() {} - - private static final Logger logger = LoggerFactory.getLogger(OtlpExporterUtil.class); - - static E applySignalProperties( - String dataType, - OtlpExporterProperties properties, - OtlpExporterProperties.SignalProperties signalProperties, - Supplier newGrpcBuilder, - Supplier newHttpBuilder, - BiConsumer setGrpcEndpoint, - BiConsumer setHttpEndpoint, - BiConsumer> addGrpcHeader, - BiConsumer> addHttpHeader, - BiConsumer setGrpcTimeout, - BiConsumer setHttpTimeout, - Function buildGrpcExporter, - Function buildHttpExporter) { - - String protocol = signalProperties.getProtocol(); - if (protocol == null) { - protocol = properties.getProtocol(); - } - - G grpcBuilder = newGrpcBuilder.get(); - H httpBuilder = newHttpBuilder.get(); - - boolean isHttpProtobuf = !"grpc".equals(protocol); - - if (protocol != null - && !OtlpConfigUtil.PROTOCOL_GRPC.equals(protocol) - && !OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF.equals(protocol)) { - logger.warn( - "Unknown OTLP protocol '" - + protocol - + "', using '" - + OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF - + "'."); - } - - String endpoint = signalProperties.getEndpoint(); - if (endpoint == null) { - endpoint = properties.getEndpoint(); - if (endpoint != null && isHttpProtobuf) { - if (!endpoint.endsWith("/")) { - endpoint += "/"; - } - endpoint += signalPath(dataType); - } - } - - if (endpoint != null) { - if (isHttpProtobuf) { - setHttpEndpoint.accept(httpBuilder, endpoint); - } else { - setGrpcEndpoint.accept(grpcBuilder, endpoint); - } - } - - Map headers = signalProperties.getHeaders(); - if (headers.isEmpty()) { - headers = properties.getHeaders(); - } - for (Map.Entry entry : headers.entrySet()) { - if (isHttpProtobuf) { - addHttpHeader.accept(httpBuilder, entry); - } else { - addGrpcHeader.accept(grpcBuilder, entry); - } - } - - Duration timeout = signalProperties.getTimeout(); - if (timeout == null) { - timeout = properties.getTimeout(); - } - if (timeout != null) { - if (isHttpProtobuf) { - setHttpTimeout.accept(httpBuilder, timeout); - } else { - setGrpcTimeout.accept(grpcBuilder, timeout); - } - } - - return isHttpProtobuf - ? buildHttpExporter.apply(httpBuilder) - : buildGrpcExporter.apply(grpcBuilder); - } - - private static String signalPath(String dataType) { - switch (dataType) { - case OtlpConfigUtil.DATA_TYPE_METRICS: - return "v1/metrics"; - case OtlpConfigUtil.DATA_TYPE_TRACES: - return "v1/traces"; - case OtlpConfigUtil.DATA_TYPE_LOGS: - return "v1/logs"; - default: - throw new IllegalArgumentException( - "Cannot determine signal path for unrecognized data type: " + dataType); - } - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogRecordExporterAutoConfiguration.java similarity index 57% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogRecordExporterAutoConfiguration.java index 99a50d675ebf..5c65cd13593b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLoggerExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogRecordExporterAutoConfiguration.java @@ -6,49 +6,28 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; -import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporterBuilder; -import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; +import io.opentelemetry.exporter.otlp.internal.OtlpLogRecordExporterProvider; import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; -import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.internal.ExporterConfigEvaluator; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.logs.export.LogRecordExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @AutoConfigureBefore(OpenTelemetryAutoConfiguration.class) -@EnableConfigurationProperties(OtlpExporterProperties.class) -@Conditional(OtlpLoggerExporterAutoConfiguration.CustomCondition.class) +@Conditional(OtlpLogRecordExporterAutoConfiguration.CustomCondition.class) @ConditionalOnClass(OtlpGrpcLogRecordExporter.class) -public class OtlpLoggerExporterAutoConfiguration { +public class OtlpLogRecordExporterAutoConfiguration { @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance @ConditionalOnMissingBean({OtlpGrpcLogRecordExporter.class, OtlpHttpLogRecordExporter.class}) - public LogRecordExporter otelOtlpLogRecordExporter(OtlpExporterProperties properties) { - - return OtlpExporterUtil.applySignalProperties( - OtlpConfigUtil.DATA_TYPE_LOGS, - properties, - properties.getLogs(), - OtlpGrpcLogRecordExporter::builder, - OtlpHttpLogRecordExporter::builder, - OtlpGrpcLogRecordExporterBuilder::setEndpoint, - OtlpHttpLogRecordExporterBuilder::setEndpoint, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - OtlpGrpcLogRecordExporterBuilder::setTimeout, - OtlpHttpLogRecordExporterBuilder::setTimeout, - OtlpGrpcLogRecordExporterBuilder::build, - OtlpHttpLogRecordExporterBuilder::build); + public LogRecordExporter otelOtlpLogRecordExporter(ConfigProperties configProperties) { + return new OtlpLogRecordExporterProvider().createExporter(configProperties); } static final class CustomCondition implements Condition { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java index 3450b4051fa0..2ada08d5c387 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfiguration.java @@ -6,17 +6,15 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; -import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder; -import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; +import io.opentelemetry.exporter.otlp.internal.OtlpMetricExporterProvider; import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; -import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.internal.ExporterConfigEvaluator; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.metrics.export.MetricExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @@ -24,32 +22,14 @@ @Configuration @AutoConfigureBefore(OpenTelemetryAutoConfiguration.class) -@EnableConfigurationProperties(OtlpExporterProperties.class) @Conditional(OtlpMetricExporterAutoConfiguration.CustomCondition.class) @ConditionalOnClass(OtlpGrpcMetricExporter.class) public class OtlpMetricExporterAutoConfiguration { @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance @ConditionalOnMissingBean({OtlpGrpcMetricExporter.class, OtlpHttpMetricExporter.class}) - public MetricExporter otelOtlpMetricExporter(OtlpExporterProperties properties) { - return OtlpExporterUtil.applySignalProperties( - OtlpConfigUtil.DATA_TYPE_METRICS, - properties, - properties.getLogs(), - OtlpGrpcMetricExporter::builder, - OtlpHttpMetricExporter::builder, - OtlpGrpcMetricExporterBuilder::setEndpoint, - OtlpHttpMetricExporterBuilder::setEndpoint, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - OtlpGrpcMetricExporterBuilder::setTimeout, - OtlpHttpMetricExporterBuilder::setTimeout, - OtlpGrpcMetricExporterBuilder::build, - OtlpHttpMetricExporterBuilder::build); + public MetricExporter otelOtlpMetricExporter(ConfigProperties configProperties) { + return new OtlpMetricExporterProvider().createExporter(configProperties); } static final class CustomCondition implements Condition { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java index f4b35980b74a..ab254433c034 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfiguration.java @@ -6,17 +6,15 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; -import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; -import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; +import io.opentelemetry.exporter.otlp.internal.OtlpSpanExporterProvider; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.internal.ExporterConfigEvaluator; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.trace.export.SpanExporter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.Conditional; @@ -29,40 +27,14 @@ */ @Configuration @AutoConfigureBefore(OpenTelemetryAutoConfiguration.class) -@EnableConfigurationProperties(OtlpExporterProperties.class) @Conditional(OtlpSpanExporterAutoConfiguration.CustomCondition.class) @ConditionalOnClass(OtlpGrpcSpanExporter.class) public class OtlpSpanExporterAutoConfiguration { - @Bean - @ConditionalOnMissingBean({OtlpHttpSpanExporterBuilder.class}) - public OtlpHttpSpanExporterBuilder otelOtlpHttpSpanExporterBuilder() { - // used for testing only - the builder is final - return OtlpHttpSpanExporter.builder(); - } - @Bean(destroyMethod = "") // SDK components are shutdown from the OpenTelemetry instance @ConditionalOnMissingBean({OtlpGrpcSpanExporter.class, OtlpHttpSpanExporter.class}) - public SpanExporter otelOtlpSpanExporter( - OtlpExporterProperties properties, OtlpHttpSpanExporterBuilder otlpHttpSpanExporterBuilder) { - return OtlpExporterUtil.applySignalProperties( - OtlpConfigUtil.DATA_TYPE_TRACES, - properties, - properties.getLogs(), - OtlpGrpcSpanExporter::builder, - () -> otlpHttpSpanExporterBuilder, - OtlpGrpcSpanExporterBuilder::setEndpoint, - OtlpHttpSpanExporterBuilder::setEndpoint, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - (builder, entry) -> { - builder.addHeader(entry.getKey(), entry.getValue()); - }, - OtlpGrpcSpanExporterBuilder::setTimeout, - OtlpHttpSpanExporterBuilder::setTimeout, - OtlpGrpcSpanExporterBuilder::build, - OtlpHttpSpanExporterBuilder::build); + public SpanExporter otelOtlpSpanExporter(ConfigProperties configProperties) { + return new OtlpSpanExporterProvider().createExporter(configProperties); } static final class CustomCondition implements Condition { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/zipkin/ZipkinSpanExporterProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/zipkin/ZipkinSpanExporterProperties.java index c6a7e412d8fb..d7e1df91b948 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/zipkin/ZipkinSpanExporterProperties.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/zipkin/ZipkinSpanExporterProperties.java @@ -16,17 +16,8 @@ @ConfigurationProperties(prefix = "otel.exporter.zipkin") public class ZipkinSpanExporterProperties { - private boolean enabled = true; @Nullable private String endpoint; - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - @Nullable public String getEndpoint() { return endpoint; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigProperties.java new file mode 100644 index 000000000000..60210ba60991 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigProperties.java @@ -0,0 +1,111 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.resources; + +import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil; +import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpExporterProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.annotation.Nullable; +import org.springframework.core.env.Environment; +import org.springframework.expression.ExpressionParser; + +public class SpringConfigProperties implements ConfigProperties { + private final Environment environment; + + private final ExpressionParser parser; + private final OtlpExporterProperties otlpExporterProperties; + + public SpringConfigProperties( + Environment environment, + ExpressionParser parser, + OtlpExporterProperties otlpExporterProperties) { + this.environment = environment; + this.parser = parser; + this.otlpExporterProperties = otlpExporterProperties; + } + + @Nullable + @Override + public String getString(String name) { + String value = environment.getProperty(name, String.class); + if (value == null && name.equals("otel.exporter.otlp.protocol")) { + // SDK autoconfigure module defaults to `grpc`, but this module aligns with recommendation + // in specification to default to `http/protobuf` + return OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF; + } + return value; + } + + @Nullable + @Override + public Boolean getBoolean(String name) { + return environment.getProperty(name, Boolean.class); + } + + @Nullable + @Override + public Integer getInt(String name) { + return environment.getProperty(name, Integer.class); + } + + @Nullable + @Override + public Long getLong(String name) { + return environment.getProperty(name, Long.class); + } + + @Nullable + @Override + public Double getDouble(String name) { + return environment.getProperty(name, Double.class); + } + + @SuppressWarnings("unchecked") + @Override + public List getList(String name) { + return (List) environment.getProperty(name, List.class); + } + + @Nullable + @Override + public Duration getDuration(String name) { + String value = getString(name); + if (value == null) { + return null; + } + return DefaultConfigProperties.createFromMap(Collections.singletonMap(name, value)) + .getDuration(name); + } + + @SuppressWarnings("unchecked") + @Override + public Map getMap(String name) { + // maps from config properties are not supported by Environment, so we have to fake it + switch (name) { + case "otel.exporter.otlp.headers": + return otlpExporterProperties.getHeaders(); + case "otel.exporter.otlp.logs.headers": + return otlpExporterProperties.getLogs().getHeaders(); + case "otel.exporter.otlp.metrics.headers": + return otlpExporterProperties.getMetrics().getHeaders(); + case "otel.exporter.otlp.traces.headers": + return otlpExporterProperties.getTraces().getHeaders(); + default: + break; + } + + String value = environment.getProperty(name); + if (value == null) { + return Collections.emptyMap(); + } + return (Map) parser.parseExpression(value).getValue(); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigProperties.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigProperties.java deleted file mode 100644 index 4ed9190ac45c..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigProperties.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.resources; - -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import java.time.Duration; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import javax.annotation.Nullable; -import org.springframework.core.env.Environment; -import org.springframework.expression.ExpressionParser; - -public class SpringResourceConfigProperties implements ConfigProperties { - private final Environment environment; - - private final ExpressionParser parser; - - public SpringResourceConfigProperties(Environment environment, ExpressionParser parser) { - this.environment = environment; - this.parser = parser; - } - - @Nullable - @Override - public String getString(String name) { - return environment.getProperty(name, String.class); - } - - @Nullable - @Override - public Boolean getBoolean(String name) { - return environment.getProperty(name, Boolean.class); - } - - @Nullable - @Override - public Integer getInt(String name) { - return environment.getProperty(name, Integer.class); - } - - @Nullable - @Override - public Long getLong(String name) { - return environment.getProperty(name, Long.class); - } - - @Nullable - @Override - public Double getDouble(String name) { - return environment.getProperty(name, Double.class); - } - - @Nullable - @Override - public Duration getDuration(String name) { - return environment.getProperty(name, Duration.class); - } - - @SuppressWarnings("unchecked") - @Override - public List getList(String name) { - return (List) environment.getProperty(name, List.class); - } - - @SuppressWarnings("unchecked") - @Override - public Map getMap(String name) { - String value = environment.getProperty(name); - return (Map) parser.parseExpression(Objects.requireNonNull(value)).getValue(); - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index b12bc3157aa6..07ca3e93af70 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -5,6 +5,198 @@ } ], "properties": [ + { + "name": "otel.experimental.exporter.otlp.retry.enabled", + "type": "java.lang.Boolean", + "description": "Enable experimental retry support. See https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#otlp-exporter-retry.", + "defaultValue": false + }, + { + "name": "otel.exporter.otlp.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default the host platform's trusted root certificates are used." + }, + { + "name": "otel.exporter.otlp.client.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log client's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, no chain file is used." + }, + { + "name": "otel.exporter.otlp.client.key", + "type": "java.lang.String", + "description": "The path to the file containing private client key to use when verifying an OTLP trace, metric, or log client's TLS credentials.
The file should contain one private key PKCS8 PEM format.
By default, no client key is used." + }, + { + "name": "otel.exporter.otlp.compression", + "type": "java.lang.String", + "description": "The compression type to use on OTLP trace, metric, and log requests.
Options include gzip.
By default, no compression will be used." + }, + { + "name": "otel.exporter.otlp.endpoint", + "type": "java.lang.String", + "description": "The OTLP traces, metrics, and logs endpoint to connect to.
Must be a URL with a scheme of either http or https based on the use of TLS. If protocol is http/protobuf the version and signal will be appended to the path (e.g. v1/traces, v1/metrics, or v1/logs).
Default is http://localhost:4317 when protocol is grpc, and http://localhost:4318/v1/{signal} when protocol is http/protobuf." + }, + { + "name": "otel.exporter.otlp.headers", + "type": "java.util.Map", + "description": "Request headers for OTLP trace, metric, and log requests.
Can be either a Spring map or a key-value separated String, e.g. key1=value1,key2=value2." + }, + { + "name": "otel.exporter.otlp.logs.certificate", + "type": "java.lang.String", + "description": " The path to the file containing trusted certificates to use when verifying an OTLP log server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, the host platform's trusted root certificates are used." + }, + { + "name": "otel.exporter.otlp.logs.client.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP log server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, no chain file is used." + }, + { + "name": "otel.exporter.otlp.logs.client.key", + "type": "java.lang.String", + "description": "The path to the file containing private client key to use when verifying an OTLP log client's TLS credentials.
The file should contain one private key PKCS8 PEM format.
By default, no client key file is used." + }, + { + "name": "otel.exporter.otlp.logs.compression", + "type": "java.lang.String", + "description": "The compression type to use on OTLP log requests.
Options include gzip.
By default, no compression will be used." + }, + { + "name": "otel.exporter.otlp.logs.endpoint", + "type": "java.lang.String", + "description": "The OTLP logs endpoint to connect to.
Must be a URL with a scheme of either http or https based on the use of TLS.
Default is http://localhost:4317 when protocol is grpc, and http://localhost:4318/v1/logs when protocol is http/protobuf." + }, + { + "name": "otel.exporter.otlp.logs.headers", + "type": "java.util.Map", + "description": "Request headers for OTLP log requests.
Can be either a Spring map or a key-value separated String, e.g. key1=value1,key2=value2." + }, + { + "name": "otel.exporter.otlp.logs.protocol", + "type": "java.lang.String", + "description": "The transport protocol to use on OTLP log requests.", + "defaultValue": "http/protobuf" + }, + { + "name": "otel.exporter.otlp.logs.timeout", + "type": "java.lang.String", + "description": "The maximum waiting time, in milliseconds, allowed to send each OTLP log batch.
Durations can be of the form {number}{unit}, where unit is one of:

If no unit is specified, milliseconds is the assumed duration unit.", + "defaultValue": "10000" + }, + { + "name": "otel.exporter.otlp.metrics.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP metric server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, the host platform's trusted root certificates are used." + }, + { + "name": "otel.exporter.otlp.metrics.client.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP metric server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, no chain file is used." + }, + { + "name": "otel.exporter.otlp.metrics.client.key", + "type": "java.lang.String", + "description": "The path to the file containing private client key to use when verifying an OTLP metric client's TLS credentials.
The file should contain one private key PKCS8 PEM format.
By default, no client key file is used." + }, + { + "name": "otel.exporter.otlp.metrics.compression", + "type": "java.lang.String", + "description": "The compression type to use on OTLP metric requests.
Options include gzip.
By default, no compression will be used." + }, + { + "name": "otel.exporter.otlp.metrics.default.histogram.aggregation", + "type": "java.lang.String", + "description": "The preferred default histogram aggregation.", + "defaultValue": "EXPLICIT_BUCKET_HISTOGRAM" + }, + { + "name": "otel.exporter.otlp.metrics.endpoint", + "type": "java.lang.String", + "description": "The OTLP metrics endpoint to connect to.
Must be a URL with a scheme of either http or https based on the use of TLS.
Default is http://localhost:4317 when protocol is grpc, and http://localhost:4318/v1/metrics when protocol is http/protobuf." + }, + { + "name": "otel.exporter.otlp.metrics.headers", + "type": "java.util.Map", + "description": "Request headers for OTLP metric requests.
Can be either a Spring map or a key-value separated String, e.g. key1=value1,key2=value2." + }, + { + "name": "otel.exporter.otlp.metrics.protocol", + "type": "java.lang.String", + "description": "The transport protocol to use on OTLP metric requests.", + "defaultValue": "http/protobuf" + }, + { + "name": "otel.exporter.otlp.metrics.temporality.preference", + "type": "java.lang.String", + "description": "The preferred output aggregation temporality.", + "defaultValue": "CUMULATIVE" + }, + { + "name": "otel.exporter.otlp.metrics.timeout", + "type": "java.lang.String", + "description": "The maximum waiting time, in milliseconds, allowed to send each OTLP metric batch.
Durations can be of the form {number}{unit}, where unit is one of:

If no unit is specified, milliseconds is the assumed duration unit.", + "defaultValue": "10000" + }, + { + "name": "otel.exporter.otlp.protocol", + "type": "java.lang.String", + "description": "The transport protocol to use on OTLP trace, metric, and log requests.", + "defaultValue": "http/protobuf" + }, + { + "name": "otel.exporter.otlp.timeout", + "type": "java.lang.String", + "description": "The maximum waiting time, in milliseconds, allowed to send each OTLP trace, metric, and log batch.
Durations can be of the form {number}{unit}, where unit is one of:

If no unit is specified, milliseconds is the assumed duration unit.", + "defaultValue": "10000" + }, + { + "name": "otel.exporter.otlp.traces.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP trace server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default, the host platform's trusted root certificates are used." + }, + { + "name": "otel.exporter.otlp.traces.client.certificate", + "type": "java.lang.String", + "description": "The path to the file containing trusted certificates to use when verifying an OTLP trace server's TLS credentials.
The file should contain one or more X.509 certificates in PEM format.
By default no chain file is used." + }, + { + "name": "otel.exporter.otlp.traces.client.key", + "type": "java.lang.String", + "description": "The path to the file containing private client key to use when verifying an OTLP trace client's TLS credentials.
The file should contain one private key PKCS8 PEM format.
By default, no client key file is used." + }, + { + "name": "otel.exporter.otlp.traces.compression", + "type": "java.lang.String", + "description": "The compression type to use on OTLP trace requests.
Options include gzip.
By default, no compression will be used." + }, + { + "name": "otel.exporter.otlp.traces.endpoint", + "type": "java.lang.String", + "description": "The OTLP traces endpoint to connect to.
Must be a URL with a scheme of either http or https based on the use of TLS.
Default is http://localhost:4317 when protocol is grpc, and http://localhost:4318/v1/traces when protocol is http/protobuf." + }, + { + "name": "otel.exporter.otlp.traces.headers", + "type": "java.util.Map", + "description": "Request headers for OTLP trace requests.
Can be either a Spring map or a key-value separated String, e.g. key1=value1,key2=value2." + }, + { + "name": "otel.exporter.otlp.traces.protocol", + "type": "java.lang.String", + "description": "The transport protocol to use on OTLP trace requests.", + "defaultValue": "http/protobuf" + }, + { + "name": "otel.exporter.otlp.traces.timeout", + "type": "java.lang.String", + "description": "The maximum waiting time, in milliseconds, allowed to send each OTLP trace batch.
Durations can be of the form {number}{unit}, where unit is one of:

If no unit is specified, milliseconds is the assumed duration unit.", + "defaultValue": "10000" + }, + { + "name": "otel.exporter.zipkin.endpoint", + "type": "java.lang.String", + "description": "The Zipkin endpoint to connect to.
Currently only HTTP is supported.", + "defaultValue": "http://localhost:9411/api/v2/spans" + }, { "name": "otel.instrumentation.logback-appender.experimental.capture-code-attributes", "type": "java.lang.Boolean", @@ -38,7 +230,162 @@ { "name": "otel.instrumentation.logback-appender.experimental.capture-mdc-attributes", "type": "java.lang.String", - "description": "Comma separated list of MDC attributes to capture. Use the wildcard character * to capture all attributes." + "description": "Comma separated list of MDC attributes to capture. Use the wildcard character * to capture all attributes." + }, + { + "name": "otel.logs.exporter", + "type": "java.lang.String", + "description": "List of exporters to be used for logs, separated by commas.", + "defaultValue": "otlp" + }, + { + "name": "otel.metric.export.interval", + "type": "java.lang.String", + "description": "The interval, in milliseconds, between the start of two export attempts.
Durations can be of the form {number}{unit}, where unit is one of:

If no unit is specified, milliseconds is the assumed duration unit.", + "defaultValue": "60000" + }, + { + "name": "otel.metrics.exporter", + "type": "java.lang.String", + "description": "List of exporters to be used for metrics, separated by commas.", + "defaultValue": "otlp" + }, + { + "name": "otel.traces.exporter", + "type": "java.lang.String", + "description": "List of exporters to be used for tracing, separated by commas.", + "defaultValue": "otlp" + }, + { + "name": "otel.traces.sampler.probability", + "type": "java.lang.Double", + "description": "The probability of sampling.
The value should be within [0.0, 1.0]. 1.0 means keep everything, 0.0 means drop all spans.", + "defaultValue": 1.0 + } + ], + "hints": [ + { + "name": "otel.exporter.otlp.logs.protocol", + "values": [ + { + "value": "http/protobuf" + }, + { + "value": "grpc" + } + ] + }, + { + "name": "otel.exporter.otlp.metrics.protocol", + "values": [ + { + "value": "http/protobuf" + }, + { + "value": "grpc" + } + ] + }, + { + "name": "otel.exporter.otlp.protocol", + "values": [ + { + "value": "http/protobuf" + }, + { + "value": "grpc" + } + ] + }, + { + "name": "otel.exporter.otlp.traces.protocol", + "values": [ + { + "value": "http/protobuf" + }, + { + "value": "grpc" + } + ] + }, + { + "name": "otel.exporter.otlp.metrics.default.histogram.aggregation", + "values": [ + { + "value": "BASE2_EXPONENTIAL_BUCKET_HISTOGRAM" + }, + { + "value": "EXPLICIT_BUCKET_HISTOGRAM" + } + ] + }, + { + "name": "otel.exporter.otlp.metrics.temporality.preference", + "values": [ + { + "value": "CUMULATIVE", + "description": "All instruments will have cumulative temporality." + }, + { + "value": "DELTA", + "description": "Counter (sync and async) and histograms will be delta, up down counters (sync and async) will be cumulative." + }, + { + "value": "LOWMEMORY", + "description": "Sync counter and histograms will be delta, async counter and up down counters (sync and async) will be cumulative." + } + ] + }, + { + "name": "otel.logs.exporter", + "values": [ + { + "value": "none", + "description": "No autoconfigured exporter." + }, + { + "value": "otlp", + "description": "OpenTelemetry Protocol (OTLP) exporter." + } + ] + }, + { + "name": "otel.metrics.exporter", + "values": [ + { + "value": "logging", + "description": "The logging exporter prints exported metrics to stdout. It's mainly used for testing and debugging." + }, + { + "value": "none", + "description": "No autoconfigured exporter." + }, + { + "value": "otlp", + "description": "OpenTelemetry Protocol (OTLP) exporter." + } + ] + }, + { + "name": "otel.traces.exporter", + "values": [ + { + "value": "logging", + "description": "The logging exporter prints the name of the span along with its attributes to stdout. It's mainly used for testing and debugging." + }, + { + "value": "none", + "description": "No autoconfigured exporter." + }, + { + "value": "otlp", + "description": "OpenTelemetry Protocol (OTLP) exporter." + }, + { + "value": "zipkin", + "description": "Zipkin exporter." + } + ] } ] } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 389172ec1bd7..0d6e9b094c9e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -2,7 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingMetricExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLogRecordExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration,\ diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 8c9d440219d7..0642d53bce54 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,7 +1,7 @@ io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingMetricExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLogRecordExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/MetricExporterAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/MetricExporterAutoConfigurationTest.java index fb53294240f5..88519549b725 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/MetricExporterAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/MetricExporterAutoConfigurationTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.exporter.logging.LoggingMetricExporter; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; +import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingMetricExporterAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration; import org.junit.jupiter.api.Test; @@ -21,6 +22,7 @@ class MetricExporterAutoConfigurationTest { new ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( + OpenTelemetryAutoConfiguration.class, OtlpMetricExporterAutoConfiguration.class, LoggingMetricExporterAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/SpanExporterAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/SpanExporterAutoConfigurationTest.java index 558fe147088f..084694823be3 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/SpanExporterAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/SpanExporterAutoConfigurationTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration; import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration; import org.junit.jupiter.api.Test; @@ -21,6 +22,7 @@ class SpanExporterAutoConfigurationTest { new ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( + OpenTelemetryAutoConfiguration.class, OtlpSpanExporterAutoConfiguration.class, LoggingSpanExporterAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterPropertiesTest.java new file mode 100644 index 000000000000..8d61a4e7d4ae --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpExporterPropertiesTest.java @@ -0,0 +1,95 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; + +import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; +import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration; +import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import java.util.Arrays; +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.core.env.Environment; +import org.springframework.expression.spel.standard.SpelExpressionParser; + +class OtlpExporterPropertiesTest { + + private static final String[] HEADER_KEYS = { + "otel.exporter.otlp.traces.headers", + "otel.exporter.otlp.metrics.headers", + "otel.exporter.otlp.logs.headers", + "otel.exporter.otlp.headers", + }; + + private final ApplicationContextRunner contextRunner = + new ApplicationContextRunner() + .withConfiguration( + AutoConfigurations.of( + OpenTelemetryAutoConfiguration.class, OtelResourceAutoConfiguration.class)); + + public static Stream headerKeys() { + return Arrays.stream(HEADER_KEYS).map(Arguments::of); + } + + @Test + @DisplayName("test all property types") + void allTypes() { + this.contextRunner + .withPropertyValues( + "otel.exporter.otlp.enabled=true", + "otel.exporter.otlp.timeout=1s", + "otel.exporter.otlp.compression=gzip") + .run( + context -> { + ConfigProperties config = getConfig(context); + assertThat(config.getString("otel.exporter.otlp.compression")).isEqualTo("gzip"); + assertThat(config.getBoolean("otel.exporter.otlp.enabled")).isTrue(); + assertThat(config.getDuration("otel.exporter.otlp.timeout")) + .isEqualByComparingTo(java.time.Duration.ofSeconds(1)); + }); + } + + @ParameterizedTest + @MethodSource("headerKeys") + @DisplayName("should map headers from spring properties") + void mapFlatHeaders(String key) { + this.contextRunner + .withSystemProperties(key + "=a=1,b=2") + .run( + context -> + assertThat(getConfig(context).getMap(key)) + .containsExactly(entry("a", "1"), entry("b", "2"))); + } + + @ParameterizedTest + @MethodSource("headerKeys") + @DisplayName("should map headers from spring application.yaml") + void mapObjectHeaders(String key) { + this.contextRunner + .withPropertyValues(key + ".a=1", key + ".b=2") + .run( + context -> + assertThat(getConfig(context).getMap(key)) + .containsExactly(entry("a", "1"), entry("b", "2"))); + } + + private static ConfigProperties getConfig(AssertableApplicationContext context) { + return new SpringConfigProperties( + context.getBean("environment", Environment.class), + new SpelExpressionParser(), + context.getBean(OtlpExporterProperties.class)); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogExporterAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogExporterAutoConfigurationTest.java index 519c3cff167c..644193d8933d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogExporterAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpLogExporterAutoConfigurationTest.java @@ -7,11 +7,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter; -import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -22,7 +19,8 @@ class OtlpLogExporterAutoConfigurationTest { new ApplicationContextRunner() .withConfiguration( AutoConfigurations.of( - OpenTelemetryAutoConfiguration.class, OtlpLoggerExporterAutoConfiguration.class)); + OpenTelemetryAutoConfiguration.class, + OtlpLogRecordExporterAutoConfiguration.class)); @Test void otlpEnabled() { @@ -64,39 +62,4 @@ void otlpLogsDisabled() { .withPropertyValues("otel.logs.exporter=none") .run(context -> assertThat(context.containsBean("otelOtlpLogRecordExporter")).isFalse()); } - - @Test - void otlpHttpUsedByDefault() { - runner.run( - context -> - assertThat( - context.getBean("otelOtlpLogRecordExporter", OtlpHttpLogRecordExporter.class)) - .isNotNull()); - } - - @Test - @DisplayName("use grpc when protocol set") - void useGrpc() { - runner - .withPropertyValues("otel.exporter.otlp.protocol=grpc") - .run( - context -> - assertThat( - context.getBean( - "otelOtlpLogRecordExporter", OtlpGrpcLogRecordExporter.class)) - .isNotNull()); - } - - @Test - @DisplayName("use http when unknown protocol set") - void useHttpWhenAnUnknownProtocolIsSet() { - runner - .withPropertyValues("otel.exporter.otlp.protocol=unknown") - .run( - context -> - assertThat( - context.getBean( - "otelOtlpLogRecordExporter", OtlpHttpLogRecordExporter.class)) - .isNotNull()); - } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfigurationTest.java index 106ccd4a493f..b9a017d38613 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpMetricExporterAutoConfigurationTest.java @@ -8,9 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter; -import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; -import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -33,28 +31,6 @@ void otlpEnabled() { .isNotNull()); } - @Test - @DisplayName("use grpc when protocol set") - void useGrpc() { - runner - .withPropertyValues("otel.exporter.otlp.protocol=grpc") - .run( - context -> - assertThat(context.getBean("otelOtlpMetricExporter", OtlpGrpcMetricExporter.class)) - .isNotNull()); - } - - @Test - @DisplayName("use http when unknown protocol set") - void useHttpWhenAnUnknownProtocolIsSet() { - runner - .withPropertyValues("otel.exporter.otlp.protocol=unknown") - .run( - context -> - assertThat(context.getBean("otelOtlpMetricExporter", OtlpHttpMetricExporter.class)) - .isNotNull()); - } - @Test void otlpMetricsEnabled() { runner @@ -85,12 +61,4 @@ void otlpMetricsDisabled() { .withPropertyValues("otel.metrics.exporter=none") .run(context -> assertThat(context.containsBean("otelOtlpMetricExporter")).isFalse()); } - - @Test - void otlpHttpUsedByDefault() { - runner.run( - context -> - assertThat(context.getBean("otelOtlpMetricExporter", OtlpHttpMetricExporter.class)) - .isNotNull()); - } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfigurationTest.java index f0f934e10f8b..c98d9817161d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/exporters/otlp/OtlpSpanExporterAutoConfigurationTest.java @@ -7,24 +7,16 @@ import static org.assertj.core.api.Assertions.assertThat; -import io.opentelemetry.exporter.logging.LoggingSpanExporter; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; -import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder; -import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; -import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.util.stream.Collectors; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; /** Spring Boot auto configuration test for {@link OtlpSpanExporterAutoConfiguration}. */ class OtlpSpanExporterAutoConfigurationTest { - private final OtlpHttpSpanExporterBuilder otlpHttpSpanExporterBuilder = - Mockito.mock(OtlpHttpSpanExporterBuilder.class); private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration( @@ -40,8 +32,6 @@ void otlpEnabled() { context -> assertThat(context.getBean("otelOtlpSpanExporter", OtlpHttpSpanExporter.class)) .isNotNull()); - - Mockito.verifyNoMoreInteractions(otlpHttpSpanExporterBuilder); } @Test @@ -68,99 +58,4 @@ void otlpTracesDisabledOld() { .withPropertyValues("otel.exporter.otlp.traces.enabled=false") .run(context -> assertThat(context.containsBean("otelOtlpSpanExporter")).isFalse()); } - - @Test - void otlpTracesDisabled() { - this.contextRunner - .withPropertyValues("otel.traces.exporter=none") - .run(context -> assertThat(context.containsBean("otelOtlpSpanExporter")).isFalse()); - } - - @Test - @DisplayName("when otlp enabled property is MISSING should initialize OtlpHttpSpanExporter bean") - void exporterPresentByDefault() { - this.contextRunner.run( - context -> - assertThat(context.getBean("otelOtlpSpanExporter", OtlpHttpSpanExporter.class)) - .isNotNull()); - } - - @Test - @DisplayName("use http/protobuf when protocol set") - void useHttp() { - this.contextRunner - .withBean(OtlpHttpSpanExporterBuilder.class, () -> otlpHttpSpanExporterBuilder) - .withPropertyValues( - "otel.exporter.otlp.enabled=true", - "otel.exporter.otlp.protocol=http/protobuf", - "otel.exporter.otlp.endpoint=http://localhost:4317", - "otel.exporter.otlp.headers.x=1", - "otel.exporter.otlp.headers.y=2", - "otel.exporter.otlp.timeout=1s") - .run(context -> {}); - - Mockito.verify(otlpHttpSpanExporterBuilder).build(); - Mockito.verify(otlpHttpSpanExporterBuilder).setEndpoint("http://localhost:4317/v1/traces"); - Mockito.verify(otlpHttpSpanExporterBuilder).addHeader("x", "1"); - Mockito.verify(otlpHttpSpanExporterBuilder).addHeader("y", "2"); - Mockito.verify(otlpHttpSpanExporterBuilder).setTimeout(java.time.Duration.ofSeconds(1)); - Mockito.verifyNoMoreInteractions(otlpHttpSpanExporterBuilder); - } - - @Test - @DisplayName("use http/protobuf with environment variables for headers using the MapConverter") - void useHttpWithEnv() { - this.contextRunner - .withBean(OtlpHttpSpanExporterBuilder.class, () -> otlpHttpSpanExporterBuilder) - .withPropertyValues( - "otel.exporter.otlp.enabled=true", "otel.exporter.otlp.protocol=http/protobuf") - // are similar to environment variables in that they use the same converters - .withSystemProperties("otel.exporter.otlp.headers=x=1,y=2") - .run(context -> {}); - - Mockito.verify(otlpHttpSpanExporterBuilder).build(); - Mockito.verify(otlpHttpSpanExporterBuilder).addHeader("x", "1"); - Mockito.verify(otlpHttpSpanExporterBuilder).addHeader("y", "2"); - Mockito.verifyNoMoreInteractions(otlpHttpSpanExporterBuilder); - } - - @Test - @DisplayName("use grpc when protocol set") - void useGrpc() { - this.contextRunner - .withPropertyValues("otel.exporter.otlp.protocol=grpc") - .run( - context -> - assertThat(context.getBean(OtlpGrpcSpanExporter.class)) - .as("Should contain the gRPC span exporter when grpc is set") - .isNotNull()); - } - - @Test - @DisplayName("use http when unknown protocol set") - void useHttpWhenAnUnknownProtocolIsSet() { - this.contextRunner - .withPropertyValues("otel.exporter.otlp.protocol=unknown") - .run( - context -> - assertThat(context.getBean(OtlpHttpSpanExporter.class)) - .as("Should contain the http span exporter when an unknown is set") - .isNotNull()); - } - - @Test - @DisplayName("logging exporter can still be configured") - void loggingExporter() { - this.contextRunner - .withBean( - LoggingSpanExporter.class, - LoggingSpanExporter::create, - bd -> bd.setDestroyMethodName("")) - .run( - context -> - assertThat( - context.getBeanProvider(SpanExporter.class).stream() - .collect(Collectors.toList())) - .hasSize(2)); - } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java similarity index 81% rename from instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigPropertiesTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java index 93756ae1c4ed..779b974db8ad 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringResourceConfigPropertiesTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/resources/SpringConfigPropertiesTest.java @@ -8,13 +8,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpExporterProperties; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.core.env.Environment; import org.springframework.expression.spel.standard.SpelExpressionParser; -class SpringResourceConfigPropertiesTest { +class SpringConfigPropertiesTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); @Test @@ -26,8 +27,9 @@ void shouldInitializeAttributesByMapInArow() { .run( context -> { Environment env = context.getBean("environment", Environment.class); - SpringResourceConfigProperties config = - new SpringResourceConfigProperties(env, new SpelExpressionParser()); + SpringConfigProperties config = + new SpringConfigProperties( + env, new SpelExpressionParser(), new OtlpExporterProperties()); assertThat(config.getMap("otel.springboot.test.map")) .contains(