From 8b99d2d80b8f50d104d8722ce0654564be8dfeec Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 15:46:22 +0200 Subject: [PATCH 01/48] declarative config --- .../spring/autoconfigure/internal/OtelMapConverter.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java index e32cfb75f5b1..c0bfa6fcc9ca 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java @@ -17,6 +17,13 @@ *

This is the expected format for the OTEL_RESOURCE_ATTRIBUTES and * OTEL_EXPORTER_OTLP_HEADERS environment variables. * + *

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). + * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ From 1ef114850a9815edf385a88c73dfd33281deb894 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 16:10:25 +0200 Subject: [PATCH 02/48] isolate map converter --- .../spring/autoconfigure/internal/OtelMapConverter.java | 7 ------- .../internal/properties/SpringConfigPropertiesTest.java | 6 +++--- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java index c0bfa6fcc9ca..e32cfb75f5b1 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelMapConverter.java @@ -17,13 +17,6 @@ *

This is the expected format for the OTEL_RESOURCE_ATTRIBUTES and * OTEL_EXPORTER_OTLP_HEADERS environment variables. * - *

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). - * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ 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 02433342b1ab..96c0245747d7 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 @@ -86,9 +86,9 @@ void mapFlatHeadersWithUserSuppliedOtelBean(String key) { .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"))); + context -> { + // don't crash if OpenTelemetry bean is provided + }); } @ParameterizedTest From 92c661876a93ee41e136623b28ac3af90fb1f87e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 16:27:11 +0200 Subject: [PATCH 03/48] embedded config file --- .../build.gradle.kts | 1 + .../autoconfigure/EmbeddedConfigFile.java | 89 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index c3010d5e8aff..3e0b9680a770 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { annotationProcessor("org.springframework.boot:spring-boot-autoconfigure-processor:$springBootVersion") annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:$springBootVersion") implementation("javax.validation:validation-api") + implementation("com.fasterxml.jackson.core:jackson-core") implementation(project(":instrumentation-annotations-support")) implementation(project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library")) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java new file mode 100644 index 000000000000..c12da3907fbf --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java @@ -0,0 +1,89 @@ +package io.opentelemetry.instrumentation.spring.autoconfigure; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.incubator.config.GlobalConfigProvider; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import org.springframework.boot.env.OriginTrackedMapPropertySource; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertySource; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +class EmbeddedConfigFile { + + private static final Pattern PATTERN = Pattern.compile( + "^Config resource 'class path resource \\[(.+)]' via location 'optional:classpath:/'$" + ); + + static OpenTelemetryConfigurationModel extractModel(ConfigurableEnvironment environment) + throws IOException { + for (PropertySource propertySource : environment.getPropertySources()) { + if (propertySource instanceof OriginTrackedMapPropertySource) { + OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) propertySource; + String name = source.getName(); + System.out.println("Property Source: " + name); // todo remove + Matcher matcher = PATTERN.matcher(name); + if (matcher.matches()) { + String file = matcher.group(1); + System.out.println("Found application.yaml: " + file); + + try (InputStream resourceAsStream = + environment.getClass().getClassLoader().getResourceAsStream(file)) { + // Print the contents of the application.yaml file + if (resourceAsStream != null) { + String content = new String(resourceAsStream.readAllBytes()); + System.out.println("Contents of " + file + ":"); // todo remove + System.out.println(content); // todo remove + + extractOtelConfigFile(content); + } else { + System.out.println("Could not find the application.yaml file in the classpath."); // todo remove + } + } + } + } + } + } + + private static void extractOtelConfigFile(String content) throws IOException { + // + // https://github.com/open-telemetry/opentelemetry-configuration/blob/c205770a956713e512eddb056570a99737e3383a/examples/kitchen-sink.yaml#L11 + + // 1. read to yaml tree in jackson + ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); + JsonNode rootNode = yamlMapper.readTree(content); + + // 2. find the "otel" node + JsonNode otelNode = rootNode.get("otel"); + if (otelNode == null) { + System.out.println("No 'otel' configuration found in the YAML file."); // todo remove + return; + } + + String str = yamlMapper.writeValueAsString(otelNode); + + OpenTelemetryConfigurationModel model = + DeclarativeConfiguration.parse( + new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + OpenTelemetrySdk sdk = + DeclarativeConfiguration.create(model); // can pass ComponentLoader as second arg + + Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); + + GlobalOpenTelemetry.set(sdk); + GlobalConfigProvider.set(SdkConfigProvider.create(model)); + + System.out.println("OpenTelemetry SDK initialized with configuration from: " + sdk); // todo remove + System.out.println("OpenTelemetry configuration file content:"); // todo remove + System.out.println(str); // todo remove + } +} From 4fb136317dec7a5763bc81c80162440a442e2338 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 17:10:32 +0200 Subject: [PATCH 04/48] embedded config file --- .../build.gradle.kts | 4 +- .../autoconfigure/EmbeddedConfigFile.java | 123 +++++++------ .../OpenTelemetryAutoConfiguration.java | 166 ++++++++++++------ 3 files changed, 183 insertions(+), 110 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 3e0b9680a770..1e6f65737a85 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -35,7 +35,9 @@ dependencies { annotationProcessor("org.springframework.boot:spring-boot-autoconfigure-processor:$springBootVersion") annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:$springBootVersion") implementation("javax.validation:validation-api") - implementation("com.fasterxml.jackson.core:jackson-core") + // snake yaml is already used by "spring-boot-resources" + // and less likely to cause problems compared to jackson + implementation("org.snakeyaml:snakeyaml-engine") implementation(project(":instrumentation-annotations-support")) implementation(project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library")) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java index c12da3907fbf..0a8b6db1aa27 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java @@ -1,89 +1,104 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.incubator.config.GlobalConfigProvider; -import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; -import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import org.springframework.boot.env.OriginTrackedMapPropertySource; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.PropertySource; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nullable; +import org.snakeyaml.engine.v2.api.Dump; +import org.snakeyaml.engine.v2.api.DumpSettings; +import org.snakeyaml.engine.v2.api.Load; +import org.snakeyaml.engine.v2.api.LoadSettings; +import org.springframework.boot.env.OriginTrackedMapPropertySource; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.PropertySource; class EmbeddedConfigFile { - private static final Pattern PATTERN = Pattern.compile( - "^Config resource 'class path resource \\[(.+)]' via location 'optional:classpath:/'$" - ); + private EmbeddedConfigFile() { + // Utility class + } + + private static final Pattern PATTERN = + Pattern.compile( + "^Config resource 'class path resource \\[(.+)]' via location 'optional:classpath:/'$"); static OpenTelemetryConfigurationModel extractModel(ConfigurableEnvironment environment) throws IOException { for (PropertySource propertySource : environment.getPropertySources()) { if (propertySource instanceof OriginTrackedMapPropertySource) { - OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) propertySource; - String name = source.getName(); - System.out.println("Property Source: " + name); // todo remove - Matcher matcher = PATTERN.matcher(name); - if (matcher.matches()) { - String file = matcher.group(1); - System.out.println("Found application.yaml: " + file); + return getModel(environment, (OriginTrackedMapPropertySource) propertySource); + } + } + throw new IllegalStateException("No application.yaml file found."); + } + + private static OpenTelemetryConfigurationModel getModel( + ConfigurableEnvironment environment, OriginTrackedMapPropertySource source) + throws IOException { + String name = source.getName(); + System.out.println("Property Source: " + name); // todo remove + Matcher matcher = PATTERN.matcher(name); + if (matcher.matches()) { + String file = matcher.group(1); + System.out.println("Found application.yaml: " + file); - try (InputStream resourceAsStream = - environment.getClass().getClassLoader().getResourceAsStream(file)) { - // Print the contents of the application.yaml file - if (resourceAsStream != null) { - String content = new String(resourceAsStream.readAllBytes()); - System.out.println("Contents of " + file + ":"); // todo remove - System.out.println(content); // todo remove + try (InputStream resourceAsStream = + environment.getClass().getClassLoader().getResourceAsStream(file)) { + // Print the contents of the application.yaml file + if (resourceAsStream != null) { + // String content = new String(resourceAsStream.readAllBytes()); + // System.out.println("Contents of " + file + ":"); // todo remove + // System.out.println(content); // todo remove - extractOtelConfigFile(content); - } else { - System.out.println("Could not find the application.yaml file in the classpath."); // todo remove - } - } + return extractOtelConfigFile(resourceAsStream); + } else { + throw new IllegalStateException("Unable to load " + file + " in the classpath."); } } + } else { + throw new IllegalStateException( + "No OpenTelemetry configuration found in the application.yaml file."); + } + } + + @Nullable + @SuppressWarnings("unchecked") + private static String parseOtelNode(InputStream in) { + Load load = new Load(LoadSettings.builder().build()); + Dump dump = new Dump(DumpSettings.builder().build()); + for (Object o : load.loadAllFromInputStream(in)) { + Map data = (Map) o; + Map> otel = (Map>) data.get("otel"); + if (otel != null) { + return dump.dumpToString(otel); + } } + throw new IllegalStateException("No 'otel' configuration found in the YAML file."); } - private static void extractOtelConfigFile(String content) throws IOException { + private static OpenTelemetryConfigurationModel extractOtelConfigFile(InputStream content) { // // https://github.com/open-telemetry/opentelemetry-configuration/blob/c205770a956713e512eddb056570a99737e3383a/examples/kitchen-sink.yaml#L11 // 1. read to yaml tree in jackson - ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); - JsonNode rootNode = yamlMapper.readTree(content); + // ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); + // JsonNode rootNode = yamlMapper.readTree(content); - // 2. find the "otel" node - JsonNode otelNode = rootNode.get("otel"); - if (otelNode == null) { - System.out.println("No 'otel' configuration found in the YAML file."); // todo remove - return; + String node = parseOtelNode(content); + if (node == null || node.isEmpty()) { + throw new IllegalStateException("otel node is empty or null in the YAML file."); } - String str = yamlMapper.writeValueAsString(otelNode); - - OpenTelemetryConfigurationModel model = - DeclarativeConfiguration.parse( - new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); - OpenTelemetrySdk sdk = - DeclarativeConfiguration.create(model); // can pass ComponentLoader as second arg - - Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - - GlobalOpenTelemetry.set(sdk); - GlobalConfigProvider.set(SdkConfigProvider.create(model)); + System.out.println("OpenTelemetry configuration file content:"); // todo remove + System.out.println(node); // todo remove - System.out.println("OpenTelemetry SDK initialized with configuration from: " + sdk); // todo remove - System.out.println("OpenTelemetry configuration file content:"); // todo remove - System.out.println(str); // todo remove + return DeclarativeConfiguration.parse( + new ByteArrayInputStream(node.getBytes(StandardCharsets.UTF_8))); } } 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 b9a9bd7c9a2a..598cdf4ebfc4 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 @@ -5,10 +5,12 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; +import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.GlobalConfigProvider; import io.opentelemetry.api.trace.TracerProvider; -import io.opentelemetry.common.ComponentLoader; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; +import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridge; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelMapConverter; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties; @@ -17,12 +19,18 @@ import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.SpringConfigProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.DistroVersionResourceProvider; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.SpringResourceProvider; +import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -41,7 +49,7 @@ 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.ConfigurableEnvironment; import org.springframework.core.env.Environment; /** @@ -52,39 +60,19 @@ *

Updates the sampler probability for the configured {@link TracerProvider}. */ @Configuration -@EnableConfigurationProperties({ - OtlpExporterProperties.class, - OtelResourceProperties.class, - OtelSpringProperties.class -}) public class OpenTelemetryAutoConfiguration { private static final Logger logger = LoggerFactory.getLogger(OpenTelemetryAutoConfiguration.class); 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 - public OpenTelemetrySdkComponentLoader openTelemetrySdkComponentLoader( + public ComponentLoader openTelemetrySdkComponentLoader( ApplicationContext applicationContext) { return new OpenTelemetrySdkComponentLoader(applicationContext); } @@ -99,53 +87,122 @@ public ResourceProvider otelDistroVersionResourceProvider() { return new DistroVersionResourceProvider(); } + @Configuration + @EnableConfigurationProperties({ + OtlpExporterProperties.class, + OtelResourceProperties.class, + OtelSpringProperties.class + }) + @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") + static class PropertiesConfig { + + @Bean + @ConfigurationPropertiesBinding + OtelMapConverter otelMapConverter() { + return new OtelMapConverter(); + } + + @Bean + public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk( + Environment env, + OtlpExporterProperties otlpExporterProperties, + OtelResourceProperties resourceProperties, + OtelSpringProperties otelSpringProperties, + ComponentLoader componentLoader) { + + return AutoConfigureUtil.setComponentLoader( + AutoConfigureUtil.setConfigPropertiesCustomizer( + AutoConfiguredOpenTelemetrySdk.builder(), + c -> + SpringConfigProperties.create( + env, + otlpExporterProperties, + resourceProperties, + otelSpringProperties, + c)), + componentLoader) + .build(); + } + + @Bean + public OpenTelemetry openTelemetry( + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + logStart(); + return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk(); + } + + /** + * Expose the {@link ConfigProperties} bean for use in other auto-configurations. + * + *

Not using spring boot properties directly in order to support {@link + * io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer#addPropertiesCustomizer(Function)} + * and {@link + * io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer#addPropertiesSupplier(Supplier)}. + */ + @Bean + public ConfigProperties otelProperties( + AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + return AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); + } + } + + @Configuration + @ConditionalOnProperty(name = "otel.file_format") + static class EmbeddedConfigFileConfig { + @Bean - public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk( - Environment env, - OtlpExporterProperties otlpExporterProperties, - OtelResourceProperties resourceProperties, - OtelSpringProperties otelSpringProperties, - OpenTelemetrySdkComponentLoader componentLoader) { - - return AutoConfigureUtil.setConfigPropertiesCustomizer( - AutoConfiguredOpenTelemetrySdk.builder().setComponentLoader(componentLoader), - c -> - SpringConfigProperties.create( - env, otlpExporterProperties, resourceProperties, otelSpringProperties, c)) - .build(); + public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( + ConfigurableEnvironment environment) throws IOException { + return EmbeddedConfigFile.extractModel(environment); } @Bean - public OpenTelemetry openTelemetry( - AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - logger.info( - "OpenTelemetry Spring Boot starter ({}) has been started", - EmbeddedInstrumentationProperties.findVersion( - "io.opentelemetry.spring-boot-autoconfigure")); - - return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk(); + public OpenTelemetry openTelemetry(OpenTelemetryConfigurationModel model, ComponentLoader componentLoader) { + OpenTelemetrySdk sdk = + DeclarativeConfiguration.create(model, componentLoader); + + Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); + + GlobalOpenTelemetry.set(sdk); + GlobalConfigProvider.set(SdkConfigProvider.create(model)); + + System.out.println( + "OpenTelemetry SDK initialized with configuration from: " + sdk); // todo remove + + // todo declarative configuration + // todo map converter not needed here, because the declarative configuration is not using + // environment variables + + logStart(); + + return null; } /** * Expose the {@link ConfigProperties} bean for use in other auto-configurations. * - *

Not using spring boot properties directly in order to support {@link - * io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer#addPropertiesCustomizer(Function)} - * and {@link - * io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer#addPropertiesSupplier(Supplier)}. + *

Not using spring boot properties directly, because declarative configuration does not + * integrate with spring boot properties. */ @Bean - public ConfigProperties otelProperties( - AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - return AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); + public ConfigProperties otelProperties(OpenTelemetryConfigurationModel model) { + return DeclarativeConfigPropertiesBridge.create( + DeclarativeConfiguration.toConfigProperties(model)); } } + private static void logStart() { + logger.info( + "OpenTelemetry Spring Boot starter ({}) has been started", + EmbeddedInstrumentationProperties.findVersion( + "io.opentelemetry.spring-boot-autoconfigure")); + } + @Configuration - @DependsOn("otelMapConverter") @ConditionalOnMissingBean(OpenTelemetry.class) @ConditionalOnProperty(name = "otel.sdk.disabled", havingValue = "true") static class DisabledOpenTelemetrySdkConfig { + @Bean public OpenTelemetry openTelemetry() { logger.info("OpenTelemetry Spring Boot starter has been disabled"); @@ -164,9 +221,8 @@ public ConfigProperties otelProperties() { @ConditionalOnMissingBean({ConfigProperties.class}) static class FallbackConfigProperties { @Bean - public ConfigProperties otelProperties(ApplicationContext applicationContext) { - return DefaultConfigProperties.create( - Collections.emptyMap(), new OpenTelemetrySdkComponentLoader(applicationContext)); + public ConfigProperties otelProperties() { + return DefaultConfigProperties.create(Collections.emptyMap()); } } From 6bd882e37f2344e15f0d988453a26ce09a50702f Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 17:26:06 +0200 Subject: [PATCH 05/48] config bridge --- .../OpenTelemetryAutoConfiguration.java | 28 +++++++++++++------ .../properties/ConfigPropertiesBridge.java | 15 ++++++++-- 2 files changed, 32 insertions(+), 11 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 598cdf4ebfc4..ff379ca3ad51 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 @@ -5,14 +5,16 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.incubator.config.GlobalConfigProvider; import io.opentelemetry.api.trace.TracerProvider; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridge; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelMapConverter; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelSpringProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties; @@ -72,8 +74,7 @@ public OpenTelemetryAutoConfiguration() {} static class OpenTelemetrySdkConfig { @Bean - public ComponentLoader openTelemetrySdkComponentLoader( - ApplicationContext applicationContext) { + public ComponentLoader openTelemetrySdkComponentLoader(ApplicationContext applicationContext) { return new OpenTelemetrySdkComponentLoader(applicationContext); } @@ -157,14 +158,14 @@ public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( } @Bean - public OpenTelemetry openTelemetry(OpenTelemetryConfigurationModel model, ComponentLoader componentLoader) { - OpenTelemetrySdk sdk = - DeclarativeConfiguration.create(model, componentLoader); + public OpenTelemetry openTelemetry( + OpenTelemetryConfigurationModel model, ComponentLoader componentLoader) { + OpenTelemetrySdk sdk = DeclarativeConfiguration.create(model, componentLoader); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - GlobalOpenTelemetry.set(sdk); - GlobalConfigProvider.set(SdkConfigProvider.create(model)); + SdkConfigProvider configProvider = SdkConfigProvider.create(model); + GlobalConfigProvider.set(configProvider); System.out.println( "OpenTelemetry SDK initialized with configuration from: " + sdk); // todo remove @@ -178,6 +179,17 @@ public OpenTelemetry openTelemetry(OpenTelemetryConfigurationModel model, Compon return null; } + @Bean + public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { + return SdkConfigProvider.create(model); + } + + @Bean + public InstrumentationConfig instrumentationConfig( + ConfigProperties properties, ConfigProvider configProvider) { + return new ConfigPropertiesBridge(properties, configProvider); + } + /** * Expose the {@link ConfigProperties} bean for use in other auto-configurations. * diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java index 047d2ee809ea..f5433573a2e4 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.api.incubator.config.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; @@ -24,9 +25,16 @@ public final class ConfigPropertiesBridge implements InstrumentationConfig { private final ConfigProperties configProperties; + @Nullable private final ConfigProvider configProvider; public ConfigPropertiesBridge(ConfigProperties configProperties) { + this(configProperties, null); + } + + public ConfigPropertiesBridge( + ConfigProperties configProperties, @Nullable ConfigProvider configProvider) { this.configProperties = configProperties; + this.configProvider = configProvider; } @Nullable @@ -124,8 +132,9 @@ public DeclarativeConfigProperties getDeclarativeConfig(String node) { @Nullable @Override - public ConfigProvider getConfigProvider() { - // declarative config support will be added in the future - return null; + public DeclarativeConfigProperties getDeclarativeConfig(String instrumentationName) { + return configProvider != null + ? InstrumentationConfigUtil.javaInstrumentationConfig(configProvider, instrumentationName) + : null; } } From b65d454ae9fce89293fc3a8bab79050f66bf3a76 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 17:30:35 +0200 Subject: [PATCH 06/48] config bridge --- .../OpenTelemetryAutoConfiguration.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 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 ff379ca3ad51..1bb8aba1ea43 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 @@ -6,7 +6,6 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.incubator.config.GlobalConfigProvider; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; @@ -132,6 +131,12 @@ public OpenTelemetry openTelemetry( return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk(); } + @Bean + public InstrumentationConfig instrumentationConfig( + ConfigProperties properties) { + return new ConfigPropertiesBridge(properties); + } + /** * Expose the {@link ConfigProperties} bean for use in other auto-configurations. * @@ -179,15 +184,10 @@ public OpenTelemetry openTelemetry( return null; } - @Bean - public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { - return SdkConfigProvider.create(model); - } - @Bean public InstrumentationConfig instrumentationConfig( - ConfigProperties properties, ConfigProvider configProvider) { - return new ConfigPropertiesBridge(properties, configProvider); + ConfigProperties properties, OpenTelemetryConfigurationModel model) { + return new ConfigPropertiesBridge(properties, SdkConfigProvider.create(model)); } /** From 5da12b32e70b24d75eb144093ca0d6bfd0ce9a21 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 17:54:08 +0200 Subject: [PATCH 07/48] use InstrumentationConfig for encapsulation --- .../autoconfigure/EmbeddedConfigFile.java | 5 ++++ .../OpenTelemetryAutoConfiguration.java | 3 +-- .../jdbc/DataSourcePostProcessor.java | 26 +++++++++---------- .../JdbcInstrumentationAutoConfiguration.java | 6 ++--- ...KafkaInstrumentationAutoConfiguration.java | 10 +++---- ...lientInstrumentationAutoConfiguration.java | 4 +-- ...R2dbcInstrumentationAutoConfiguration.java | 6 ++--- .../R2dbcInstrumentingPostProcessor.java | 10 +++---- ...SpringSchedulingInstrumentationAspect.java | 6 ++--- ...ulingInstrumentationAutoConfiguration.java | 6 ++--- .../web/RestTemplateBeanPostProcessor.java | 12 ++++----- .../web/RestTemplateInstrumentation.java | 4 +-- ...ngWebInstrumentationAutoConfiguration.java | 10 +++---- ...bfluxInstrumentationAutoConfiguration.java | 8 +++--- .../webflux/WebClientBeanPostProcessor.java | 15 +++++------ ...bMvc5InstrumentationAutoConfiguration.java | 4 +-- .../properties/InstrumentationConfigUtil.java | 12 ++++----- .../web/RestClientBeanPostProcessor.java | 14 +++++----- ...lientInstrumentationAutoConfiguration.java | 9 +++---- ...bMvc6InstrumentationAutoConfiguration.java | 3 +-- .../SchedulingInstrumentationAspectTest.java | 5 ++-- 21 files changed, 88 insertions(+), 90 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java index 0a8b6db1aa27..944069026aa1 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java @@ -1,3 +1,8 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.spring.autoconfigure; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; 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 1bb8aba1ea43..e0242d73856f 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 @@ -132,8 +132,7 @@ public OpenTelemetry openTelemetry( } @Bean - public InstrumentationConfig instrumentationConfig( - ConfigProperties properties) { + public InstrumentationConfig instrumentationConfig(ConfigProperties properties) { return new ConfigPropertiesBridge(properties); } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java index a1a615a31fba..859f8366b9d2 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java @@ -7,6 +7,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -28,13 +29,13 @@ final class DataSourcePostProcessor implements BeanPostProcessor, Ordered { private static final Class ROUTING_DATA_SOURCE_CLASS = getRoutingDataSourceClass(); private final ObjectProvider openTelemetryProvider; - private final ObjectProvider configPropertiesProvider; + private final ObjectProvider configProvider; DataSourcePostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { this.openTelemetryProvider = openTelemetryProvider; - this.configPropertiesProvider = configPropertiesProvider; + this.configProvider = configProvider; } private static Class getRoutingDataSourceClass() { @@ -57,21 +58,18 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { && !isRoutingDatasource(bean) && !ScopedProxyUtils.isScopedTarget(beanName)) { DataSource dataSource = (DataSource) bean; + InstrumentationConfig config = configProvider.getObject(); DataSource otelDataSource = - JdbcTelemetry.builder(openTelemetryProvider.getObject()) + JdbcTelemetry.builder(openTelemetryProvider.getObject()) .setStatementSanitizationEnabled( InstrumentationConfigUtil.isStatementSanitizationEnabled( - configPropertiesProvider.getObject(), - "otel.instrumentation.jdbc.statement-sanitizer.enabled")) + config, "otel.instrumentation.jdbc.statement-sanitizer.enabled")) .setCaptureQueryParameters( - configPropertiesProvider - .getObject() - .getBoolean( - "otel.instrumentation.jdbc.experimental.capture-query-parameters", false)) - .setTransactionInstrumenterEnabled( - configPropertiesProvider - .getObject() - .getBoolean( + config.getBoolean( + "otel.instrumentation.jdbc.experimental.capture-query-parameters", false)) + .setTransactionInstrumenterEnabled( + config.getBoolean( + "otel.instrumentation.jdbc.experimental.transaction.enabled", false)) .build() .wrap(dataSource); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java index 3ec55a5a06c2..1732c3be178d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfiguration.java @@ -6,8 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.jdbc; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import javax.sql.DataSource; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -33,7 +33,7 @@ public JdbcInstrumentationAutoConfiguration() {} // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning static DataSourcePostProcessor dataSourcePostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { - return new DataSourcePostProcessor(openTelemetryProvider, configPropertiesProvider); + ObjectProvider configProvider) { + return new DataSourcePostProcessor(openTelemetryProvider, configProvider); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java index 44f845e25ff1..4df611685733 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/kafka/KafkaInstrumentationAutoConfiguration.java @@ -6,10 +6,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.kafka; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -42,10 +42,10 @@ DefaultKafkaProducerFactoryCustomizer otelKafkaProducerFactoryCustomizer( @Bean static SpringKafkaTelemetry getTelemetry( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { return SpringKafkaTelemetry.builder(openTelemetryProvider.getObject()) .setCaptureExperimentalSpanAttributes( - configPropertiesProvider + configProvider .getObject() .getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false)) .build(); @@ -60,8 +60,8 @@ static SpringKafkaTelemetry getTelemetry( static ConcurrentKafkaListenerContainerFactoryPostProcessor otelKafkaListenerContainerFactoryBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { return new ConcurrentKafkaListenerContainerFactoryPostProcessor( - () -> getTelemetry(openTelemetryProvider, configPropertiesProvider)); + () -> getTelemetry(openTelemetryProvider, configProvider)); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java index 39a56a8b07c4..2c370a8afc49 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/mongo/MongoClientInstrumentationAutoConfiguration.java @@ -7,10 +7,10 @@ import com.mongodb.MongoClientSettings; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; @@ -29,7 +29,7 @@ public class MongoClientInstrumentationAutoConfiguration { @Bean MongoClientSettingsBuilderCustomizer customizer( - OpenTelemetry openTelemetry, ConfigProperties config) { + OpenTelemetry openTelemetry, InstrumentationConfig config) { return builder -> builder.addCommandListener( MongoTelemetry.builder(openTelemetry) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java index d744b8fe1dc4..254297f2eafa 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentationAutoConfiguration.java @@ -6,8 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.r2dbc.spi.ConnectionFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -31,7 +31,7 @@ public R2dbcInstrumentationAutoConfiguration() {} // static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning static R2dbcInstrumentingPostProcessor r2dbcInstrumentingPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { - return new R2dbcInstrumentingPostProcessor(openTelemetryProvider, configPropertiesProvider); + ObjectProvider configProvider) { + return new R2dbcInstrumentingPostProcessor(openTelemetryProvider, configProvider); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java index 5d75b28946ef..09849deef13b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2dbcInstrumentingPostProcessor.java @@ -6,9 +6,9 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.r2dbc; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.r2dbc.v1_0.internal.shaded.R2dbcTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactoryOptions; import org.springframework.aop.scope.ScopedProxyUtils; @@ -19,13 +19,13 @@ class R2dbcInstrumentingPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - private final ObjectProvider configPropertiesProvider; + private final ObjectProvider configProvider; R2dbcInstrumentingPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { this.openTelemetryProvider = openTelemetryProvider; - this.configPropertiesProvider = configPropertiesProvider; + this.configProvider = configProvider; } @Override @@ -35,7 +35,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { return R2dbcTelemetry.builder(openTelemetryProvider.getObject()) .setStatementSanitizationEnabled( InstrumentationConfigUtil.isStatementSanitizationEnabled( - configPropertiesProvider.getObject(), + configProvider.getObject(), "otel.instrumentation.r2dbc.statement-sanitizer.enabled")) .build() .wrapConnectionFactory(connectionFactory, getConnectionFactoryOptions(connectionFactory)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAspect.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAspect.java index 5dfec2280e8e..6d84cde77985 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAspect.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAspect.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter; import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeSpanNameExtractor; @@ -16,7 +17,6 @@ import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -43,7 +43,7 @@ final class SpringSchedulingInstrumentationAspect { private final Instrumenter instrumenter; public SpringSchedulingInstrumentationAspect( - OpenTelemetry openTelemetry, ConfigProperties configProperties) { + OpenTelemetry openTelemetry, InstrumentationConfig config) { CodeAttributesGetter codedAttributesGetter = ClassAndMethod.codeAttributesGetter(); InstrumenterBuilder builder = @@ -52,7 +52,7 @@ public SpringSchedulingInstrumentationAspect( INSTRUMENTATION_NAME, CodeSpanNameExtractor.create(codedAttributesGetter)) .addAttributesExtractor(CodeAttributesExtractor.create(codedAttributesGetter)); - if (configProperties.getBoolean( + if (config.getBoolean( "otel.instrumentation.spring-scheduling.experimental-span-attributes", false)) { builder.addAttributesExtractor( AttributesExtractor.constant(AttributeKey.stringKey("job.system"), "spring_scheduling")); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAutoConfiguration.java index 8135bead9c0b..2d5e0fba7473 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SpringSchedulingInstrumentationAutoConfiguration.java @@ -6,8 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.aspectj.lang.annotation.Aspect; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -28,7 +28,7 @@ class SpringSchedulingInstrumentationAutoConfiguration { @Bean SpringSchedulingInstrumentationAspect springSchedulingInstrumentationAspect( - OpenTelemetry openTelemetry, ConfigProperties configProperties) { - return new SpringSchedulingInstrumentationAspect(openTelemetry, configProperties); + OpenTelemetry openTelemetry, InstrumentationConfig config) { + return new SpringSchedulingInstrumentationAspect(openTelemetry, config); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java index 0cda4b63d686..4db9b873fece 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateBeanPostProcessor.java @@ -6,7 +6,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.web.client.RestTemplate; @@ -15,13 +15,13 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - private final ObjectProvider configPropertiesProvider; + private final ObjectProvider configProvider; RestTemplateBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { this.openTelemetryProvider = openTelemetryProvider; - this.configPropertiesProvider = configPropertiesProvider; + this.configProvider = configProvider; } @Override @@ -31,8 +31,6 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { } return RestTemplateInstrumentation.addIfNotPresent( - (RestTemplate) bean, - openTelemetryProvider.getObject(), - configPropertiesProvider.getObject()); + (RestTemplate) bean, openTelemetryProvider.getObject(), configProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java index 9465c534d0ce..ca4c0c97c466 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestTemplateInstrumentation.java @@ -7,10 +7,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; import io.opentelemetry.instrumentation.spring.web.v3_1.internal.WebTelemetryUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.util.List; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; @@ -21,7 +21,7 @@ private RestTemplateInstrumentation() {} @CanIgnoreReturnValue static RestTemplate addIfNotPresent( - RestTemplate restTemplate, OpenTelemetry openTelemetry, ConfigProperties config) { + RestTemplate restTemplate, OpenTelemetry openTelemetry, InstrumentationConfig config) { ClientHttpRequestInterceptor instrumentationInterceptor = InstrumentationConfigUtil.configureClientBuilder( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java index 21a18ec8db2b..97d5bd9b52d5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfiguration.java @@ -6,8 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.web.client.RestTemplateCustomizer; @@ -34,16 +34,16 @@ public SpringWebInstrumentationAutoConfiguration() {} @Bean static RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { - return new RestTemplateBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); + ObjectProvider configProvider) { + return new RestTemplateBeanPostProcessor(openTelemetryProvider, configProvider); } @Bean RestTemplateCustomizer otelRestTemplateCustomizer( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { return restTemplate -> RestTemplateInstrumentation.addIfNotPresent( - restTemplate, openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); + restTemplate, openTelemetryProvider.getObject(), configProvider.getObject()); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java index ff6d8f9a5d0b..79bacde3ccc2 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java @@ -6,8 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -34,12 +34,12 @@ public SpringWebfluxInstrumentationAutoConfiguration() {} @Bean static WebClientBeanPostProcessor otelWebClientBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { - return new WebClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); + ObjectProvider configProvider) { + return new WebClientBeanPostProcessor(openTelemetryProvider, configProvider); } @Bean - WebFilter telemetryFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + WebFilter telemetryFilter(OpenTelemetry openTelemetry, InstrumentationConfig config) { return WebClientBeanPostProcessor.getWebfluxServerTelemetry(openTelemetry, config) .createWebFilterAndRegisterReactorHook(); } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java index 13a74048d3eb..9b501c410be3 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java @@ -6,11 +6,11 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxClientTelemetry; import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxServerTelemetry; import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.web.reactive.function.client.WebClient; @@ -23,17 +23,17 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - private final ObjectProvider configPropertiesProvider; + private final ObjectProvider configProvider; WebClientBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { this.openTelemetryProvider = openTelemetryProvider; - this.configPropertiesProvider = configPropertiesProvider; + this.configProvider = configProvider; } static SpringWebfluxClientTelemetry getWebfluxClientTelemetry( - OpenTelemetry openTelemetry, ConfigProperties config) { + OpenTelemetry openTelemetry, InstrumentationConfig config) { return InstrumentationConfigUtil.configureClientBuilder( config, SpringWebfluxClientTelemetry.builder(openTelemetry), @@ -42,7 +42,7 @@ static SpringWebfluxClientTelemetry getWebfluxClientTelemetry( } static SpringWebfluxServerTelemetry getWebfluxServerTelemetry( - OpenTelemetry openTelemetry, ConfigProperties config) { + OpenTelemetry openTelemetry, InstrumentationConfig config) { return InstrumentationConfigUtil.configureServerBuilder( config, SpringWebfluxServerTelemetry.builder(openTelemetry), @@ -64,8 +64,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) { SpringWebfluxClientTelemetry instrumentation = - getWebfluxClientTelemetry( - openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); + getWebfluxClientTelemetry(openTelemetryProvider.getObject(), configProvider.getObject()); return webClientBuilder.filters(instrumentation::addFilter); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java index 8d971c9d4890..73d3f657504c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc5InstrumentationAutoConfiguration.java @@ -6,11 +6,11 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetry; import io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal.SpringMvcBuilderUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import javax.servlet.Filter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -28,7 +28,7 @@ public class SpringWebMvc5InstrumentationAutoConfiguration { @Bean - Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + Filter otelWebMvcFilter(OpenTelemetry openTelemetry, InstrumentationConfig config) { return InstrumentationConfigUtil.configureServerBuilder( config, SpringWebMvcTelemetry.builder(openTelemetry), diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java index fb5e582bfaa5..683529a18b29 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import java.util.function.Function; /** @@ -21,7 +21,7 @@ private InstrumentationConfigUtil() {} @CanIgnoreReturnValue public static T configureClientBuilder( - ConfigProperties config, + InstrumentationConfig config, T builder, Function> getBuilder) { getBuilder.apply(builder).configure(getConfig(config)); @@ -30,18 +30,18 @@ public static T configureClientBuilder( @CanIgnoreReturnValue public static T configureServerBuilder( - ConfigProperties config, + InstrumentationConfig config, T builder, Function> getBuilder) { getBuilder.apply(builder).configure(getConfig(config)); return builder; } - private static CommonConfig getConfig(ConfigProperties config) { - return new CommonConfig(new ConfigPropertiesBridge(config)); + private static CommonConfig getConfig(InstrumentationConfig config) { + return new CommonConfig(config); } - public static boolean isStatementSanitizationEnabled(ConfigProperties config, String key) { + public static boolean isStatementSanitizationEnabled(InstrumentationConfig config, String key) { return config.getBoolean( key, config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true)); } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java index 8ebefdd655f6..9ef5b7f19194 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientBeanPostProcessor.java @@ -6,10 +6,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; import io.opentelemetry.instrumentation.spring.web.v3_1.internal.WebTelemetryUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.http.client.ClientHttpRequestInterceptor; @@ -18,26 +18,26 @@ final class RestClientBeanPostProcessor implements BeanPostProcessor { private final ObjectProvider openTelemetryProvider; - private final ObjectProvider configPropertiesProvider; + private final ObjectProvider configProvider; public RestClientBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { this.openTelemetryProvider = openTelemetryProvider; - this.configPropertiesProvider = configPropertiesProvider; + this.configProvider = configProvider; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { if (bean instanceof RestClient restClient) { return addRestClientInterceptorIfNotPresent( - restClient, openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); + restClient, openTelemetryProvider.getObject(), configProvider.getObject()); } return bean; } private static RestClient addRestClientInterceptorIfNotPresent( - RestClient restClient, OpenTelemetry openTelemetry, ConfigProperties config) { + RestClient restClient, OpenTelemetry openTelemetry, InstrumentationConfig config) { ClientHttpRequestInterceptor instrumentationInterceptor = getInterceptor(openTelemetry, config); return restClient @@ -55,7 +55,7 @@ private static RestClient addRestClientInterceptorIfNotPresent( } static ClientHttpRequestInterceptor getInterceptor( - OpenTelemetry openTelemetry, ConfigProperties config) { + OpenTelemetry openTelemetry, InstrumentationConfig config) { return InstrumentationConfigUtil.configureClientBuilder( config, SpringWebTelemetry.builder(openTelemetry), diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java index a0fad74b0a35..cc6915d9f08a 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java @@ -7,7 +7,6 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -34,17 +33,17 @@ public class RestClientInstrumentationAutoConfiguration { @Bean static RestClientBeanPostProcessor otelRestClientBeanPostProcessor( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { - return new RestClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider); + ObjectProvider configProvider) { + return new RestClientBeanPostProcessor(openTelemetryProvider, configProvider); } @Bean RestClientCustomizer otelRestClientCustomizer( ObjectProvider openTelemetryProvider, - ObjectProvider configPropertiesProvider) { + ObjectProvider configProvider) { return builder -> builder.requestInterceptor( RestClientBeanPostProcessor.getInterceptor( - openTelemetryProvider.getObject(), configPropertiesProvider.getObject())); + openTelemetryProvider.getObject(), configProvider.getObject())); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java index 2dc83966bc5f..e8759e614fdb 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java @@ -10,7 +10,6 @@ import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry; import io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal.SpringMvcBuilderUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import jakarta.servlet.Filter; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; @@ -28,7 +27,7 @@ public class SpringWebMvc6InstrumentationAutoConfiguration { @Bean - Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) { + Filter otelWebMvcFilter(OpenTelemetry openTelemetry, InstrumentationConfig config) { return InstrumentationConfigUtil.configureServerBuilder( config, SpringWebMvcTelemetry.builder(openTelemetry), diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java index d5fdb35b2bb8..61982f55afa8 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java @@ -13,6 +13,7 @@ import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -39,8 +40,8 @@ class SchedulingInstrumentationAspectTest { private String unproxiedTesterClassName; SpringSchedulingInstrumentationAspect newAspect( - OpenTelemetry openTelemetry, ConfigProperties configProperties) { - return new SpringSchedulingInstrumentationAspect(openTelemetry, configProperties); + OpenTelemetry openTelemetry, InstrumentationConfig config) { + return new SpringSchedulingInstrumentationAspect(openTelemetry, config); } @BeforeEach From 15c2890522ac774337a9cec44e1353f2ac535ffb Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 17:55:46 +0200 Subject: [PATCH 08/48] use InstrumentationConfig for encapsulation --- .../web/RestClientInstrumentationAutoConfiguration.java | 1 + .../webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java | 1 + 2 files changed, 2 insertions(+) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java index cc6915d9f08a..72c83ef5d5ad 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfiguration.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.AutoConfiguration; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java index e8759e614fdb..b8653d4d3936 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/javaSpring3/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvc6InstrumentationAutoConfiguration.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry; From 87d75a16e443fe76ba18b84f609bc22d17f71bdc Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 18:02:18 +0200 Subject: [PATCH 09/48] use InstrumentationConfig for encapsulation --- .../RuntimeMetricsAutoConfiguration.java | 6 ++---- .../OpenTelemetryAutoConfigurationTest.java | 2 +- .../R2DbcInstrumentationAutoConfigurationTest.java | 9 ++++++--- .../SchedulingInstrumentationAspectTest.java | 4 +++- ...hedulingInstrumentationAutoConfigurationTest.java | 9 ++++++--- ...pringWebInstrumentationAutoConfigurationTest.java | 9 ++++++--- ...gWebfluxInstrumentationAutoConfigurationTest.java | 9 ++++++--- .../webflux/WebClientBeanPostProcessorTest.java | 12 ++++++------ ...gWebMvcInstrumentation5AutoConfigurationTest.java | 9 ++++++--- ...stClientInstrumentationAutoConfigurationTest.java | 9 ++++++--- ...gWebMvcInstrumentation6AutoConfigurationTest.java | 9 ++++++--- 11 files changed, 54 insertions(+), 33 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/RuntimeMetricsAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/RuntimeMetricsAutoConfiguration.java index f58f4da5f217..e88d02ac0c62 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/RuntimeMetricsAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/RuntimeMetricsAutoConfiguration.java @@ -6,9 +6,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.util.Comparator; import java.util.Optional; import javax.annotation.PreDestroy; @@ -45,8 +44,7 @@ public void stopMetrics() throws Exception { public void handleApplicationReadyEvent(ApplicationReadyEvent event) { ConfigurableApplicationContext applicationContext = event.getApplicationContext(); OpenTelemetry openTelemetry = applicationContext.getBean(OpenTelemetry.class); - ConfigPropertiesBridge config = - new ConfigPropertiesBridge(applicationContext.getBean(ConfigProperties.class)); + InstrumentationConfig config = applicationContext.getBean(InstrumentationConfig.class); double version = Math.max(8, Double.parseDouble(System.getProperty("java.specification.version"))); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index 1e1a04bb5f10..1be6d883aa03 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -112,7 +112,7 @@ void enabledProviders() { .run( context -> assertThat(context) - .getBean("otelProperties", ConfigProperties.class) + .getBean("otelProperties", InstrumentationConfig.class) .satisfies( configProperties -> assertThat( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java index ffdd3c7d0181..bed063c28d1f 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/r2dbc/R2DbcInstrumentationAutoConfigurationTest.java @@ -9,8 +9,9 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.Test; @@ -28,8 +29,10 @@ class R2DbcInstrumentationAutoConfigurationTest { private final ApplicationContextRunner runner = new ApplicationContextRunner() .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of( R2dbcInstrumentationAutoConfiguration.class, R2dbcAutoConfiguration.class)) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java index 61982f55afa8..f25e7f795920 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java @@ -14,6 +14,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -57,7 +58,8 @@ void setup() { SpringSchedulingInstrumentationAspect aspect = newAspect( testing.getOpenTelemetry(), - DefaultConfigProperties.createFromMap(Collections.emptyMap())); + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))); factory.addAspect(aspect); schedulingTester = factory.getProxy(); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAutoConfigurationTest.java index 37d91b411d5a..5b631daf1434 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAutoConfigurationTest.java @@ -8,7 +8,8 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.Test; @@ -20,8 +21,10 @@ class SchedulingInstrumentationAutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of(SpringSchedulingInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java index 53bbd882a6d2..8e08dec0ea20 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/SpringWebInstrumentationAutoConfigurationTest.java @@ -8,7 +8,8 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.Test; @@ -22,8 +23,10 @@ class SpringWebInstrumentationAutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withBean(RestTemplate.class, RestTemplate::new) .withConfiguration( AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java index d75814732785..df6273d4686c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfigurationTest.java @@ -8,7 +8,8 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.Test; @@ -21,8 +22,10 @@ class SpringWebfluxInstrumentationAutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of(SpringWebfluxInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java index 821f0fbfb647..d29a695d2d1e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java @@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.DisplayName; @@ -34,7 +34,7 @@ void returnsObject() { BeanPostProcessor underTest = new WebClientBeanPostProcessor( beanFactory.getBeanProvider(OpenTelemetry.class), - beanFactory.getBeanProvider(ConfigProperties.class)); + beanFactory.getBeanProvider(InstrumentationConfig.class)); assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject")) .isExactlyInstanceOf(Object.class); @@ -46,7 +46,7 @@ void returnsWebClient() { BeanPostProcessor underTest = new WebClientBeanPostProcessor( beanFactory.getBeanProvider(OpenTelemetry.class), - beanFactory.getBeanProvider(ConfigProperties.class)); + beanFactory.getBeanProvider(InstrumentationConfig.class)); assertThat(underTest.postProcessAfterInitialization(WebClient.create(), "testWebClient")) .isInstanceOf(WebClient.class); @@ -58,7 +58,7 @@ void returnsWebClientBuilder() { BeanPostProcessor underTest = new WebClientBeanPostProcessor( beanFactory.getBeanProvider(OpenTelemetry.class), - beanFactory.getBeanProvider(ConfigProperties.class)); + beanFactory.getBeanProvider(InstrumentationConfig.class)); assertThat( underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder")) @@ -71,7 +71,7 @@ void addsExchangeFilterWebClient() { BeanPostProcessor underTest = new WebClientBeanPostProcessor( beanFactory.getBeanProvider(OpenTelemetry.class), - beanFactory.getBeanProvider(ConfigProperties.class)); + beanFactory.getBeanProvider(InstrumentationConfig.class)); WebClient webClient = WebClient.create(); Object processedWebClient = @@ -96,7 +96,7 @@ void addsExchangeFilterWebClientBuilder() { BeanPostProcessor underTest = new WebClientBeanPostProcessor( beanFactory.getBeanProvider(OpenTelemetry.class), - beanFactory.getBeanProvider(ConfigProperties.class)); + beanFactory.getBeanProvider(InstrumentationConfig.class)); WebClient.Builder webClientBuilder = WebClient.builder(); underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder"); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java index 62112774516e..3c90a46fdfdc 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation5AutoConfigurationTest.java @@ -9,7 +9,8 @@ import static org.junit.jupiter.api.Assumptions.assumeFalse; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import javax.servlet.Filter; @@ -24,8 +25,10 @@ class SpringWebMvcInstrumentation5AutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of(SpringWebMvc5InstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java index bae340b948ef..3e16f15b23ef 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/web/RestClientInstrumentationAutoConfigurationTest.java @@ -8,7 +8,8 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.Test; @@ -22,8 +23,10 @@ class RestClientInstrumentationAutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withBean(RestClient.class, RestClient::create) .withConfiguration( AutoConfigurations.of(RestClientInstrumentationAutoConfiguration.class)); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java index d064262095c6..a96d6abc2f4e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testSpring3/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webmvc/SpringWebMvcInstrumentation6AutoConfigurationTest.java @@ -9,7 +9,8 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import jakarta.servlet.Filter; import java.util.Collections; @@ -24,8 +25,10 @@ class SpringWebMvcInstrumentation6AutoConfigurationTest { new ApplicationContextRunner() .withBean(OpenTelemetry.class, OpenTelemetry::noop) .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of(SpringWebMvc6InstrumentationAutoConfiguration.class)); From 25b7884bf08415b5d94fb1a4bb20e703b863eda4 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 18 Jun 2025 18:07:07 +0200 Subject: [PATCH 10/48] use InstrumentationConfig for encapsulation --- .../autoconfigure/OpenTelemetryAutoConfigurationTest.java | 2 +- .../webflux/WebClientBeanPostProcessorTest.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index 1be6d883aa03..1e1a04bb5f10 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -112,7 +112,7 @@ void enabledProviders() { .run( context -> assertThat(context) - .getBean("otelProperties", InstrumentationConfig.class) + .getBean("otelProperties", ConfigProperties.class) .satisfies( configProperties -> assertThat( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java index d29a695d2d1e..4c25da12a112 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessorTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Collections; import org.junit.jupiter.api.DisplayName; @@ -24,7 +25,8 @@ class WebClientBeanPostProcessorTest { static { beanFactory.registerSingleton("openTelemetry", OpenTelemetry.noop()); beanFactory.registerSingleton( - "configProperties", DefaultConfigProperties.createFromMap(Collections.emptyMap())); + "configProperties", + new ConfigPropertiesBridge(DefaultConfigProperties.createFromMap(Collections.emptyMap()))); } @Test From d61e7b1b48d8688484d42664dbb8f50248382dab Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 12:48:07 +0200 Subject: [PATCH 11/48] create component loader directly (doesn't work otherwise) --- .../OpenTelemetryAutoConfiguration.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 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 e0242d73856f..389d0c6be490 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 @@ -71,12 +71,6 @@ public OpenTelemetryAutoConfiguration() {} @Conditional(SdkEnabled.class) @ConditionalOnMissingBean(OpenTelemetry.class) static class OpenTelemetrySdkConfig { - - @Bean - public ComponentLoader openTelemetrySdkComponentLoader(ApplicationContext applicationContext) { - return new OpenTelemetrySdkComponentLoader(applicationContext); - } - @Bean public ResourceProvider otelSpringResourceProvider(Optional buildProperties) { return new SpringResourceProvider(buildProperties); @@ -108,7 +102,7 @@ public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk( OtlpExporterProperties otlpExporterProperties, OtelResourceProperties resourceProperties, OtelSpringProperties otelSpringProperties, - ComponentLoader componentLoader) { + ApplicationContext applicationContext) { return AutoConfigureUtil.setComponentLoader( AutoConfigureUtil.setConfigPropertiesCustomizer( @@ -120,7 +114,7 @@ public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk( resourceProperties, otelSpringProperties, c)), - componentLoader) + new OpenTelemetrySdkComponentLoader(applicationContext)) .build(); } @@ -163,8 +157,8 @@ public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( @Bean public OpenTelemetry openTelemetry( - OpenTelemetryConfigurationModel model, ComponentLoader componentLoader) { - OpenTelemetrySdk sdk = DeclarativeConfiguration.create(model, componentLoader); + OpenTelemetryConfigurationModel model, ApplicationContext applicationContext) { + OpenTelemetrySdk sdk = DeclarativeConfiguration.create(model, new OpenTelemetrySdkComponentLoader(applicationContext)); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); From db2b93f7089d211aca7787582cfd89cd903bd52c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 13:14:36 +0200 Subject: [PATCH 12/48] fix disabled config --- .../OpenTelemetryAutoConfiguration.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 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 389d0c6be490..b167ccf0dec7 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 @@ -6,7 +6,6 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.GlobalConfigProvider; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; @@ -158,23 +157,12 @@ public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( @Bean public OpenTelemetry openTelemetry( OpenTelemetryConfigurationModel model, ApplicationContext applicationContext) { - OpenTelemetrySdk sdk = DeclarativeConfiguration.create(model, new OpenTelemetrySdkComponentLoader(applicationContext)); - + OpenTelemetrySdk sdk = + DeclarativeConfiguration.create( + model, new OpenTelemetrySdkComponentLoader(applicationContext)); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - - SdkConfigProvider configProvider = SdkConfigProvider.create(model); - GlobalConfigProvider.set(configProvider); - - System.out.println( - "OpenTelemetry SDK initialized with configuration from: " + sdk); // todo remove - - // todo declarative configuration - // todo map converter not needed here, because the declarative configuration is not using - // environment variables - logStart(); - - return null; + return sdk; } @Bean @@ -219,6 +207,26 @@ public OpenTelemetry openTelemetry() { public ConfigProperties otelProperties() { return DefaultConfigProperties.createFromMap(Collections.emptyMap()); } + + @Bean + public InstrumentationConfig instrumentationConfig(ConfigProperties properties) { + return new ConfigPropertiesBridge(properties, null); + } + + @Configuration + @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") + static class PropertiesConfig { + /** + * Is only added so that we have the same converters as with active OpenTelemetry SDK + * + *

In other words, don't break applications that (accidentally) use the {@link + * OtelMapConverter}. + */ + @Bean + OtelMapConverter otelMapConverter() { + return new OtelMapConverter(); + } + } } @Configuration @@ -231,6 +239,16 @@ public ConfigProperties otelProperties() { } } + @Configuration + @ConditionalOnBean(OpenTelemetry.class) + @ConditionalOnMissingBean({InstrumentationConfig.class}) + static class FallbackInstrumentationConfig { + @Bean + public InstrumentationConfig instrumentationConfig(ConfigProperties properties) { + return new ConfigPropertiesBridge(properties, null); + } + } + /** * The {@link ComponentLoader} is used by the SDK autoconfiguration to load all components, e.g. * Date: Thu, 19 Jun 2025 13:31:38 +0200 Subject: [PATCH 13/48] add test --- .../build.gradle.kts | 22 ++++++ .../OpenTelemetryAutoConfigurationTest.java | 74 +++++++++++++++++++ .../resources/application.yaml | 31 ++++++++ 3 files changed, 127 insertions(+) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 1e6f65737a85..6fae7bccad80 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -176,6 +176,27 @@ testing { } } } + + val testDeclarativeConfig by registering(JvmTestSuite::class) { + dependencies { + implementation(project()) + implementation("org.springframework.boot:spring-boot-starter-web:3.2.4") + implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + implementation("org.springframework.boot:spring-boot-starter-test:3.2.4") { + exclude("org.junit.vintage", "junit-vintage-engine") + } + } + } + + val testStableSemconv by registering(JvmTestSuite::class) { + targets { + all { + testTask.configure { + jvmArgs("-Dotel.semconv-stability.opt-in=database") + } + } + } + } } } @@ -230,5 +251,6 @@ tasks { check { dependsOn(testing.suites, testStableSemconv) + dependsOn(testStableSemconv) } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java new file mode 100644 index 000000000000..20c374c9a13b --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -0,0 +1,74 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.OpenTelemetry; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; + +/** Spring Boot auto configuration test for {@link OpenTelemetryAutoConfiguration}. */ +class OpenTelemetryAutoConfigurationTest { + @TestConfiguration + static class CustomTracerConfiguration { + @Bean + public OpenTelemetry customOpenTelemetry() { + return OpenTelemetry.noop(); + } + } + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + @DisplayName( + "when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry") + void customOpenTelemetry() { + this.contextRunner + .withUserConfiguration(CustomTracerConfiguration.class) + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) + .run( + context -> + assertThat(context) + .hasBean("customOpenTelemetry") + .doesNotHaveBean("openTelemetry") + .hasBean("otelProperties")); + } + + @Test + @DisplayName( + "when Application Context DOES NOT contain OpenTelemetry bean should initialize openTelemetry") + void initializeProvidersAndOpenTelemetry() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) + .run(context -> assertThat(context).hasBean("openTelemetry").hasBean("otelProperties")); + } + + @Test + void shouldInitializeSdkWhenNotDisabled() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) + .withPropertyValues("otel.sdk.disabled=false") + .run( + context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); + } + + @Test + void shouldInitializeNoopOpenTelemetryWhenSdkIsDisabled() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) + .withPropertyValues( + "otel.sdk.disabled=true", + "otel.resource.attributes=service.name=workflow-backend-dev,service.version=3c8f9ce9") + .run( + context -> + assertThat(context).getBean("openTelemetry").isEqualTo(OpenTelemetry.noop())); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml new file mode 100644 index 000000000000..897ce307f6c8 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml @@ -0,0 +1,31 @@ +otel: + # "file_format" serves as opt-in to the new file format + file_format: "0.4" + tracer_provider: + processors: + - simple: + exporter: + test_bridge: + - simple: + exporter: + console: + + logger_provider: + processors: + - simple: + exporter: + test_bridge: + + meter_provider: + readers: + - periodic: + # Set really long interval. We'll call forceFlush when we need the metrics + # instead of collecting them periodically. + interval: 1000000 + exporter: + test_bridge: + + resource: + attributes: + - name: foo + value: bar From cd7f827253c382205c8be756bb464639426ce8c8 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 13:49:38 +0200 Subject: [PATCH 14/48] add test --- .../build.gradle.kts | 34 +++++++++++++++---- .../OpenTelemetryAutoConfigurationTest.java | 1 + .../spring-boot-2/build.gradle.kts | 13 +++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 6fae7bccad80..656aa037db23 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -5,7 +5,8 @@ plugins { base.archivesName.set("opentelemetry-spring-boot-autoconfigure") group = "io.opentelemetry.instrumentation" -val springBootVersion = "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions +val springBootVersion = + "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions // r2dbc-proxy is shadowed to prevent org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration // from being loaded by Spring Boot (by the presence of META-INF/services/io.r2dbc.spi.ConnectionFactoryProvider) - even if the user doesn't want to use R2DBC. @@ -42,7 +43,12 @@ dependencies { implementation(project(":instrumentation-annotations-support")) implementation(project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library")) implementation(project(":instrumentation:mongo:mongo-3.1:library")) - compileOnly(project(path = ":instrumentation:r2dbc-1.0:library-instrumentation-shaded", configuration = "shadow")) + compileOnly( + project( + path = ":instrumentation:r2dbc-1.0:library-instrumentation-shaded", + configuration = "shadow" + ) + ) implementation(project(":instrumentation:spring:spring-kafka-2.7:library")) implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-5.3:library")) @@ -107,8 +113,14 @@ dependencies { add("javaSpring3CompileOnly", files(sourceSets.main.get().output.classesDirs)) add("javaSpring3CompileOnly", "org.springframework.boot:spring-boot-starter-web:3.2.4") add("javaSpring3CompileOnly", "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-web:spring-web-3.1:library")) - add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) + add( + "javaSpring3CompileOnly", + project(":instrumentation:spring:spring-web:spring-web-3.1:library") + ) + add( + "javaSpring3CompileOnly", + project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library") + ) } val latestDepTest = findProperty("testLatestDeps") as Boolean @@ -120,8 +132,10 @@ if (latestDepTest) { } } -val testJavaVersion = gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) -val testSpring3 = (testJavaVersion == null || testJavaVersion.compareTo(JavaVersion.VERSION_17) >= 0) +val testJavaVersion = + gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) +val testSpring3 = + (testJavaVersion == null || testJavaVersion.compareTo(JavaVersion.VERSION_17) >= 0) testing { suites { @@ -178,10 +192,16 @@ testing { } val testDeclarativeConfig by registering(JvmTestSuite::class) { + otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) + } dependencies { implementation(project()) implementation("org.springframework.boot:spring-boot-starter-web:3.2.4") - implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + implementation("io.opentelemetry:opentelemetry-sdk") + implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) + implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) + implementation("jakarta.servlet:jakarta.servlet-api:5.0.0") implementation("org.springframework.boot:spring-boot-starter-test:3.2.4") { exclude("org.junit.vintage", "junit-vintage-engine") } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index 20c374c9a13b..73f9ae23d580 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -8,6 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.sdk.OpenTelemetrySdk; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; diff --git a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts index 788a8042bd30..177d3091f8b6 100644 --- a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts @@ -30,3 +30,16 @@ configurations.configureEach { force("org.slf4j:slf4j-api:1.7.36") } } + +testing { + suites { + val testDeclarativeConfig by registering(JvmTestSuite::class) { + } + } +} + +tasks { + check { + dependsOn(testing.suites) + } +} From 0a165ae954b399f7d8ffdf6315d35d1c468a8b87 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 14:35:42 +0200 Subject: [PATCH 15/48] add test --- .../build.gradle.kts | 9 +---- .../OpenTelemetryAutoConfigurationTest.java | 5 +-- ...onTest.java => DeclarativeConfigTest.java} | 34 ++++++++++++++----- .../resources/application.yaml | 33 ++++-------------- .../smoketest/OtelSpringStarterSmokeTest.java | 22 ++++++++++++ .../resources/application.yaml | 31 +++++++++++++++++ 6 files changed, 86 insertions(+), 48 deletions(-) rename instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/{OpenTelemetryAutoConfigurationTest.java => DeclarativeConfigTest.java} (62%) create mode 100644 smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java create mode 100644 smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 656aa037db23..4f1f8dd91c0b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -192,17 +192,10 @@ testing { } val testDeclarativeConfig by registering(JvmTestSuite::class) { - otelJava { - minJavaVersionSupported.set(JavaVersion.VERSION_17) - } dependencies { implementation(project()) - implementation("org.springframework.boot:spring-boot-starter-web:3.2.4") implementation("io.opentelemetry:opentelemetry-sdk") - implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) - implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) - implementation("jakarta.servlet:jakarta.servlet-api:5.0.0") - implementation("org.springframework.boot:spring-boot-starter-test:3.2.4") { + implementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") { exclude("org.junit.vintage", "junit-vintage-engine") } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index 1e1a04bb5f10..7c3bd118e828 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -152,10 +152,7 @@ void shouldInitializeSdkWhenNotDisabled() { .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .withPropertyValues("otel.sdk.disabled=false") .run( - context -> { - assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class); - assertThat(context).hasBean("openTelemetry"); - }); + context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); } @Test diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java similarity index 62% rename from instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java rename to instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index 73f9ae23d580..c022e746aff5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -8,16 +8,18 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.OpenTelemetrySdk; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; /** Spring Boot auto configuration test for {@link OpenTelemetryAutoConfiguration}. */ -class OpenTelemetryAutoConfigurationTest { +class DeclarativeConfigTest { @TestConfiguration static class CustomTracerConfiguration { @Bean @@ -26,7 +28,11 @@ public OpenTelemetry customOpenTelemetry() { } } - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + private final ApplicationContextRunner contextRunner = + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) + // to load application.yaml + .withInitializer(new ConfigDataApplicationContextInitializer()); @Test @DisplayName( @@ -34,7 +40,6 @@ public OpenTelemetry customOpenTelemetry() { void customOpenTelemetry() { this.contextRunner .withUserConfiguration(CustomTracerConfiguration.class) - .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .run( context -> assertThat(context) @@ -47,24 +52,35 @@ void customOpenTelemetry() { @DisplayName( "when Application Context DOES NOT contain OpenTelemetry bean should initialize openTelemetry") void initializeProvidersAndOpenTelemetry() { - this.contextRunner - .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) - .run(context -> assertThat(context).hasBean("openTelemetry").hasBean("otelProperties")); + this.contextRunner.run( + context -> + assertThat(context) + .hasBean("openTelemetry") + .hasBean("otelProperties") + .getBean(InstrumentationConfig.class) + .isNotNull() + .satisfies( + c -> + assertThat(c.getDeclarativeConfig("foo")) + .isNotNull() + .satisfies( + instrumentationConfig -> + assertThat(instrumentationConfig.getString("foo")) + .isEqualTo("bar")))); } @Test void shouldInitializeSdkWhenNotDisabled() { this.contextRunner - .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .withPropertyValues("otel.sdk.disabled=false") .run( - context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); + context -> + assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); } @Test void shouldInitializeNoopOpenTelemetryWhenSdkIsDisabled() { this.contextRunner - .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .withPropertyValues( "otel.sdk.disabled=true", "otel.resource.attributes=service.name=workflow-backend-dev,service.version=3c8f9ce9") diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml index 897ce307f6c8..fa88b2a28125 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml @@ -1,31 +1,10 @@ otel: # "file_format" serves as opt-in to the new file format file_format: "0.4" - tracer_provider: - processors: - - simple: - exporter: - test_bridge: - - simple: - exporter: - console: - logger_provider: - processors: - - simple: - exporter: - test_bridge: - - meter_provider: - readers: - - periodic: - # Set really long interval. We'll call forceFlush when we need the metrics - # instead of collecting them periodically. - interval: 1000000 - exporter: - test_bridge: - - resource: - attributes: - - name: foo - value: bar + # very lightweight test to make sure the declarative config is loaded + # the full config is tested in smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig + instrumentation/development: + java: + foo: + bar: baz diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java new file mode 100644 index 000000000000..65315b926d5b --- /dev/null +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.spring.smoketest; + +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest( + classes = { + OtelSpringStarterSmokeTestApplication.class, + AbstractOtelSpringStarterSmokeTest.TestConfiguration.class, + SpringSmokeOtelConfiguration.class + }, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = { + // The headers are simply set here to make sure that headers can be parsed + "otel.exporter.otlp.headers.c=3", + "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry=true", + }) +class OtelSpringStarterSmokeTest extends AbstractOtelSpringStarterSmokeTest {} diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml new file mode 100644 index 000000000000..897ce307f6c8 --- /dev/null +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -0,0 +1,31 @@ +otel: + # "file_format" serves as opt-in to the new file format + file_format: "0.4" + tracer_provider: + processors: + - simple: + exporter: + test_bridge: + - simple: + exporter: + console: + + logger_provider: + processors: + - simple: + exporter: + test_bridge: + + meter_provider: + readers: + - periodic: + # Set really long interval. We'll call forceFlush when we need the metrics + # instead of collecting them periodically. + interval: 1000000 + exporter: + test_bridge: + + resource: + attributes: + - name: foo + value: bar From 451f3ee358bf54c1088103c2029347a81d87086b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 14:54:47 +0200 Subject: [PATCH 16/48] add test --- .../OpenTelemetryAutoConfiguration.java | 67 ++++++++++--------- .../autoconfigure/DeclarativeConfigTest.java | 4 +- 2 files changed, 36 insertions(+), 35 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 b167ccf0dec7..cafd449b5953 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 @@ -144,43 +144,44 @@ public ConfigProperties otelProperties( } } - @Configuration - @ConditionalOnProperty(name = "otel.file_format") - static class EmbeddedConfigFileConfig { + @Configuration + @ConditionalOnProperty(name = "otel.file_format") + static class EmbeddedConfigFileConfig { - @Bean - public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( - ConfigurableEnvironment environment) throws IOException { - return EmbeddedConfigFile.extractModel(environment); - } + @Bean + public OpenTelemetryConfigurationModel openTelemetryConfigurationModel( + ConfigurableEnvironment environment) throws IOException { + return EmbeddedConfigFile.extractModel(environment); + } - @Bean - public OpenTelemetry openTelemetry( - OpenTelemetryConfigurationModel model, ApplicationContext applicationContext) { - OpenTelemetrySdk sdk = - DeclarativeConfiguration.create( - model, new OpenTelemetrySdkComponentLoader(applicationContext)); - Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - logStart(); - return sdk; - } + @Bean + public OpenTelemetry openTelemetry( + OpenTelemetryConfigurationModel model, ApplicationContext applicationContext) { + OpenTelemetrySdk sdk = + DeclarativeConfiguration.create( + model, new OpenTelemetrySdkComponentLoader(applicationContext)); + Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); + logStart(); + return sdk; + } - @Bean - public InstrumentationConfig instrumentationConfig( - ConfigProperties properties, OpenTelemetryConfigurationModel model) { - return new ConfigPropertiesBridge(properties, SdkConfigProvider.create(model)); - } + @Bean + public InstrumentationConfig instrumentationConfig( + ConfigProperties properties, OpenTelemetryConfigurationModel model) { + return new ConfigPropertiesBridge(properties, SdkConfigProvider.create(model)); + } - /** - * Expose the {@link ConfigProperties} bean for use in other auto-configurations. - * - *

Not using spring boot properties directly, because declarative configuration does not - * integrate with spring boot properties. - */ - @Bean - public ConfigProperties otelProperties(OpenTelemetryConfigurationModel model) { - return DeclarativeConfigPropertiesBridge.create( - DeclarativeConfiguration.toConfigProperties(model)); + /** + * Expose the {@link ConfigProperties} bean for use in other auto-configurations. + * + *

Not using spring boot properties directly, because declarative configuration does not + * integrate with spring boot properties. + */ + @Bean + public ConfigProperties otelProperties(OpenTelemetryConfigurationModel model) { + return DeclarativeConfigPropertiesBridge.create( + DeclarativeConfiguration.toConfigProperties(model)); + } } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index c022e746aff5..bb17849a053d 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -65,8 +65,8 @@ void initializeProvidersAndOpenTelemetry() { .isNotNull() .satisfies( instrumentationConfig -> - assertThat(instrumentationConfig.getString("foo")) - .isEqualTo("bar")))); + assertThat(instrumentationConfig.getString("bar")) + .isEqualTo("baz")))); } @Test From 00eae94249e3e3ddbcf6d095de6d960f7c77559c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 15:12:59 +0200 Subject: [PATCH 17/48] add test --- .../autoconfigure/EmbeddedConfigFile.java | 20 +------------------ .../spring-boot-2/build.gradle.kts | 5 +++++ 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java index 944069026aa1..195782a2e1f1 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/EmbeddedConfigFile.java @@ -46,21 +46,13 @@ static OpenTelemetryConfigurationModel extractModel(ConfigurableEnvironment envi private static OpenTelemetryConfigurationModel getModel( ConfigurableEnvironment environment, OriginTrackedMapPropertySource source) throws IOException { - String name = source.getName(); - System.out.println("Property Source: " + name); // todo remove - Matcher matcher = PATTERN.matcher(name); + Matcher matcher = PATTERN.matcher(source.getName()); if (matcher.matches()) { String file = matcher.group(1); - System.out.println("Found application.yaml: " + file); try (InputStream resourceAsStream = environment.getClass().getClassLoader().getResourceAsStream(file)) { - // Print the contents of the application.yaml file if (resourceAsStream != null) { - // String content = new String(resourceAsStream.readAllBytes()); - // System.out.println("Contents of " + file + ":"); // todo remove - // System.out.println(content); // todo remove - return extractOtelConfigFile(resourceAsStream); } else { throw new IllegalStateException("Unable to load " + file + " in the classpath."); @@ -88,21 +80,11 @@ private static String parseOtelNode(InputStream in) { } private static OpenTelemetryConfigurationModel extractOtelConfigFile(InputStream content) { - // - // https://github.com/open-telemetry/opentelemetry-configuration/blob/c205770a956713e512eddb056570a99737e3383a/examples/kitchen-sink.yaml#L11 - - // 1. read to yaml tree in jackson - // ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); - // JsonNode rootNode = yamlMapper.readTree(content); - String node = parseOtelNode(content); if (node == null || node.isEmpty()) { throw new IllegalStateException("otel node is empty or null in the YAML file."); } - System.out.println("OpenTelemetry configuration file content:"); // todo remove - System.out.println(node); // todo remove - return DeclarativeConfiguration.parse( new ByteArrayInputStream(node.getBytes(StandardCharsets.UTF_8))); } diff --git a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts index 177d3091f8b6..3b8fd9d14002 100644 --- a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts @@ -34,6 +34,11 @@ configurations.configureEach { testing { suites { val testDeclarativeConfig by registering(JvmTestSuite::class) { + dependencies { + implementation(project()) + implementation(project(":smoke-tests-otel-starter:spring-boot-common")) + implementation("org.springframework.boot:spring-boot-starter-test:2.6.15") + } } } } From be11de3365971df0f45faf525611e0b99dea9579 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 15:42:51 +0200 Subject: [PATCH 18/48] add test --- .../resources/application.yaml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 897ce307f6c8..f010634fcdad 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -5,25 +5,20 @@ otel: processors: - simple: exporter: - test_bridge: - - simple: - exporter: - console: + otlp_http: logger_provider: processors: - simple: exporter: - test_bridge: + otlp_http: meter_provider: readers: - periodic: - # Set really long interval. We'll call forceFlush when we need the metrics - # instead of collecting them periodically. - interval: 1000000 + interval: 1000 exporter: - test_bridge: + otlp_http: resource: attributes: From 7e1d3a76b8b0b8699bbfccaa37582ab75c7bc040 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 16:06:07 +0200 Subject: [PATCH 19/48] add test --- .../spring/autoconfigure/OpenTelemetryAutoConfiguration.java | 4 ++++ 1 file changed, 4 insertions(+) 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 cafd449b5953..b6c09974d6d0 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 @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; +import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; @@ -161,6 +162,9 @@ public OpenTelemetry openTelemetry( DeclarativeConfiguration.create( model, new OpenTelemetrySdkComponentLoader(applicationContext)); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); + // todo there is no equivalent to https://github.com/open-telemetry/opentelemetry-java/blob/7655192df504d28da2d2013f2fc49ec44ef6202e/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java#L96 + // so we get a NPE when there is no global OpenTelemetry instance set + GlobalOpenTelemetry.set(sdk); logStart(); return sdk; } From 443828a98b7040faae2ee8844a84c45638882515 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 16:06:26 +0200 Subject: [PATCH 20/48] add test --- .../spring/smoketest/OtelSpringStarterSmokeTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index 65315b926d5b..7a7e66209be3 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -16,7 +16,6 @@ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { // The headers are simply set here to make sure that headers can be parsed - "otel.exporter.otlp.headers.c=3", - "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry=true", + "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry=true", // todo to file config }) class OtelSpringStarterSmokeTest extends AbstractOtelSpringStarterSmokeTest {} From ff121c375553d7575beadc234c68f7a48cb40ac1 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 16:48:08 +0200 Subject: [PATCH 21/48] add test --- .../spring-boot-2/build.gradle.kts | 1 + .../smoketest/OtelSpringStarterSmokeTest.java | 36 +++++++++++++++---- .../resources/application.yaml | 13 ++++--- .../smoketest/SpringSmokeTestRunner.java | 8 +++++ 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts index 3b8fd9d14002..678510b3e43d 100644 --- a/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts +++ b/smoke-tests-otel-starter/spring-boot-2/build.gradle.kts @@ -37,6 +37,7 @@ testing { dependencies { implementation(project()) implementation(project(":smoke-tests-otel-starter:spring-boot-common")) + implementation("org.springframework.boot:spring-boot-starter-web:2.6.15") implementation("org.springframework.boot:spring-boot-starter-test:2.6.15") } } diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index 7a7e66209be3..cb451f2a1ea7 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -5,7 +5,13 @@ package io.opentelemetry.spring.smoketest; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.semconv.HttpAttributes; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.client.RestTemplateBuilder; @SpringBootTest( classes = { @@ -13,9 +19,27 @@ AbstractOtelSpringStarterSmokeTest.TestConfiguration.class, SpringSmokeOtelConfiguration.class }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { - // The headers are simply set here to make sure that headers can be parsed - "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry=true", // todo to file config - }) -class OtelSpringStarterSmokeTest extends AbstractOtelSpringStarterSmokeTest {} + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest { + + @Autowired private RestTemplateBuilder restTemplateBuilder; + + // can't use @LocalServerPort annotation since it moved packages between Spring Boot 2 and 3 + @Value("${local.server.port}") + private int port; + + @Test + void restTemplate() { + testing.clearAllExportedData(); + + org.springframework.web.client.RestTemplate restTemplate = restTemplateBuilder.rootUri("http://localhost:" + port).build(); + restTemplate.getForObject(OtelSpringStarterSmokeTestController.PING, String.class); + testing.waitAndAssertTraces( + traceAssert -> + traceAssert.hasSpansSatisfyingExactly( + span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"), + span -> + span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), + AbstractSpringStarterSmokeTest::withSpanAssert)); + } +} diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index f010634fcdad..897ce307f6c8 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -5,20 +5,25 @@ otel: processors: - simple: exporter: - otlp_http: + test_bridge: + - simple: + exporter: + console: logger_provider: processors: - simple: exporter: - otlp_http: + test_bridge: meter_provider: readers: - periodic: - interval: 1000 + # Set really long interval. We'll call forceFlush when we need the metrics + # instead of collecting them periodically. + interval: 1000000 exporter: - otlp_http: + test_bridge: resource: attributes: diff --git a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java index 471016ee883e..72e95725af9c 100644 --- a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java +++ b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java @@ -7,6 +7,9 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; +import io.opentelemetry.instrumentation.testing.provider.TestBridgeLogRecordExporterComponentProvider; +import io.opentelemetry.instrumentation.testing.provider.TestBridgeMetricExporterComponentProvider; +import io.opentelemetry.instrumentation.testing.provider.TestBridgeSpanExporterComponentProvider; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; @@ -36,6 +39,11 @@ static void resetExporters() { testSpanExporter = InMemorySpanExporter.create(); testMetricExporter = InMemoryMetricExporter.create(AggregationTemporality.DELTA); testLogRecordExporter = InMemoryLogRecordExporter.create(); + + // for declarative config + TestBridgeLogRecordExporterComponentProvider.setLogRecordExporter(testLogRecordExporter); + TestBridgeMetricExporterComponentProvider.setMetricExporter(testMetricExporter); + TestBridgeSpanExporterComponentProvider.setSpanExporter(testSpanExporter); } @Override From 809c906c54670f002afb5481b273b527a6a74d07 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 17:29:58 +0200 Subject: [PATCH 22/48] add test --- .../OpenTelemetryAutoConfiguration.java | 6 +++++- .../smoketest/OtelSpringStarterSmokeTest.java | 4 ++++ .../resources/application.yaml | 16 ++++++++++++---- 3 files changed, 21 insertions(+), 5 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 b6c09974d6d0..9c989c7a5ad7 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 @@ -7,6 +7,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; @@ -183,8 +184,11 @@ public InstrumentationConfig instrumentationConfig( */ @Bean public ConfigProperties otelProperties(OpenTelemetryConfigurationModel model) { + SdkConfigProvider provider = SdkConfigProvider.create(model); + DeclarativeConfigProperties instrumentationConfig = provider.getInstrumentationConfig(); + return DeclarativeConfigPropertiesBridge.create( - DeclarativeConfiguration.toConfigProperties(model)); + instrumentationConfig); } } } diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index cb451f2a1ea7..cb57d1b8231d 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -10,6 +10,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -20,6 +23,7 @@ SpringSmokeOtelConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest { @Autowired private RestTemplateBuilder restTemplateBuilder; diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 897ce307f6c8..0606404826c3 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -25,7 +25,15 @@ otel: exporter: test_bridge: - resource: - attributes: - - name: foo - value: bar + propagator: + composite: + - tracecontext: + - baggage: + + instrumentation/development: + java: + runtime-telemetry: + emit-experimental-telemetry: true + http: + client: + emit-experimental-telemetry: true From 4136013e68d10f179ec9a6c839a9dd2d0e75e55a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 17:35:40 +0200 Subject: [PATCH 23/48] cleanup --- .../OpenTelemetryAutoConfiguration.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 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 9c989c7a5ad7..f48de48b8fcc 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 @@ -7,7 +7,7 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.trace.TracerProvider; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; @@ -163,7 +163,8 @@ public OpenTelemetry openTelemetry( DeclarativeConfiguration.create( model, new OpenTelemetrySdkComponentLoader(applicationContext)); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - // todo there is no equivalent to https://github.com/open-telemetry/opentelemetry-java/blob/7655192df504d28da2d2013f2fc49ec44ef6202e/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java#L96 + // todo there is no equivalent to + // https://github.com/open-telemetry/opentelemetry-java/blob/7655192df504d28da2d2013f2fc49ec44ef6202e/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java#L96 // so we get a NPE when there is no global OpenTelemetry instance set GlobalOpenTelemetry.set(sdk); logStart(); @@ -172,8 +173,13 @@ public OpenTelemetry openTelemetry( @Bean public InstrumentationConfig instrumentationConfig( - ConfigProperties properties, OpenTelemetryConfigurationModel model) { - return new ConfigPropertiesBridge(properties, SdkConfigProvider.create(model)); + ConfigProperties properties, ConfigProvider configProvider) { + return new ConfigPropertiesBridge(properties, configProvider); + } + + @Bean + public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { + return SdkConfigProvider.create(model); } /** @@ -183,12 +189,8 @@ public InstrumentationConfig instrumentationConfig( * integrate with spring boot properties. */ @Bean - public ConfigProperties otelProperties(OpenTelemetryConfigurationModel model) { - SdkConfigProvider provider = SdkConfigProvider.create(model); - DeclarativeConfigProperties instrumentationConfig = provider.getInstrumentationConfig(); - - return DeclarativeConfigPropertiesBridge.create( - instrumentationConfig); + public ConfigProperties otelProperties(ConfigProvider configProvider) { + return DeclarativeConfigPropertiesBridge.create(configProvider.getInstrumentationConfig()); } } } From 39214aa79b0cb2a78b9721338335ca19b2ca517e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 17:37:27 +0200 Subject: [PATCH 24/48] cleanup --- .../spring/autoconfigure/DeclarativeConfigTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index bb17849a053d..bfa74331d4ce 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -7,9 +7,11 @@ import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.OpenTelemetrySdk; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -34,6 +36,12 @@ public OpenTelemetry customOpenTelemetry() { // to load application.yaml .withInitializer(new ConfigDataApplicationContextInitializer()); + @BeforeEach + void setUp() { + // todo remove - see io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration.OpenTelemetrySdkConfig.EmbeddedConfigFileConfig + GlobalOpenTelemetry.resetForTest(); + } + @Test @DisplayName( "when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry") From ec91535a21e781aa300efde54630b8756158698c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 19 Jun 2025 17:39:11 +0200 Subject: [PATCH 25/48] format --- .../autoconfigure/OpenTelemetryAutoConfigurationTest.java | 3 ++- .../spring/autoconfigure/DeclarativeConfigTest.java | 3 ++- .../spring/smoketest/OtelSpringStarterSmokeTest.java | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index 7c3bd118e828..cf97dc2f7302 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -152,7 +152,8 @@ void shouldInitializeSdkWhenNotDisabled() { .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .withPropertyValues("otel.sdk.disabled=false") .run( - context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); + context -> + assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); } @Test diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index bfa74331d4ce..7aa8716179e6 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -38,7 +38,8 @@ public OpenTelemetry customOpenTelemetry() { @BeforeEach void setUp() { - // todo remove - see io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration.OpenTelemetrySdkConfig.EmbeddedConfigFileConfig + // todo remove - see + // io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration.OpenTelemetrySdkConfig.EmbeddedConfigFileConfig GlobalOpenTelemetry.resetForTest(); } diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index cb57d1b8231d..513960c9b2e2 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -23,7 +23,7 @@ SpringSmokeOtelConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@EnableAutoConfiguration(exclude={MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) +@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest { @Autowired private RestTemplateBuilder restTemplateBuilder; @@ -36,7 +36,8 @@ class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest { void restTemplate() { testing.clearAllExportedData(); - org.springframework.web.client.RestTemplate restTemplate = restTemplateBuilder.rootUri("http://localhost:" + port).build(); + org.springframework.web.client.RestTemplate restTemplate = + restTemplateBuilder.rootUri("http://localhost:" + port).build(); restTemplate.getForObject(OtelSpringStarterSmokeTestController.PING, String.class); testing.waitAndAssertTraces( traceAssert -> From 8dda0faaebe0377c60c3d6be1206d0c63e89d571 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 30 Jun 2025 11:29:25 +0200 Subject: [PATCH 26/48] fix rebase --- .../spring/smoketest/SpringSmokeTestRunner.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java index 72e95725af9c..0675f3b0b61a 100644 --- a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java +++ b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/SpringSmokeTestRunner.java @@ -7,9 +7,9 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner; -import io.opentelemetry.instrumentation.testing.provider.TestBridgeLogRecordExporterComponentProvider; -import io.opentelemetry.instrumentation.testing.provider.TestBridgeMetricExporterComponentProvider; -import io.opentelemetry.instrumentation.testing.provider.TestBridgeSpanExporterComponentProvider; +import io.opentelemetry.instrumentation.testing.provider.TestLogRecordExporterComponentProvider; +import io.opentelemetry.instrumentation.testing.provider.TestMetricExporterComponentProvider; +import io.opentelemetry.instrumentation.testing.provider.TestSpanExporterComponentProvider; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; @@ -41,9 +41,9 @@ static void resetExporters() { testLogRecordExporter = InMemoryLogRecordExporter.create(); // for declarative config - TestBridgeLogRecordExporterComponentProvider.setLogRecordExporter(testLogRecordExporter); - TestBridgeMetricExporterComponentProvider.setMetricExporter(testMetricExporter); - TestBridgeSpanExporterComponentProvider.setSpanExporter(testSpanExporter); + TestLogRecordExporterComponentProvider.setLogRecordExporter(testLogRecordExporter); + TestMetricExporterComponentProvider.setMetricExporter(testMetricExporter); + TestSpanExporterComponentProvider.setSpanExporter(testSpanExporter); } @Override From 9c68b5f181466e65b389176f61ec2a0a5afcb9f6 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 30 Jun 2025 11:31:35 +0200 Subject: [PATCH 27/48] fix rebase --- .../src/testDeclarativeConfig/resources/application.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 0606404826c3..4f7438d8568a 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -5,7 +5,7 @@ otel: processors: - simple: exporter: - test_bridge: + test: - simple: exporter: console: @@ -14,7 +14,7 @@ otel: processors: - simple: exporter: - test_bridge: + test: meter_provider: readers: @@ -23,7 +23,7 @@ otel: # instead of collecting them periodically. interval: 1000000 exporter: - test_bridge: + test: propagator: composite: From 4dfd9e8ad6b5ed405ab1aaee9240c14886043ee7 Mon Sep 17 00:00:00 2001 From: otelbot <197425009+otelbot@users.noreply.github.com> Date: Mon, 30 Jun 2025 09:36:19 +0000 Subject: [PATCH 28/48] ./gradlew spotlessApply --- .../scheduling/SchedulingInstrumentationAspectTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java index f25e7f795920..3306b280869c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/scheduling/SchedulingInstrumentationAspectTest.java @@ -17,7 +17,6 @@ import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; From 7c01608199ae30a2555109efd44fee78c661ebc4 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 7 Jul 2025 14:55:19 +0200 Subject: [PATCH 29/48] fix rebase --- .../build.gradle.kts | 26 +++++-------------- .../OpenTelemetryAutoConfiguration.java | 5 ++-- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 4f1f8dd91c0b..dfa85158e918 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -5,8 +5,7 @@ plugins { base.archivesName.set("opentelemetry-spring-boot-autoconfigure") group = "io.opentelemetry.instrumentation" -val springBootVersion = - "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions +val springBootVersion = "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions // r2dbc-proxy is shadowed to prevent org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration // from being loaded by Spring Boot (by the presence of META-INF/services/io.r2dbc.spi.ConnectionFactoryProvider) - even if the user doesn't want to use R2DBC. @@ -43,12 +42,7 @@ dependencies { implementation(project(":instrumentation-annotations-support")) implementation(project(":instrumentation:kafka:kafka-clients:kafka-clients-2.6:library")) implementation(project(":instrumentation:mongo:mongo-3.1:library")) - compileOnly( - project( - path = ":instrumentation:r2dbc-1.0:library-instrumentation-shaded", - configuration = "shadow" - ) - ) + compileOnly(project(path = ":instrumentation:r2dbc-1.0:library-instrumentation-shaded", configuration = "shadow")) implementation(project(":instrumentation:spring:spring-kafka-2.7:library")) implementation(project(":instrumentation:spring:spring-web:spring-web-3.1:library")) implementation(project(":instrumentation:spring:spring-webmvc:spring-webmvc-5.3:library")) @@ -113,14 +107,8 @@ dependencies { add("javaSpring3CompileOnly", files(sourceSets.main.get().output.classesDirs)) add("javaSpring3CompileOnly", "org.springframework.boot:spring-boot-starter-web:3.2.4") add("javaSpring3CompileOnly", "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - add( - "javaSpring3CompileOnly", - project(":instrumentation:spring:spring-web:spring-web-3.1:library") - ) - add( - "javaSpring3CompileOnly", - project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library") - ) + add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-web:spring-web-3.1:library")) + add("javaSpring3CompileOnly", project(":instrumentation:spring:spring-webmvc:spring-webmvc-6.0:library")) } val latestDepTest = findProperty("testLatestDeps") as Boolean @@ -132,10 +120,8 @@ if (latestDepTest) { } } -val testJavaVersion = - gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) -val testSpring3 = - (testJavaVersion == null || testJavaVersion.compareTo(JavaVersion.VERSION_17) >= 0) +val testJavaVersion = gradle.startParameter.projectProperties["testJavaVersion"]?.let(JavaVersion::toVersion) +val testSpring3 = (testJavaVersion == null || testJavaVersion.compareTo(JavaVersion.VERSION_17) >= 0) testing { suites { 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 f48de48b8fcc..1397461122c1 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 @@ -189,8 +189,9 @@ public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { * integrate with spring boot properties. */ @Bean - public ConfigProperties otelProperties(ConfigProvider configProvider) { - return DeclarativeConfigPropertiesBridge.create(configProvider.getInstrumentationConfig()); + public ConfigProperties otelProperties( + OpenTelemetryConfigurationModel model, ConfigProvider configProvider) { + return new DeclarativeConfigPropertiesBridge(configProvider, model.getLogLevel()); } } } From 440d997d95c0b62cd181b253106e334e8a911013 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 7 Jul 2025 15:10:27 +0200 Subject: [PATCH 30/48] extract condition --- .../OpenTelemetryAutoConfiguration.java | 8 ++++--- .../internal/DeclarativeConfigDisabled.java | 22 +++++++++++++++++++ .../internal/DeclarativeConfigEnabled.java | 22 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java 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 1397461122c1..d1d4ff03e55c 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 @@ -12,6 +12,8 @@ import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridge; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelMapConverter; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; @@ -88,7 +90,7 @@ public ResourceProvider otelDistroVersionResourceProvider() { OtelResourceProperties.class, OtelSpringProperties.class }) - @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") + @Conditional(DeclarativeConfigDisabled.class) static class PropertiesConfig { @Bean @@ -147,7 +149,7 @@ public ConfigProperties otelProperties( } @Configuration - @ConditionalOnProperty(name = "otel.file_format") + @Conditional(DeclarativeConfigEnabled.class) static class EmbeddedConfigFileConfig { @Bean @@ -226,7 +228,7 @@ public InstrumentationConfig instrumentationConfig(ConfigProperties properties) } @Configuration - @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") + @Conditional(DeclarativeConfigDisabled.class) static class PropertiesConfig { /** * Is only added so that we have the same converters as with active OpenTelemetry SDK diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java new file mode 100644 index 000000000000..927c849e59e4 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal; + +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class DeclarativeConfigDisabled extends AnyNestedCondition { + public DeclarativeConfigDisabled() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") + static class Disabled {} +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java new file mode 100644 index 000000000000..391dbc9f15ab --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java @@ -0,0 +1,22 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal; + +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class DeclarativeConfigEnabled extends AnyNestedCondition { + public DeclarativeConfigEnabled() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty(name = "otel.file_format") + static class Enabled {} +} From 27f3919702591dbd98ce2516ca137bbc8838797c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 8 Jul 2025 12:52:42 +0200 Subject: [PATCH 31/48] use _ --- .../src/testDeclarativeConfig/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 4f7438d8568a..9fea1850cad5 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -33,7 +33,7 @@ otel: instrumentation/development: java: runtime-telemetry: - emit-experimental-telemetry: true + emit_experimental_telemetry: true http: client: - emit-experimental-telemetry: true + emit_experimental_telemetry: true From fef29538a0587b25284225a6f76145c8e38f2af1 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 8 Jul 2025 14:02:01 +0200 Subject: [PATCH 32/48] use declarative config properties --- .../OpenTelemetryAutoConfiguration.java | 8 +-- .../ConditionalOnEnabledInstrumentation.java | 2 +- .../internal/DeclarativeConfigDisabled.java | 15 +++--- .../internal/DeclarativeConfigEnabled.java | 15 +++--- .../autoconfigure/internal/EarlyConfig.java | 49 +++++++++++++++++++ .../InstrumentationPropertyEnabled.java | 23 ++++++--- .../autoconfigure/internal/OtelDisabled.java | 21 ++++++++ .../autoconfigure/internal/OtelEnabled.java | 21 ++++++++ .../autoconfigure/internal/SdkEnabled.java | 22 --------- .../logging/LogbackAppenderInstaller.java | 7 +-- .../autoconfigure/DeclarativeConfigTest.java | 4 +- 11 files changed, 133 insertions(+), 54 deletions(-) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelDisabled.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelEnabled.java delete mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/SdkEnabled.java 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 d1d4ff03e55c..078bd9ca8691 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 @@ -14,8 +14,9 @@ import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridge; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelDisabled; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelMapConverter; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.SdkEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelSpringProperties; @@ -45,7 +46,6 @@ import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.info.BuildProperties; @@ -71,7 +71,7 @@ public class OpenTelemetryAutoConfiguration { public OpenTelemetryAutoConfiguration() {} @Configuration - @Conditional(SdkEnabled.class) + @Conditional(OtelEnabled.class) @ConditionalOnMissingBean(OpenTelemetry.class) static class OpenTelemetrySdkConfig { @Bean @@ -207,7 +207,7 @@ private static void logStart() { @Configuration @ConditionalOnMissingBean(OpenTelemetry.class) - @ConditionalOnProperty(name = "otel.sdk.disabled", havingValue = "true") + @Conditional(OtelDisabled.class) static class DisabledOpenTelemetrySdkConfig { @Bean diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/ConditionalOnEnabledInstrumentation.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/ConditionalOnEnabledInstrumentation.java index 7c55f430d1e4..0383c5117298 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/ConditionalOnEnabledInstrumentation.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/ConditionalOnEnabledInstrumentation.java @@ -20,7 +20,7 @@ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @ConditionalOnBean(OpenTelemetry.class) -@Conditional({SdkEnabled.class, InstrumentationPropertyEnabled.class}) +@Conditional({OtelEnabled.class, InstrumentationPropertyEnabled.class}) public @interface ConditionalOnEnabledInstrumentation { String module(); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java index 927c849e59e4..72ceddb62cd5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigDisabled.java @@ -5,18 +5,17 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public class DeclarativeConfigDisabled extends AnyNestedCondition { - public DeclarativeConfigDisabled() { - super(ConfigurationPhase.PARSE_CONFIGURATION); +public class DeclarativeConfigDisabled implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return !EarlyConfig.isDeclarativeConfig(context.getEnvironment()); } - - @ConditionalOnProperty(name = "otel.file_format", matchIfMissing = true, havingValue = "never") - static class Disabled {} } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java index 391dbc9f15ab..b64134d72f93 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/DeclarativeConfigEnabled.java @@ -5,18 +5,17 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public class DeclarativeConfigEnabled extends AnyNestedCondition { - public DeclarativeConfigEnabled() { - super(ConfigurationPhase.PARSE_CONFIGURATION); +public class DeclarativeConfigEnabled implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return EarlyConfig.isDeclarativeConfig(context.getEnvironment()); } - - @ConditionalOnProperty(name = "otel.file_format") - static class Enabled {} } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java new file mode 100644 index 000000000000..ae5f9d40a3bf --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.springframework.core.env.Environment; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class EarlyConfig { + private EarlyConfig() {} + + private static final Map DECLARATIVE_CONFIG_PROPERTY_MAPPING = new HashMap<>(); + + static { + DECLARATIVE_CONFIG_PROPERTY_MAPPING.put("otel.sdk.disabled", "otel.disabled"); + DECLARATIVE_CONFIG_PROPERTY_MAPPING.put( + "otel.instrumentation.%s.enabled", "otel.instrumentation/development.java.%s.enabled"); + DECLARATIVE_CONFIG_PROPERTY_MAPPING.put( + "otel.instrumentation.common.default-enabled", + "otel.instrumentation/development.java.common.default.enabled"); + } + + public static boolean otelEnabled(Environment environment) { + return !environment.getProperty( + translatePropertyName(environment, "otel.sdk.disabled"), Boolean.class, false); + } + + public static Boolean isDeclarativeConfig(Environment environment) { + return environment.getProperty("otel.file_format", String.class) != null; + } + + public static String translatePropertyName(Environment environment, String name) { + if (isDeclarativeConfig(environment)) { + return Objects.requireNonNull( + DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name), + "No mapping found for property name: " + name + ". Please report this bug."); + } else { + return name; + } + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java index 87687f668b6c..d60260b0a3c9 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java @@ -5,9 +5,13 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; +import static io.opentelemetry.instrumentation.spring.autoconfigure.internal.EarlyConfig.translatePropertyName; + import java.util.Map; +import java.util.Objects; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; /** @@ -19,10 +23,16 @@ public class InstrumentationPropertyEnabled implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map attributes = - metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName()); + Objects.requireNonNull( + metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName())); + + Environment environment = context.getEnvironment(); - String name = String.format("otel.instrumentation.%s.enabled", attributes.get("module")); - Boolean explicit = context.getEnvironment().getProperty(name, Boolean.class); + String name = + String.format( + translatePropertyName(environment, "otel.instrumentation.%s.enabled"), + attributes.get("module")); + Boolean explicit = environment.getProperty(name, Boolean.class); if (explicit != null) { return explicit; } @@ -30,8 +40,9 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) if (!defaultValue) { return false; } - return context - .getEnvironment() - .getProperty("otel.instrumentation.common.default-enabled", Boolean.class, true); + return environment.getProperty( + translatePropertyName(environment, "otel.instrumentation.common.default-enabled"), + Boolean.class, + true); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelDisabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelDisabled.java new file mode 100644 index 000000000000..d521f76eb7ba --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelDisabled.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class OtelDisabled implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return !EarlyConfig.otelEnabled(context.getEnvironment()); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelEnabled.java new file mode 100644 index 000000000000..a1b87384e8ce --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/OtelEnabled.java @@ -0,0 +1,21 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class OtelEnabled implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return EarlyConfig.otelEnabled(context.getEnvironment()); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/SdkEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/SdkEnabled.java deleted file mode 100644 index 082bdebc00b7..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/SdkEnabled.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.internal; - -import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public class SdkEnabled extends AnyNestedCondition { - public SdkEnabled() { - super(ConfigurationPhase.PARSE_CONFIGURATION); - } - - @ConditionalOnProperty(name = "otel.sdk.disabled", havingValue = "false", matchIfMissing = true) - static class NotDisabled {} -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java index fd13848aaf2f..a052d50fa571 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java @@ -9,6 +9,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Appender; import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.EarlyConfig; import java.util.Iterator; import java.util.Optional; import org.slf4j.ILoggerFactory; @@ -54,11 +55,11 @@ private static boolean isLogbackMdcAppenderAddable( private static boolean isAppenderAddable( ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, String property) { - boolean otelSdkDisabled = - evaluateBooleanProperty(applicationEnvironmentPreparedEvent, "otel.sdk.disabled", false); + boolean otelEnabled = + EarlyConfig.otelEnabled(applicationEnvironmentPreparedEvent.getEnvironment()); boolean logbackInstrumentationEnabled = evaluateBooleanProperty(applicationEnvironmentPreparedEvent, property, true); - return !otelSdkDisabled && logbackInstrumentationEnabled; + return otelEnabled && logbackInstrumentationEnabled; } private static void reInitializeOpenTelemetryAppender( diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index 7aa8716179e6..2d12325779d6 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -81,7 +81,7 @@ void initializeProvidersAndOpenTelemetry() { @Test void shouldInitializeSdkWhenNotDisabled() { this.contextRunner - .withPropertyValues("otel.sdk.disabled=false") + .withPropertyValues("otel.disabled=false") .run( context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); @@ -91,7 +91,7 @@ void shouldInitializeSdkWhenNotDisabled() { void shouldInitializeNoopOpenTelemetryWhenSdkIsDisabled() { this.contextRunner .withPropertyValues( - "otel.sdk.disabled=true", + "otel.disabled=true", "otel.resource.attributes=service.name=workflow-backend-dev,service.version=3c8f9ce9") .run( context -> From 1aa0a45c108bf205b278c1fc3a10facddba7c3e0 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 8 Jul 2025 14:35:12 +0200 Subject: [PATCH 33/48] use declarative config properties --- .../autoconfigure/internal/EarlyConfig.java | 33 ++++++++++++++-- .../InstrumentationPropertyEnabled.java | 25 ++---------- .../logging/LogbackAppenderInstaller.java | 39 ++++++------------- 3 files changed, 46 insertions(+), 51 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java index ae5f9d40a3bf..a939de4d07a8 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -7,7 +7,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Objects; import org.springframework.core.env.Environment; /** @@ -39,11 +38,39 @@ public static Boolean isDeclarativeConfig(Environment environment) { public static String translatePropertyName(Environment environment, String name) { if (isDeclarativeConfig(environment)) { - return Objects.requireNonNull( - DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name), + String value = DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name); + if (value != null) { + return value; + } + if (name.startsWith("otel.instrumentation.")) { + return String.format( + "otel.instrumentation/development.java.%s", + name.substring("otel.instrumentation.".length())); + } + + throw new IllegalStateException( "No mapping found for property name: " + name + ". Please report this bug."); } else { return name; } } + + public static boolean isInstrumentationEnabled( + Environment environment, String name, boolean defaultValue) { + Boolean explicit = + environment.getProperty( + String.format( + translatePropertyName(environment, "otel.instrumentation.%s.enabled"), name), + Boolean.class); + if (explicit != null) { + return explicit; + } + if (!defaultValue) { + return false; + } + return environment.getProperty( + translatePropertyName(environment, "otel.instrumentation.common.default-enabled"), + Boolean.class, + true); + } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java index d60260b0a3c9..39de2fc9227b 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/InstrumentationPropertyEnabled.java @@ -5,13 +5,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; -import static io.opentelemetry.instrumentation.spring.autoconfigure.internal.EarlyConfig.translatePropertyName; - import java.util.Map; import java.util.Objects; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; -import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; /** @@ -26,23 +23,9 @@ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) Objects.requireNonNull( metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName())); - Environment environment = context.getEnvironment(); - - String name = - String.format( - translatePropertyName(environment, "otel.instrumentation.%s.enabled"), - attributes.get("module")); - Boolean explicit = environment.getProperty(name, Boolean.class); - if (explicit != null) { - return explicit; - } - boolean defaultValue = (boolean) attributes.get("enabledByDefault"); - if (!defaultValue) { - return false; - } - return environment.getProperty( - translatePropertyName(environment, "otel.instrumentation.common.default-enabled"), - Boolean.class, - true); + return EarlyConfig.isInstrumentationEnabled( + context.getEnvironment(), + attributes.get("module").toString(), + (boolean) attributes.get("enabledByDefault")); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java index a052d50fa571..51588f786d25 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java @@ -16,6 +16,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.core.env.ConfigurableEnvironment; class LogbackAppenderInstaller { @@ -41,25 +42,18 @@ static void install(ApplicationEnvironmentPreparedEvent applicationEnvironmentPr } } - private static boolean isLogbackAppenderAddable( - ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) { - return isAppenderAddable( - applicationEnvironmentPreparedEvent, "otel.instrumentation.logback-appender.enabled"); + private static boolean isLogbackAppenderAddable(ApplicationEnvironmentPreparedEvent event) { + return isAppenderAddable(event, "logback-appender"); } - private static boolean isLogbackMdcAppenderAddable( - ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) { - return isAppenderAddable( - applicationEnvironmentPreparedEvent, "otel.instrumentation.logback-mdc.enabled"); + private static boolean isLogbackMdcAppenderAddable(ApplicationEnvironmentPreparedEvent event) { + return isAppenderAddable(event, "logback-mdc"); } - private static boolean isAppenderAddable( - ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, String property) { - boolean otelEnabled = - EarlyConfig.otelEnabled(applicationEnvironmentPreparedEvent.getEnvironment()); - boolean logbackInstrumentationEnabled = - evaluateBooleanProperty(applicationEnvironmentPreparedEvent, property, true); - return otelEnabled && logbackInstrumentationEnabled; + private static boolean isAppenderAddable(ApplicationEnvironmentPreparedEvent event, String name) { + ConfigurableEnvironment environment = event.getEnvironment(); + return EarlyConfig.otelEnabled(environment) + && EarlyConfig.isInstrumentationEnabled(environment, name, true); } private static void reInitializeOpenTelemetryAppender( @@ -225,18 +219,9 @@ private static void initializeMdcAppenderFromProperties( private static Boolean evaluateBooleanProperty( ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, String property) { - return applicationEnvironmentPreparedEvent - .getEnvironment() - .getProperty(property, Boolean.class); - } - - private static boolean evaluateBooleanProperty( - ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, - String property, - boolean defaultValue) { - return applicationEnvironmentPreparedEvent - .getEnvironment() - .getProperty(property, Boolean.class, defaultValue); + ConfigurableEnvironment environment = applicationEnvironmentPreparedEvent.getEnvironment(); + return environment.getProperty( + EarlyConfig.translatePropertyName(environment, property), Boolean.class); } private static Optional findAppender(Class appenderClass) { From 9c5b7bab6d0918972f5c9a9e522834f895d78dcc Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 15 Aug 2025 10:25:51 +0200 Subject: [PATCH 34/48] fix rebase --- .../OpenTelemetryAutoConfiguration.java | 32 ++++++++----------- .../jdbc/DataSourcePostProcessor.java | 14 ++++---- .../properties/ConfigPropertiesBridge.java | 21 ++++++++---- 3 files changed, 34 insertions(+), 33 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 078bd9ca8691..76bbc63a9683 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 @@ -9,9 +9,10 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.trace.TracerProvider; +import io.opentelemetry.common.ComponentLoader; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridge; +import io.opentelemetry.instrumentation.sdk.internal.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelDisabled; @@ -27,7 +28,6 @@ import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil; -import io.opentelemetry.sdk.autoconfigure.internal.ComponentLoader; import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; @@ -107,17 +107,12 @@ public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk( OtelSpringProperties otelSpringProperties, ApplicationContext applicationContext) { - return AutoConfigureUtil.setComponentLoader( - AutoConfigureUtil.setConfigPropertiesCustomizer( - AutoConfiguredOpenTelemetrySdk.builder(), - c -> - SpringConfigProperties.create( - env, - otlpExporterProperties, - resourceProperties, - otelSpringProperties, - c)), - new OpenTelemetrySdkComponentLoader(applicationContext)) + return AutoConfigureUtil.setConfigPropertiesCustomizer( + AutoConfiguredOpenTelemetrySdk.builder() + .setComponentLoader(new OpenTelemetrySdkComponentLoader(applicationContext)), + c -> + SpringConfigProperties.create( + env, otlpExporterProperties, resourceProperties, otelSpringProperties, c)) .build(); } @@ -191,9 +186,9 @@ public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { * integrate with spring boot properties. */ @Bean - public ConfigProperties otelProperties( - OpenTelemetryConfigurationModel model, ConfigProvider configProvider) { - return new DeclarativeConfigPropertiesBridge(configProvider, model.getLogLevel()); + public ConfigProperties otelProperties(ConfigProvider configProvider) { + return new DeclarativeConfigPropertiesBridgeBuilder() + .buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); } } } @@ -248,8 +243,9 @@ OtelMapConverter otelMapConverter() { @ConditionalOnMissingBean({ConfigProperties.class}) static class FallbackConfigProperties { @Bean - public ConfigProperties otelProperties() { - return DefaultConfigProperties.create(Collections.emptyMap()); + public ConfigProperties otelProperties(ApplicationContext applicationContext) { + return DefaultConfigProperties.create( + Collections.emptyMap(), new OpenTelemetrySdkComponentLoader(applicationContext)); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java index 859f8366b9d2..88baae305c96 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/DataSourcePostProcessor.java @@ -10,7 +10,6 @@ import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; @@ -60,17 +59,16 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { DataSource dataSource = (DataSource) bean; InstrumentationConfig config = configProvider.getObject(); DataSource otelDataSource = - JdbcTelemetry.builder(openTelemetryProvider.getObject()) + JdbcTelemetry.builder(openTelemetryProvider.getObject()) .setStatementSanitizationEnabled( InstrumentationConfigUtil.isStatementSanitizationEnabled( - config, "otel.instrumentation.jdbc.statement-sanitizer.enabled")) + config, "otel.instrumentation.jdbc.statement-sanitizer.enabled")) .setCaptureQueryParameters( - config.getBoolean( - "otel.instrumentation.jdbc.experimental.capture-query-parameters", false)) - .setTransactionInstrumenterEnabled( config.getBoolean( - - "otel.instrumentation.jdbc.experimental.transaction.enabled", false)) + "otel.instrumentation.jdbc.experimental.capture-query-parameters", false)) + .setTransactionInstrumenterEnabled( + config.getBoolean( + "otel.instrumentation.jdbc.experimental.transaction.enabled", false)) .build() .wrap(dataSource); diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java index f5433573a2e4..0f840594847e 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/ConfigPropertiesBridge.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties; +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.api.incubator.config.InstrumentationConfigUtil; @@ -121,20 +123,25 @@ public Map getMap(String name, Map defaultValue) @Override public boolean isDeclarative() { - return false; + return configProvider != null; } @Override public DeclarativeConfigProperties getDeclarativeConfig(String node) { - throw new IllegalStateException( - "Declarative configuration is not supported in spring boot autoconfigure yet"); + DeclarativeConfigProperties config = + InstrumentationConfigUtil.javaInstrumentationConfig(configProvider, node); + if (config == null) { + // there is no declarative config for this node + // this needs to be a different value than null to avoid confusion with + // the case when declarative config is not supported at all + return empty(); + } + return config; } @Nullable @Override - public DeclarativeConfigProperties getDeclarativeConfig(String instrumentationName) { - return configProvider != null - ? InstrumentationConfigUtil.javaInstrumentationConfig(configProvider, instrumentationName) - : null; + public ConfigProvider getConfigProvider() { + return configProvider; } } From fa5ef159e88cbd26770826be330391a3b658a12e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Sat, 16 Aug 2025 11:36:09 +0200 Subject: [PATCH 35/48] fix rebase --- .../jdbc/JdbcInstrumentationAutoConfigurationTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfigurationTest.java index e269ea83693c..a81051228f98 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/jdbc/JdbcInstrumentationAutoConfigurationTest.java @@ -10,8 +10,9 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.ConfigPropertiesBridge; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.sql.Connection; import java.sql.Statement; @@ -33,8 +34,10 @@ class JdbcInstrumentationAutoConfigurationTest { private final ApplicationContextRunner runner = new ApplicationContextRunner() .withBean( - ConfigProperties.class, - () -> DefaultConfigProperties.createFromMap(Collections.emptyMap())) + InstrumentationConfig.class, + () -> + new ConfigPropertiesBridge( + DefaultConfigProperties.createFromMap(Collections.emptyMap()))) .withConfiguration( AutoConfigurations.of( JdbcInstrumentationAutoConfiguration.class, DataSourceAutoConfiguration.class)) From fcd4fe2fbfd061e5f443c38bb2800aec62689fbf Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 29 Aug 2025 15:49:21 +0200 Subject: [PATCH 36/48] fix rebase --- .../spring/spring-boot-autoconfigure/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index dfa85158e918..7ecef2759a58 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -250,6 +250,5 @@ tasks { check { dependsOn(testing.suites, testStableSemconv) - dependsOn(testStableSemconv) } } From e82c5f627fd4724e103472476916d7dff6be71c3 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 29 Aug 2025 16:17:28 +0200 Subject: [PATCH 37/48] fix rebase --- .../spring/autoconfigure/OpenTelemetryAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 76bbc63a9683..808c9132b0df 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 @@ -12,7 +12,7 @@ import io.opentelemetry.common.ComponentLoader; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import io.opentelemetry.instrumentation.sdk.internal.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelDisabled; From f480ec84160533b927abc7bc43171cff6bfda4cf Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 5 Sep 2025 13:03:17 +0200 Subject: [PATCH 38/48] fix test --- .../spring-boot-autoconfigure/build.gradle.kts | 12 ++---------- .../OpenTelemetryAutoConfiguration.java | 4 ++-- .../testDeclarativeConfig/resources/application.yaml | 2 +- .../spring/smoketest/OtelSpringStarterSmokeTest.java | 12 +++++++++++- .../testDeclarativeConfig/resources/application.yaml | 7 ++++++- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 7ecef2759a58..7973f35f31e3 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -68,7 +68,9 @@ dependencies { library("org.springframework.boot:spring-boot-starter-data-jdbc:$springBootVersion") implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + implementation("io.opentelemetry:opentelemetry-sdk-extension-incubator") implementation(project(":sdk-autoconfigure-support")) + implementation(project(":declarative-config-bridge")) compileOnly("io.opentelemetry:opentelemetry-extension-trace-propagators") compileOnly("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") compileOnly("io.opentelemetry:opentelemetry-exporter-logging") @@ -186,16 +188,6 @@ testing { } } } - - val testStableSemconv by registering(JvmTestSuite::class) { - targets { - all { - testTask.configure { - jvmArgs("-Dotel.semconv-stability.opt-in=database") - } - } - } - } } } 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 808c9132b0df..7f049141f462 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 @@ -12,7 +12,7 @@ import io.opentelemetry.common.ComponentLoader; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import io.opentelemetry.instrumentation.sdk.DeclarativeConfigPropertiesBridgeBuilder; +import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigDisabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.DeclarativeConfigEnabled; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelDisabled; @@ -141,7 +141,7 @@ public ConfigProperties otelProperties( AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { return AutoConfigureUtil.getConfig(autoConfiguredOpenTelemetrySdk); } - } + } @Configuration @Conditional(DeclarativeConfigEnabled.class) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml index fa88b2a28125..8f263bc8ff50 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/resources/application.yaml @@ -1,6 +1,6 @@ otel: # "file_format" serves as opt-in to the new file format - file_format: "0.4" + file_format: "1.0-rc.1" # very lightweight test to make sure the declarative config is loaded # the full config is tested in smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index 513960c9b2e2..d15e6dead37f 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -7,6 +7,7 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.semconv.HttpAttributes; +import io.opentelemetry.semconv.ServiceAttributes; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -42,7 +43,16 @@ void restTemplate() { testing.waitAndAssertTraces( traceAssert -> traceAssert.hasSpansSatisfyingExactly( - span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"), + span -> + HttpSpanDataAssert.create(span) + .assertClientGetRequest("/ping") + .hasResourceSatisfying( + r -> + r.hasAttribute( + // to make sure the declarative config is picked up + // in application.yaml + ServiceAttributes.SERVICE_NAME, + "declarative-config-spring-boot-2")), span -> span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), AbstractSpringStarterSmokeTest::withSpanAssert)); diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 9fea1850cad5..264a1d34a18d 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -1,6 +1,11 @@ otel: # "file_format" serves as opt-in to the new file format - file_format: "0.4" + file_format: "1.0-rc.1" + resource: + attributes: + - name: service.name + value: declarative-config-spring-boot-2 + tracer_provider: processors: - simple: From fb975cc847c2cb3d68ad06b24109a8f77ea03f97 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Sep 2025 10:37:23 +0200 Subject: [PATCH 39/48] bug was fixed --- .../autoconfigure/OpenTelemetryAutoConfiguration.java | 5 ----- .../spring/autoconfigure/DeclarativeConfigTest.java | 9 --------- 2 files changed, 14 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 7f049141f462..18c8527af039 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 @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.spring.autoconfigure; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.incubator.config.ConfigProvider; import io.opentelemetry.api.trace.TracerProvider; @@ -160,10 +159,6 @@ public OpenTelemetry openTelemetry( DeclarativeConfiguration.create( model, new OpenTelemetrySdkComponentLoader(applicationContext)); Runtime.getRuntime().addShutdownHook(new Thread(sdk::close)); - // todo there is no equivalent to - // https://github.com/open-telemetry/opentelemetry-java/blob/7655192df504d28da2d2013f2fc49ec44ef6202e/sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/LoggerProviderConfiguration.java#L96 - // so we get a NPE when there is no global OpenTelemetry instance set - GlobalOpenTelemetry.set(sdk); logStart(); return sdk; } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index 2d12325779d6..aba987ba0595 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -7,11 +7,9 @@ import static org.assertj.core.api.Assertions.assertThat; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; import io.opentelemetry.sdk.OpenTelemetrySdk; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; @@ -36,13 +34,6 @@ public OpenTelemetry customOpenTelemetry() { // to load application.yaml .withInitializer(new ConfigDataApplicationContextInitializer()); - @BeforeEach - void setUp() { - // todo remove - see - // io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration.OpenTelemetrySdkConfig.EmbeddedConfigFileConfig - GlobalOpenTelemetry.resetForTest(); - } - @Test @DisplayName( "when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry") From d4fd64ae20eae9bdab1de8e82a44ef1f0a2fc045 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Sep 2025 11:35:26 +0200 Subject: [PATCH 40/48] add distro --- .../OpenTelemetryAutoConfiguration.java | 36 ++++++++--- .../resources/DistroComponentProvider.java | 33 ++++++++++ .../DistroVersionResourceProvider.java | 4 ++ .../resources/ResourceCustomizerProvider.java | 63 +++++++++++++++++++ .../smoketest/OtelSpringStarterSmokeTest.java | 21 ++++++- .../resources/application.yaml | 3 + 6 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroComponentProvider.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/ResourceCustomizerProvider.java 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 18c8527af039..02474251bb66 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 @@ -22,7 +22,9 @@ import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelSpringProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.SpringConfigProperties; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.DistroComponentProvider; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.DistroVersionResourceProvider; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.ResourceCustomizerProvider; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources.SpringResourceProvider; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; @@ -30,10 +32,13 @@ import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import io.opentelemetry.sdk.resources.Resource; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -72,16 +77,8 @@ public OpenTelemetryAutoConfiguration() {} @Configuration @Conditional(OtelEnabled.class) @ConditionalOnMissingBean(OpenTelemetry.class) + @SuppressWarnings("OtelPrivateConstructorForUtilityClass") static class OpenTelemetrySdkConfig { - @Bean - public ResourceProvider otelSpringResourceProvider(Optional buildProperties) { - return new SpringResourceProvider(buildProperties); - } - - @Bean - public ResourceProvider otelDistroVersionResourceProvider() { - return new DistroVersionResourceProvider(); - } @Configuration @EnableConfigurationProperties({ @@ -92,6 +89,17 @@ public ResourceProvider otelDistroVersionResourceProvider() { @Conditional(DeclarativeConfigDisabled.class) static class PropertiesConfig { + @Bean + public ResourceProvider otelSpringResourceProvider( + Optional buildProperties) { + return new SpringResourceProvider(buildProperties); + } + + @Bean + public ResourceProvider otelDistroVersionResourceProvider() { + return new DistroVersionResourceProvider(); + } + @Bean @ConfigurationPropertiesBinding OtelMapConverter otelMapConverter() { @@ -185,6 +193,16 @@ public ConfigProperties otelProperties(ConfigProvider configProvider) { return new DeclarativeConfigPropertiesBridgeBuilder() .buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); } + + @Bean + public DeclarativeConfigurationCustomizerProvider distroConfigurationCustomizerProvider() { + return new ResourceCustomizerProvider(); + } + + @Bean + public ComponentProvider distroComponentProvider() { + return new DistroComponentProvider(); + } } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroComponentProvider.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroComponentProvider.java new file mode 100644 index 000000000000..ad1a669067cd --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroComponentProvider.java @@ -0,0 +1,33 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources; + +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; +import io.opentelemetry.sdk.resources.Resource; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +@SuppressWarnings("rawtypes") +public class DistroComponentProvider implements ComponentProvider { + + @Override + public Class getType() { + return Resource.class; + } + + @Override + public String getName() { + return "opentelemetry-spring-boot-starter"; + } + + @Override + public Resource create(DeclarativeConfigProperties config) { + return DistroVersionResourceProvider.get(); + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProvider.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProvider.java index 8ba185f97b98..db66ce9f0220 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProvider.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/DistroVersionResourceProvider.java @@ -28,6 +28,10 @@ public class DistroVersionResourceProvider implements ResourceProvider { @Override public Resource createResource(ConfigProperties config) { + return get(); + } + + static Resource get() { return Resource.create( Attributes.of( TELEMETRY_DISTRO_NAME, diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/ResourceCustomizerProvider.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/ResourceCustomizerProvider.java new file mode 100644 index 000000000000..1bbd1af4f5d2 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/resources/ResourceCustomizerProvider.java @@ -0,0 +1,63 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.resources; + +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectionModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalResourceDetectorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ResourceModel; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class ResourceCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { + + // opentelemetry-javaagent-distribution: adds "distro.name" and "distro.version" attributes + // (DistroComponentProvider in this package) + private static final List REQUIRED_DETECTORS = + Collections.singletonList("opentelemetry-spring-boot-starter"); + + @Override + public void customize(DeclarativeConfigurationCustomizer customizer) { + customizer.addModelCustomizer( + model -> { + ResourceModel resource = model.getResource(); + if (resource == null) { + resource = new ResourceModel(); + model.withResource(resource); + } + ExperimentalResourceDetectionModel detectionModel = resource.getDetectionDevelopment(); + if (detectionModel == null) { + detectionModel = new ExperimentalResourceDetectionModel(); + resource.withDetectionDevelopment(detectionModel); + } + List detectors = + Objects.requireNonNull(detectionModel.getDetectors()); + Set names = + detectors.stream() + .flatMap(detector -> detector.getAdditionalProperties().keySet().stream()) + .collect(Collectors.toSet()); + + for (String name : REQUIRED_DETECTORS) { + if (!names.contains(name)) { + ExperimentalResourceDetectorModel detector = new ExperimentalResourceDetectorModel(); + detector.getAdditionalProperties().put(name, null); + // add first (the least precedence) + // so that the user can add a differently named detector that takes precedence + detectors.add(0, detector); + } + } + return model; + }); + } +} diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java index d15e6dead37f..214e464fde8b 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java @@ -5,9 +5,14 @@ package io.opentelemetry.spring.smoketest; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; + import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.semconv.HttpAttributes; import io.opentelemetry.semconv.ServiceAttributes; +import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes; +import io.opentelemetry.semconv.incubating.TelemetryIncubatingAttributes; +import org.assertj.core.api.AbstractCharSequenceAssert; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -54,7 +59,21 @@ void restTemplate() { ServiceAttributes.SERVICE_NAME, "declarative-config-spring-boot-2")), span -> - span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), + span.hasKind(SpanKind.SERVER) + .hasResourceSatisfying( + r -> + r.hasAttribute( + TelemetryIncubatingAttributes.TELEMETRY_DISTRO_NAME, + "opentelemetry-spring-boot-starter") + .hasAttribute( + satisfies( + TelemetryIncubatingAttributes.TELEMETRY_DISTRO_VERSION, + AbstractCharSequenceAssert::isNotBlank)) + .hasAttribute( + satisfies( + ServiceIncubatingAttributes.SERVICE_INSTANCE_ID, + AbstractCharSequenceAssert::isNotBlank))) + .hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"), AbstractSpringStarterSmokeTest::withSpanAssert)); } } diff --git a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml index 264a1d34a18d..6b24c0ee67fa 100644 --- a/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml +++ b/smoke-tests-otel-starter/spring-boot-2/src/testDeclarativeConfig/resources/application.yaml @@ -2,6 +2,9 @@ otel: # "file_format" serves as opt-in to the new file format file_format: "1.0-rc.1" resource: + detection/development: + detectors: + - service: attributes: - name: service.name value: declarative-config-spring-boot-2 From 63a318a9cbd2a74d0bf7ed8c3313b4bb891d7d4d Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Sep 2025 14:36:04 +0200 Subject: [PATCH 41/48] map default enabled --- .../build.gradle.kts | 2 + .../autoconfigure/internal/EarlyConfig.java | 76 +++++++++++++------ .../logging/LogbackAppenderInstaller.java | 2 +- .../OpenTelemetryAutoConfigurationTest.java | 4 +- .../autoconfigure/DeclarativeConfigTest.java | 34 ++++++++- 5 files changed, 91 insertions(+), 27 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index 7973f35f31e3..8801ea1797a8 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -85,6 +85,7 @@ dependencies { testLibrary("org.springframework.boot:spring-boot-starter-test:$springBootVersion") { exclude("org.junit.vintage", "junit-vintage-engine") } + testImplementation("javax.servlet:javax.servlet-api:3.1.0") testImplementation("jakarta.servlet:jakarta.servlet-api:5.0.0") testRuntimeOnly("com.h2database:h2:1.4.197") @@ -186,6 +187,7 @@ testing { implementation("org.springframework.boot:spring-boot-starter-test:$springBootVersion") { exclude("org.junit.vintage", "junit-vintage-engine") } + implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") } } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java index a939de4d07a8..b55ba2813568 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -5,8 +5,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.util.HashMap; import java.util.Map; +import javax.annotation.Nullable; import org.springframework.core.env.Environment; /** @@ -22,45 +24,76 @@ private EarlyConfig() {} DECLARATIVE_CONFIG_PROPERTY_MAPPING.put("otel.sdk.disabled", "otel.disabled"); DECLARATIVE_CONFIG_PROPERTY_MAPPING.put( "otel.instrumentation.%s.enabled", "otel.instrumentation/development.java.%s.enabled"); - DECLARATIVE_CONFIG_PROPERTY_MAPPING.put( - "otel.instrumentation.common.default-enabled", - "otel.instrumentation/development.java.common.default.enabled"); } public static boolean otelEnabled(Environment environment) { return !environment.getProperty( - translatePropertyName(environment, "otel.sdk.disabled"), Boolean.class, false); + translatePropertyName(environment, "otel.sdk.disabled", null), Boolean.class, false); } - public static Boolean isDeclarativeConfig(Environment environment) { + public static boolean isDeclarativeConfig(Environment environment) { return environment.getProperty("otel.file_format", String.class) != null; } - public static String translatePropertyName(Environment environment, String name) { + public static boolean isDefaultEnabled(Environment environment) { if (isDeclarativeConfig(environment)) { - String value = DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name); - if (value != null) { - return value; - } - if (name.startsWith("otel.instrumentation.")) { - return String.format( - "otel.instrumentation/development.java.%s", - name.substring("otel.instrumentation.".length())); + String mode = + environment.getProperty( + "otel.instrumentation/development.java.spring_starter.instrumentation_mode", + String.class, + "default"); + + switch (mode) { + case "none": + return false; + case "default": + return true; + default: + throw new ConfigurationException("Unknown instrumentation mode: " + mode); } + } else { + return environment.getProperty( + "otel.instrumentation.common.default-enabled", Boolean.class, true); + } + } - throw new IllegalStateException( - "No mapping found for property name: " + name + ". Please report this bug."); + public static String translatePropertyName( + Environment environment, String name, @Nullable String arg) { + if (isDeclarativeConfig(environment)) { + String key = declarativeConfigKey(name); + if (arg != null) { + key = String.format(key, arg); + } + return key.replace('-', '_'); } else { - return name; + String key = name; + if (arg != null) { + key = String.format(key, arg); + } + return key; } } + private static String declarativeConfigKey(String name) { + String value = DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name); + if (value != null) { + return value; + } + if (name.startsWith("otel.instrumentation.")) { + return String.format( + "otel.instrumentation/development.java.%s", + name.substring("otel.instrumentation.".length())); + } + + throw new IllegalStateException( + "No mapping found for property name: " + name + ". Please report this bug."); + } + public static boolean isInstrumentationEnabled( Environment environment, String name, boolean defaultValue) { Boolean explicit = environment.getProperty( - String.format( - translatePropertyName(environment, "otel.instrumentation.%s.enabled"), name), + translatePropertyName(environment, "otel.instrumentation.%s.enabled", name), Boolean.class); if (explicit != null) { return explicit; @@ -68,9 +101,6 @@ public static boolean isInstrumentationEnabled( if (!defaultValue) { return false; } - return environment.getProperty( - translatePropertyName(environment, "otel.instrumentation.common.default-enabled"), - Boolean.class, - true); + return isDefaultEnabled(environment); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java index 51588f786d25..19e6d4e7445a 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java @@ -221,7 +221,7 @@ private static Boolean evaluateBooleanProperty( ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, String property) { ConfigurableEnvironment environment = applicationEnvironmentPreparedEvent.getEnvironment(); return environment.getProperty( - EarlyConfig.translatePropertyName(environment, property), Boolean.class); + EarlyConfig.translatePropertyName(environment, property, null), Boolean.class); } private static Optional findAppender(Class appenderClass) { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java index cf97dc2f7302..be29f798f579 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/OpenTelemetryAutoConfigurationTest.java @@ -26,7 +26,7 @@ /** Spring Boot auto configuration test for {@link OpenTelemetryAutoConfiguration}. */ class OpenTelemetryAutoConfigurationTest { @TestConfiguration - static class CustomTracerConfiguration { + static class CustomOtelConfiguration { @Bean public OpenTelemetry customOpenTelemetry() { return OpenTelemetry.noop(); @@ -48,7 +48,7 @@ public OpenTelemetry customOpenTelemetry() { "when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry") void customOpenTelemetry() { this.contextRunner - .withUserConfiguration(CustomTracerConfiguration.class) + .withUserConfiguration(CustomOtelConfiguration.class) .withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class)) .run( context -> diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index aba987ba0595..65d749598b2a 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.SpringWebInstrumentationAutoConfiguration; import io.opentelemetry.sdk.OpenTelemetrySdk; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -40,6 +41,7 @@ public OpenTelemetry customOpenTelemetry() { void customOpenTelemetry() { this.contextRunner .withUserConfiguration(CustomTracerConfiguration.class) + .withPropertyValues("otel.file_format=1.0-rc.1") .run( context -> assertThat(context) @@ -72,7 +74,7 @@ void initializeProvidersAndOpenTelemetry() { @Test void shouldInitializeSdkWhenNotDisabled() { this.contextRunner - .withPropertyValues("otel.disabled=false") + .withPropertyValues("otel.file_format=1.0-rc.1", "otel.disabled=false") .run( context -> assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class)); @@ -82,10 +84,40 @@ void shouldInitializeSdkWhenNotDisabled() { void shouldInitializeNoopOpenTelemetryWhenSdkIsDisabled() { this.contextRunner .withPropertyValues( + "otel.file_format=1.0-rc.1", "otel.disabled=true", "otel.resource.attributes=service.name=workflow-backend-dev,service.version=3c8f9ce9") .run( context -> assertThat(context).getBean("openTelemetry").isEqualTo(OpenTelemetry.noop())); } + + @Test + void shouldLoadInstrumentation() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)) + .withPropertyValues("otel.file_format=1.0-rc.1") + .run(context -> assertThat(context).hasBean("otelRestTemplateBeanPostProcessor")); + } + + @Test + void shouldNotLoadInstrumentationWhenDefaultIsDisabled() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)) + .withPropertyValues( + "otel.file_format=1.0-rc.1", + "otel.instrumentation/development.java.spring_starter.instrumentation_mode=none") + .run(context -> assertThat(context).doesNotHaveBean("otelRestTemplateBeanPostProcessor")); + } + + @Test + void shouldLoadInstrumentationWhenExplicitlyEnabled() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)) + .withPropertyValues( + "otel.file_format=1.0-rc.1", + "otel.instrumentation/development.java.spring_starter.instrumentation_mode=none", + "otel.instrumentation/development.java.spring_web.enabled=true") + .run(context -> assertThat(context).hasBean("otelRestTemplateBeanPostProcessor")); + } } From 1b4a2a0e8c108be1c1ed3205f485f4259bc9a264 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 29 Sep 2025 16:51:50 +0200 Subject: [PATCH 42/48] simplify --- .../autoconfigure/internal/EarlyConfig.java | 71 ++++++++----------- .../logging/LogbackAppenderInstaller.java | 2 +- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java index b55ba2813568..c8a63554a56f 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -6,9 +6,6 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import java.util.HashMap; -import java.util.Map; -import javax.annotation.Nullable; import org.springframework.core.env.Environment; /** @@ -18,17 +15,13 @@ public class EarlyConfig { private EarlyConfig() {} - private static final Map DECLARATIVE_CONFIG_PROPERTY_MAPPING = new HashMap<>(); - - static { - DECLARATIVE_CONFIG_PROPERTY_MAPPING.put("otel.sdk.disabled", "otel.disabled"); - DECLARATIVE_CONFIG_PROPERTY_MAPPING.put( - "otel.instrumentation.%s.enabled", "otel.instrumentation/development.java.%s.enabled"); - } - public static boolean otelEnabled(Environment environment) { - return !environment.getProperty( - translatePropertyName(environment, "otel.sdk.disabled", null), Boolean.class, false); + boolean disabled = + environment.getProperty( + getPropertyName(environment, "otel.sdk.disabled", "otel.disabled"), + Boolean.class, + false); + return !disabled; } public static boolean isDeclarativeConfig(Environment environment) { @@ -57,44 +50,33 @@ public static boolean isDefaultEnabled(Environment environment) { } } - public static String translatePropertyName( - Environment environment, String name, @Nullable String arg) { + public static String translatePropertyName(Environment environment, String name) { if (isDeclarativeConfig(environment)) { - String key = declarativeConfigKey(name); - if (arg != null) { - key = String.format(key, arg); + if (name.startsWith("otel.instrumentation.")) { + return String.format( + "otel.instrumentation/development.java.%s", + name.substring("otel.instrumentation.".length())) + .replace('-', '_'); } - return key.replace('-', '_'); - } else { - String key = name; - if (arg != null) { - key = String.format(key, arg); - } - return key; - } - } - private static String declarativeConfigKey(String name) { - String value = DECLARATIVE_CONFIG_PROPERTY_MAPPING.get(name); - if (value != null) { - return value; - } - if (name.startsWith("otel.instrumentation.")) { - return String.format( - "otel.instrumentation/development.java.%s", - name.substring("otel.instrumentation.".length())); + throw new IllegalStateException( + "No mapping found for property name: " + name + ". Please report this bug."); + } else { + return name; } - - throw new IllegalStateException( - "No mapping found for property name: " + name + ". Please report this bug."); } public static boolean isInstrumentationEnabled( Environment environment, String name, boolean defaultValue) { - Boolean explicit = + String property = environment.getProperty( - translatePropertyName(environment, "otel.instrumentation.%s.enabled", name), - Boolean.class); + String.format( + getPropertyName( + environment, + "otel.instrumentation.%s.enabled", + "otel.instrumentation/development.java.%s.enabled")), + name); + Boolean explicit = environment.getProperty(property, Boolean.class); if (explicit != null) { return explicit; } @@ -103,4 +85,9 @@ public static boolean isInstrumentationEnabled( } return isDefaultEnabled(environment); } + + private static String getPropertyName( + Environment environment, String propertyBased, String declarative) { + return isDeclarativeConfig(environment) ? declarative : propertyBased; + } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java index 19e6d4e7445a..51588f786d25 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/LogbackAppenderInstaller.java @@ -221,7 +221,7 @@ private static Boolean evaluateBooleanProperty( ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent, String property) { ConfigurableEnvironment environment = applicationEnvironmentPreparedEvent.getEnvironment(); return environment.getProperty( - EarlyConfig.translatePropertyName(environment, property, null), Boolean.class); + EarlyConfig.translatePropertyName(environment, property), Boolean.class); } private static Optional findAppender(Class appenderClass) { From 62903e52ca0decb4f58e5979a37327287302976b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 29 Sep 2025 16:57:15 +0200 Subject: [PATCH 43/48] api diff --- .../opentelemetry-spring-boot-autoconfigure.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt index 3733a382e4dd..f679900a10bf 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-spring-boot-autoconfigure.txt @@ -1,2 +1,5 @@ Comparing source compatibility of opentelemetry-spring-boot-autoconfigure-2.21.0-SNAPSHOT.jar against opentelemetry-spring-boot-autoconfigure-2.20.1.jar -No changes. \ No newline at end of file +=== UNCHANGED CLASS: PUBLIC io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + --- REMOVED ANNOTATION: org.springframework.boot.context.properties.EnableConfigurationProperties + --- REMOVED ELEMENT: value=io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtlpExporterProperties,io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelResourceProperties,io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.OtelSpringProperties (-) From c3dcfc8e91aefeae66e789d828eb5c1b5b9992ef Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 30 Sep 2025 12:13:19 +0200 Subject: [PATCH 44/48] fix --- .../spring/autoconfigure/internal/EarlyConfig.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java index c8a63554a56f..db186191f871 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -69,13 +69,10 @@ public static String translatePropertyName(Environment environment, String name) public static boolean isInstrumentationEnabled( Environment environment, String name, boolean defaultValue) { String property = - environment.getProperty( - String.format( - getPropertyName( - environment, - "otel.instrumentation.%s.enabled", - "otel.instrumentation/development.java.%s.enabled")), - name); + getPropertyName( + environment, + String.format("otel.instrumentation.%s.enabled", name), + String.format("otel.instrumentation/development.java.%s.enabled", name)); Boolean explicit = environment.getProperty(property, Boolean.class); if (explicit != null) { return explicit; From 94bef101dafdad097138504178b9c25a75070659 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 30 Sep 2025 13:45:42 +0200 Subject: [PATCH 45/48] fix --- .../spring/autoconfigure/internal/EarlyConfig.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java index db186191f871..19a64749a5b9 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/EarlyConfig.java @@ -53,10 +53,10 @@ public static boolean isDefaultEnabled(Environment environment) { public static String translatePropertyName(Environment environment, String name) { if (isDeclarativeConfig(environment)) { if (name.startsWith("otel.instrumentation.")) { - return String.format( + return toSnakeCase( + String.format( "otel.instrumentation/development.java.%s", - name.substring("otel.instrumentation.".length())) - .replace('-', '_'); + name.substring("otel.instrumentation.".length()))); } throw new IllegalStateException( @@ -66,13 +66,17 @@ public static String translatePropertyName(Environment environment, String name) } } + private static String toSnakeCase(String string) { + return string.replace('-', '_'); + } + public static boolean isInstrumentationEnabled( Environment environment, String name, boolean defaultValue) { String property = getPropertyName( environment, String.format("otel.instrumentation.%s.enabled", name), - String.format("otel.instrumentation/development.java.%s.enabled", name)); + String.format("otel.instrumentation/development.java.%s.enabled", toSnakeCase(name))); Boolean explicit = environment.getProperty(property, Boolean.class); if (explicit != null) { return explicit; From a7540f5021c728906b155a74b917e201c67b1796 Mon Sep 17 00:00:00 2001 From: Jay DeLuca Date: Tue, 7 Oct 2025 09:28:47 -0400 Subject: [PATCH 46/48] add test condition --- .../autoconfigure/OpenTelemetryAutoConfiguration.java | 2 +- .../spring/autoconfigure/DeclarativeConfigTest.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) 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 02474251bb66..81b54fb10e6d 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 @@ -77,7 +77,7 @@ public OpenTelemetryAutoConfiguration() {} @Configuration @Conditional(OtelEnabled.class) @ConditionalOnMissingBean(OpenTelemetry.class) - @SuppressWarnings("OtelPrivateConstructorForUtilityClass") + @SuppressWarnings("OtelPrivateConstructorForUtilityClass") // spring uses reflection static class OpenTelemetrySdkConfig { @Configuration diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java index 65d749598b2a..d15468a17944 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/testDeclarativeConfig/java/io/opentelemetry/instrumentation/spring/autoconfigure/DeclarativeConfigTest.java @@ -120,4 +120,15 @@ void shouldLoadInstrumentationWhenExplicitlyEnabled() { "otel.instrumentation/development.java.spring_web.enabled=true") .run(context -> assertThat(context).hasBean("otelRestTemplateBeanPostProcessor")); } + + @Test + void shouldNotLoadInstrumentationWhenExplicitlyDisabled() { + this.contextRunner + .withConfiguration(AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class)) + .withPropertyValues( + "otel.file_format=1.0-rc.1", + "otel.instrumentation/development.java.spring_starter.instrumentation_mode=none", + "otel.instrumentation/development.java.spring_web.enabled=false") + .run(context -> assertThat(context).doesNotHaveBean("otelRestTemplateBeanPostProcessor")); + } } From 823068de23a2c7e84122baa0930204efdea5869a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Tue, 7 Oct 2025 15:52:55 +0200 Subject: [PATCH 47/48] reorder --- .../OpenTelemetryAutoConfiguration.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 81b54fb10e6d..9aeca1459865 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 @@ -171,12 +171,6 @@ public OpenTelemetry openTelemetry( return sdk; } - @Bean - public InstrumentationConfig instrumentationConfig( - ConfigProperties properties, ConfigProvider configProvider) { - return new ConfigPropertiesBridge(properties, configProvider); - } - @Bean public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) { return SdkConfigProvider.create(model); @@ -194,6 +188,12 @@ public ConfigProperties otelProperties(ConfigProvider configProvider) { .buildFromInstrumentationConfig(configProvider.getInstrumentationConfig()); } + @Bean + public InstrumentationConfig instrumentationConfig( + ConfigProperties properties, ConfigProvider configProvider) { + return new ConfigPropertiesBridge(properties, configProvider); + } + @Bean public DeclarativeConfigurationCustomizerProvider distroConfigurationCustomizerProvider() { return new ResourceCustomizerProvider(); From f6af6c192a376a0a24a856ed9856a445e1f85132 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Fri, 5 Sep 2025 14:23:35 +0200 Subject: [PATCH 48/48] add spring starter declarative config span logging ./gradlew spotlessApply --- ...onfigLoggingExporterAutoConfiguration.java | 50 ++++++++++++ .../SpanLoggingCustomizerProviderTest.java | 76 ++++++++++++++++++ .../SpanLoggingCustomizerProvider.java | 59 +------------- sdk-autoconfigure-support/build.gradle.kts | 1 + ...AbstractSpanLoggingCustomizerProvider.java | 78 +++++++++++++++++++ 5 files changed, 209 insertions(+), 55 deletions(-) create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/DeclarativeConfigLoggingExporterAutoConfiguration.java create mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/SpanLoggingCustomizerProviderTest.java create mode 100644 sdk-autoconfigure-support/src/main/java/io/opentelemetry/instrumentation/logging/internal/AbstractSpanLoggingCustomizerProvider.java diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/DeclarativeConfigLoggingExporterAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/DeclarativeConfigLoggingExporterAutoConfiguration.java new file mode 100644 index 000000000000..a5cf0ea7b72e --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/DeclarativeConfigLoggingExporterAutoConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; + +import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; + +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.exporter.logging.LoggingSpanExporter; +import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider; +import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OtelEnabled; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.SdkConfigProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +@Conditional(OtelEnabled.class) +@ConditionalOnClass(LoggingSpanExporter.class) +@Configuration +public class DeclarativeConfigLoggingExporterAutoConfiguration { + @Bean + public DeclarativeConfigurationCustomizerProvider spanLoggingCustomizerProvider() { + return new SpanLoggingCustomizerProvider(); + } + + static class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider { + @Override + protected boolean isEnabled(OpenTelemetryConfigurationModel model) { + DeclarativeConfigProperties instrumentation = + SdkConfigProvider.create(model).getInstrumentationConfig(); + if (instrumentation == null) { + return false; + } + + return instrumentation + .getStructured("java", empty()) + .getStructured("spring_starter", empty()) + .getBoolean("debug", false); + } + } +} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/SpanLoggingCustomizerProviderTest.java b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/SpanLoggingCustomizerProviderTest.java new file mode 100644 index 000000000000..7328adcfedb8 --- /dev/null +++ b/instrumentation/spring/spring-boot-autoconfigure/src/test/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/logging/SpanLoggingCustomizerProviderTest.java @@ -0,0 +1,76 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.logging; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class SpanLoggingCustomizerProviderTest { + + @ParameterizedTest + @CsvSource({ + "true, false, true", + "false, false, false", + ", false, false", // empty value means property is not set + "invalid, false, false", + "true, true, true", + }) + void addSpanLoggingExporter(String propertyValue, boolean alreadyAdded, boolean expected) { + String debug = + propertyValue == null + ? "" + : "instrumentation/development: \n" + + " java: \n" + + " spring_starter: \n" + + " debug: " + + propertyValue; + + String yaml = + alreadyAdded + ? "file_format: \"1.0-rc.1\"\n" + + "tracer_provider:\n" + + " processors:\n" + + " - simple:\n" + + " exporter:\n" + + " console: {}\n" + : "file_format: \"1.0-rc.1\"\n" + debug; + + OpenTelemetryConfigurationModel model = + applyCustomizer( + DeclarativeConfiguration.parse( + new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8))), + new DeclarativeConfigLoggingExporterAutoConfiguration.SpanLoggingCustomizerProvider()); + + String console = "ConsoleExporterModel"; + if (expected) { + assertThat(model.toString()).containsOnlyOnce(console); + } else { + assertThat(model.toString()).doesNotContain(console); + } + } + + private static OpenTelemetryConfigurationModel applyCustomizer( + OpenTelemetryConfigurationModel model, + DeclarativeConfigLoggingExporterAutoConfiguration.SpanLoggingCustomizerProvider provider) { + List> customizers = + new ArrayList<>(); + provider.customize(c -> customizers.add(c)); + for (Function customizer : + customizers) { + model = customizer.apply(model); + } + return model; + } +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SpanLoggingCustomizerProvider.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SpanLoggingCustomizerProvider.java index 4a012d253d46..00634e858503 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SpanLoggingCustomizerProvider.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/SpanLoggingCustomizerProvider.java @@ -7,69 +7,18 @@ import com.google.auto.service.AutoService; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; -import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.instrumentation.logging.internal.AbstractSpanLoggingCustomizerProvider; import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel; import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; -import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; /** Adds span logging exporter for debug mode */ @AutoService(DeclarativeConfigurationCustomizerProvider.class) -public class SpanLoggingCustomizerProvider implements DeclarativeConfigurationCustomizerProvider { +public class SpanLoggingCustomizerProvider extends AbstractSpanLoggingCustomizerProvider { @Override - public void customize(DeclarativeConfigurationCustomizer customizer) { - customizer.addModelCustomizer( - model -> { - maybeEnableLoggingExporter(model); - return model; - }); - } - - private static void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) { + protected boolean isEnabled(OpenTelemetryConfigurationModel model) { // read from system properties as it's an early init property and the config bridge is not // available here - if (!ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false)) { - return; - } - // don't install another instance if the user has already explicitly requested it. - if (loggingExporterIsAlreadyConfigured(model)) { - return; - } - TracerProviderModel tracerProvider = model.getTracerProvider(); - if (tracerProvider == null) { - tracerProvider = new TracerProviderModel(); - model.withTracerProvider(tracerProvider); - } - SpanProcessorModel processor = - new SpanProcessorModel() - .withSimple( - new SimpleSpanProcessorModel() - .withExporter(new SpanExporterModel().withConsole(new ConsoleExporterModel()))); - tracerProvider.getProcessors().add(processor); - } - - private static boolean loggingExporterIsAlreadyConfigured(OpenTelemetryConfigurationModel model) { - TracerProviderModel tracerProvider = model.getTracerProvider(); - if (tracerProvider == null) { - return false; - } - for (SpanProcessorModel processor : tracerProvider.getProcessors()) { - SimpleSpanProcessorModel simple = processor.getSimple(); - if (simple == null) { - continue; - } - SpanExporterModel exporter = simple.getExporter(); - if (exporter == null) { - continue; - } - if (exporter.getConsole() != null) { - return true; - } - } - return false; + return ConfigPropertiesUtil.getBoolean("otel.javaagent.debug", false); } } diff --git a/sdk-autoconfigure-support/build.gradle.kts b/sdk-autoconfigure-support/build.gradle.kts index c2948406f7e1..cf9be9f90a7d 100644 --- a/sdk-autoconfigure-support/build.gradle.kts +++ b/sdk-autoconfigure-support/build.gradle.kts @@ -7,6 +7,7 @@ group = "io.opentelemetry.instrumentation" dependencies { api("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + api("io.opentelemetry:opentelemetry-sdk-extension-incubator") compileOnly("com.google.code.findbugs:annotations") testCompileOnly("com.google.code.findbugs:annotations") diff --git a/sdk-autoconfigure-support/src/main/java/io/opentelemetry/instrumentation/logging/internal/AbstractSpanLoggingCustomizerProvider.java b/sdk-autoconfigure-support/src/main/java/io/opentelemetry/instrumentation/logging/internal/AbstractSpanLoggingCustomizerProvider.java new file mode 100644 index 000000000000..17c15209ca4c --- /dev/null +++ b/sdk-autoconfigure-support/src/main/java/io/opentelemetry/instrumentation/logging/internal/AbstractSpanLoggingCustomizerProvider.java @@ -0,0 +1,78 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.logging.internal; + +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizer; +import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ConsoleExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleSpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporterModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessorModel; +import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProviderModel; + +/** + * Adds span logging exporter for debug mode + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public abstract class AbstractSpanLoggingCustomizerProvider + implements DeclarativeConfigurationCustomizerProvider { + + protected abstract boolean isEnabled(OpenTelemetryConfigurationModel model); + + @Override + public void customize(DeclarativeConfigurationCustomizer customizer) { + customizer.addModelCustomizer( + model -> { + maybeEnableLoggingExporter(model); + return model; + }); + } + + private void maybeEnableLoggingExporter(OpenTelemetryConfigurationModel model) { + if (!isEnabled(model)) { + return; + } + // don't install another instance if the user has already explicitly requested it. + if (loggingExporterIsAlreadyConfigured(model)) { + return; + } + TracerProviderModel tracerProvider = model.getTracerProvider(); + if (tracerProvider == null) { + tracerProvider = new TracerProviderModel(); + model.withTracerProvider(tracerProvider); + } + SpanProcessorModel processor = + new SpanProcessorModel() + .withSimple( + new SimpleSpanProcessorModel() + .withExporter(new SpanExporterModel().withConsole(new ConsoleExporterModel()))); + tracerProvider.getProcessors().add(processor); + } + + private static boolean loggingExporterIsAlreadyConfigured(OpenTelemetryConfigurationModel model) { + TracerProviderModel tracerProvider = model.getTracerProvider(); + if (tracerProvider == null) { + return false; + } + for (SpanProcessorModel processor : tracerProvider.getProcessors()) { + SimpleSpanProcessorModel simple = processor.getSimple(); + if (simple == null) { + continue; + } + SpanExporterModel exporter = simple.getExporter(); + if (exporter == null) { + continue; + } + if (exporter.getConsole() != null) { + return true; + } + } + return false; + } +}