From 71bce02440aba448a1b6f696c50dfafe82f9e274 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 11 Jun 2025 03:09:53 +0200 Subject: [PATCH] fix map converter (#13972) --- .../OpenTelemetryAutoConfiguration.java | 36 +++++++++---------- .../SpringConfigPropertiesTest.java | 14 ++++++++ 2 files changed, 31 insertions(+), 19 deletions(-) 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 6b2a99d0c5..44defb2fe3 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 @@ -41,6 +41,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; import org.springframework.core.env.Environment; /** @@ -62,18 +63,26 @@ public class OpenTelemetryAutoConfiguration { public OpenTelemetryAutoConfiguration() {} + @Bean + @ConfigurationPropertiesBinding + OtelMapConverter otelMapConverter() { + // This is needed for otlp exporter headers and OtelResourceProperties. + + // We need this converter, even if the SDK is disabled, + // because the properties are parsed before the SDK is disabled. + + // We also need this converter if the OpenTelemetry bean is user supplied, + // because the environment variables may still contain a value that needs to be converted, + // even if the SDK is disabled (and the value thus ignored). + return new OtelMapConverter(); + } + @Configuration @Conditional(SdkEnabled.class) + @DependsOn("otelMapConverter") @ConditionalOnMissingBean(OpenTelemetry.class) static class OpenTelemetrySdkConfig { - @Bean - @ConfigurationPropertiesBinding - public OtelMapConverter otelMapConverter() { - // needed for otlp exporter headers and OtelResourceProperties - return new OtelMapConverter(); - } - @Bean public OpenTelemetrySdkComponentLoader openTelemetrySdkComponentLoader( ApplicationContext applicationContext) { @@ -139,21 +148,10 @@ public class OpenTelemetryAutoConfiguration { } @Configuration + @DependsOn("otelMapConverter") @ConditionalOnMissingBean(OpenTelemetry.class) @ConditionalOnProperty(name = "otel.sdk.disabled", havingValue = "true") static class DisabledOpenTelemetrySdkConfig { - - @Bean - @ConfigurationPropertiesBinding - // Duplicated in OpenTelemetrySdkConfig and DisabledOpenTelemetrySdkConfig to not expose the - // converter in the public API - public OtelMapConverter otelMapConverter() { - // needed for otlp exporter headers and OtelResourceProperties - // we need this converter, even if the SDK is disabled, - // because the properties are parsed before the SDK is disabled - return new OtelMapConverter(); - } - @Bean public OpenTelemetry openTelemetry() { logger.info("OpenTelemetry Spring Boot starter has been disabled"); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java index 8bb38dc453..9754ccb3b7 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/SpringConfigPropertiesTest.java @@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.propertie import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; @@ -77,6 +78,19 @@ class SpringConfigPropertiesTest { .containsExactly(entry("a", "1"), entry("b", "2"))); } + @ParameterizedTest + @MethodSource("headerKeys") + @DisplayName("should map headers from spring properties with user supplied OpenTelemetry bean") + void mapFlatHeadersWithUserSuppliedOtelBean(String key) { + this.contextRunner + .withSystemProperties(key + "=a=1,b=2") + .withBean(OpenTelemetry.class, OpenTelemetry::noop) + .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")