This commit is contained in:
Gregor Zeitlinger 2025-09-19 09:00:59 +02:00 committed by GitHub
commit c1f02661bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 1056 additions and 276 deletions

View File

@ -1,2 +1,5 @@
Comparing source compatibility of opentelemetry-spring-boot-autoconfigure-2.21.0-SNAPSHOT.jar against opentelemetry-spring-boot-autoconfigure-2.20.0.jar
No changes.
=== 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 (-)

View File

@ -36,6 +36,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")
// 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"))
@ -66,7 +69,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")
@ -81,6 +86,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")
@ -174,6 +180,17 @@ testing {
}
}
}
val testDeclarativeConfig by registering(JvmTestSuite::class) {
dependencies {
implementation(project())
implementation("io.opentelemetry:opentelemetry-sdk")
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")
}
}
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure;
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfigurationModel;
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 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) {
return getModel(environment, (OriginTrackedMapPropertySource) propertySource);
}
}
throw new IllegalStateException("No application.yaml file found.");
}
private static OpenTelemetryConfigurationModel getModel(
ConfigurableEnvironment environment, OriginTrackedMapPropertySource source)
throws IOException {
Matcher matcher = PATTERN.matcher(source.getName());
if (matcher.matches()) {
String file = matcher.group(1);
try (InputStream resourceAsStream =
environment.getClass().getClassLoader().getResourceAsStream(file)) {
if (resourceAsStream != null) {
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<String, Object> data = (Map<String, Object>) o;
Map<String, Map<String, Object>> otel = (Map<String, Map<String, Object>>) data.get("otel");
if (otel != null) {
return dump.dumpToString(otel);
}
}
throw new IllegalStateException("No 'otel' configuration found in the YAML file.");
}
private static OpenTelemetryConfigurationModel extractOtelConfigFile(InputStream content) {
String node = parseOtelNode(content);
if (node == null || node.isEmpty()) {
throw new IllegalStateException("otel node is empty or null in the YAML file.");
}
return DeclarativeConfiguration.parse(
new ByteArrayInputStream(node.getBytes(StandardCharsets.UTF_8)));
}
}

View File

@ -6,23 +6,40 @@
package io.opentelemetry.instrumentation.spring.autoconfigure;
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.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;
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;
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;
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
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;
import java.util.Optional;
@ -33,7 +50,6 @@ import org.slf4j.Logger;
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;
@ -41,7 +57,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
@ -52,100 +68,156 @@ import org.springframework.core.env.Environment;
* <p>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")
@Conditional(OtelEnabled.class)
@ConditionalOnMissingBean(OpenTelemetry.class)
@SuppressWarnings("OtelPrivateConstructorForUtilityClass")
static class OpenTelemetrySdkConfig {
@Bean
public OpenTelemetrySdkComponentLoader openTelemetrySdkComponentLoader(
ApplicationContext applicationContext) {
return new OpenTelemetrySdkComponentLoader(applicationContext);
@Configuration
@EnableConfigurationProperties({
OtlpExporterProperties.class,
OtelResourceProperties.class,
OtelSpringProperties.class
})
@Conditional(DeclarativeConfigDisabled.class)
static class PropertiesConfig {
@Bean
public ResourceProvider otelSpringResourceProvider(
Optional<BuildProperties> buildProperties) {
return new SpringResourceProvider(buildProperties);
}
@Bean
public ResourceProvider otelDistroVersionResourceProvider() {
return new DistroVersionResourceProvider();
}
@Bean
@ConfigurationPropertiesBinding
OtelMapConverter otelMapConverter() {
return new OtelMapConverter();
}
@Bean
public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk(
Environment env,
OtlpExporterProperties otlpExporterProperties,
OtelResourceProperties resourceProperties,
OtelSpringProperties otelSpringProperties,
ApplicationContext applicationContext) {
return AutoConfigureUtil.setConfigPropertiesCustomizer(
AutoConfiguredOpenTelemetrySdk.builder()
.setComponentLoader(new OpenTelemetrySdkComponentLoader(applicationContext)),
c ->
SpringConfigProperties.create(
env, otlpExporterProperties, resourceProperties, otelSpringProperties, c))
.build();
}
@Bean
public OpenTelemetry openTelemetry(
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
logStart();
return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
}
@Bean
public InstrumentationConfig instrumentationConfig(ConfigProperties properties) {
return new ConfigPropertiesBridge(properties);
}
/**
* Expose the {@link ConfigProperties} bean for use in other auto-configurations.
*
* <p>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);
}
}
@Bean
public ResourceProvider otelSpringResourceProvider(Optional<BuildProperties> buildProperties) {
return new SpringResourceProvider(buildProperties);
}
@Configuration
@Conditional(DeclarativeConfigEnabled.class)
static class EmbeddedConfigFileConfig {
@Bean
public ResourceProvider otelDistroVersionResourceProvider() {
return new DistroVersionResourceProvider();
}
@Bean
public OpenTelemetryConfigurationModel openTelemetryConfigurationModel(
ConfigurableEnvironment environment) throws IOException {
return EmbeddedConfigFile.extractModel(environment);
}
@Bean
public AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk(
Environment env,
OtlpExporterProperties otlpExporterProperties,
OtelResourceProperties resourceProperties,
OtelSpringProperties otelSpringProperties,
OpenTelemetrySdkComponentLoader componentLoader) {
@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;
}
return AutoConfigureUtil.setConfigPropertiesCustomizer(
AutoConfiguredOpenTelemetrySdk.builder().setComponentLoader(componentLoader),
c ->
SpringConfigProperties.create(
env, otlpExporterProperties, resourceProperties, otelSpringProperties, c))
.build();
}
@Bean
public InstrumentationConfig instrumentationConfig(
ConfigProperties properties, ConfigProvider configProvider) {
return new ConfigPropertiesBridge(properties, configProvider);
}
@Bean
public OpenTelemetry openTelemetry(
AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) {
logger.info(
"OpenTelemetry Spring Boot starter ({}) has been started",
EmbeddedInstrumentationProperties.findVersion(
"io.opentelemetry.spring-boot-autoconfigure"));
@Bean
public ConfigProvider configProvider(OpenTelemetryConfigurationModel model) {
return SdkConfigProvider.create(model);
}
return autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk();
}
/**
* Expose the {@link ConfigProperties} bean for use in other auto-configurations.
*
* <p>Not using spring boot properties directly, because declarative configuration does not
* integrate with spring boot properties.
*/
@Bean
public ConfigProperties otelProperties(ConfigProvider configProvider) {
return new DeclarativeConfigPropertiesBridgeBuilder()
.buildFromInstrumentationConfig(configProvider.getInstrumentationConfig());
}
/**
* Expose the {@link ConfigProperties} bean for use in other auto-configurations.
*
* <p>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);
@Bean
public DeclarativeConfigurationCustomizerProvider distroConfigurationCustomizerProvider() {
return new ResourceCustomizerProvider();
}
@Bean
public ComponentProvider<Resource> distroComponentProvider() {
return new DistroComponentProvider();
}
}
}
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")
@Conditional(OtelDisabled.class)
static class DisabledOpenTelemetrySdkConfig {
@Bean
public OpenTelemetry openTelemetry() {
logger.info("OpenTelemetry Spring Boot starter has been disabled");
@ -157,6 +229,26 @@ public class OpenTelemetryAutoConfiguration {
public ConfigProperties otelProperties() {
return DefaultConfigProperties.createFromMap(Collections.emptyMap());
}
@Bean
public InstrumentationConfig instrumentationConfig(ConfigProperties properties) {
return new ConfigPropertiesBridge(properties, null);
}
@Configuration
@Conditional(DeclarativeConfigDisabled.class)
static class PropertiesConfig {
/**
* Is only added so that we have the same converters as with active OpenTelemetry SDK
*
* <p>In other words, don't break applications that (accidentally) use the {@link
* OtelMapConverter}.
*/
@Bean
OtelMapConverter otelMapConverter() {
return new OtelMapConverter();
}
}
}
@Configuration
@ -170,6 +262,16 @@ public class OpenTelemetryAutoConfiguration {
}
}
@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.
* <a

View File

@ -20,7 +20,7 @@ import org.springframework.context.annotation.Conditional;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ConditionalOnBean(OpenTelemetry.class)
@Conditional({SdkEnabled.class, InstrumentationPropertyEnabled.class})
@Conditional({OtelEnabled.class, InstrumentationPropertyEnabled.class})
public @interface ConditionalOnEnabledInstrumentation {
String module();

View File

@ -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 DeclarativeConfigDisabled implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return !EarlyConfig.isDeclarativeConfig(context.getEnvironment());
}
}

View File

@ -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 DeclarativeConfigEnabled implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return EarlyConfig.isDeclarativeConfig(context.getEnvironment());
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
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;
/**
* 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<String, String> 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);
}
public static boolean isDeclarativeConfig(Environment environment) {
return environment.getProperty("otel.file_format", String.class) != null;
}
public static boolean isDefaultEnabled(Environment environment) {
if (isDeclarativeConfig(environment)) {
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);
}
}
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 {
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(
translatePropertyName(environment, "otel.instrumentation.%s.enabled", name),
Boolean.class);
if (explicit != null) {
return explicit;
}
if (!defaultValue) {
return false;
}
return isDefaultEnabled(environment);
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.internal;
import java.util.Map;
import java.util.Objects;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
@ -19,19 +20,12 @@ public class InstrumentationPropertyEnabled implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes =
metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName());
Objects.requireNonNull(
metadata.getAnnotationAttributes(ConditionalOnEnabledInstrumentation.class.getName()));
String name = String.format("otel.instrumentation.%s.enabled", attributes.get("module"));
Boolean explicit = context.getEnvironment().getProperty(name, Boolean.class);
if (explicit != null) {
return explicit;
}
boolean defaultValue = (boolean) attributes.get("enabledByDefault");
if (!defaultValue) {
return false;
}
return context
.getEnvironment()
.getProperty("otel.instrumentation.common.default-enabled", Boolean.class, true);
return EarlyConfig.isInstrumentationEnabled(
context.getEnvironment(),
attributes.get("module").toString(),
(boolean) attributes.get("enabledByDefault"));
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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 {}
}

View File

@ -7,9 +7,9 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
@ -28,13 +28,13 @@ final class DataSourcePostProcessor implements BeanPostProcessor, Ordered {
private static final Class<?> ROUTING_DATA_SOURCE_CLASS = getRoutingDataSourceClass();
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
private final ObjectProvider<InstrumentationConfig> configProvider;
DataSourcePostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
this.openTelemetryProvider = openTelemetryProvider;
this.configPropertiesProvider = configPropertiesProvider;
this.configProvider = configProvider;
}
private static Class<?> getRoutingDataSourceClass() {
@ -57,22 +57,18 @@ final class DataSourcePostProcessor implements BeanPostProcessor, Ordered {
&& !isRoutingDatasource(bean)
&& !ScopedProxyUtils.isScopedTarget(beanName)) {
DataSource dataSource = (DataSource) bean;
InstrumentationConfig config = configProvider.getObject();
DataSource otelDataSource =
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))
config.getBoolean(
"otel.instrumentation.jdbc.experimental.capture-query-parameters", false))
.setTransactionInstrumenterEnabled(
configPropertiesProvider
.getObject()
.getBoolean(
"otel.instrumentation.jdbc.experimental.transaction.enabled", false))
config.getBoolean(
"otel.instrumentation.jdbc.experimental.transaction.enabled", false))
.build()
.wrap(dataSource);

View File

@ -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 class JdbcInstrumentationAutoConfiguration {
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
static DataSourcePostProcessor dataSourcePostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
return new DataSourcePostProcessor(openTelemetryProvider, configPropertiesProvider);
ObjectProvider<InstrumentationConfig> configProvider) {
return new DataSourcePostProcessor(openTelemetryProvider, configProvider);
}
}

View File

@ -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 @@ public class KafkaInstrumentationAutoConfiguration {
@Bean
static SpringKafkaTelemetry getTelemetry(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
return SpringKafkaTelemetry.builder(openTelemetryProvider.getObject())
.setCaptureExperimentalSpanAttributes(
configPropertiesProvider
configProvider
.getObject()
.getBoolean("otel.instrumentation.kafka.experimental-span-attributes", false))
.build();
@ -60,8 +60,8 @@ public class KafkaInstrumentationAutoConfiguration {
static ConcurrentKafkaListenerContainerFactoryPostProcessor
otelKafkaListenerContainerFactoryBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
return new ConcurrentKafkaListenerContainerFactoryPostProcessor(
() -> getTelemetry(openTelemetryProvider, configPropertiesProvider));
() -> getTelemetry(openTelemetryProvider, configProvider));
}
}

View File

@ -9,12 +9,14 @@ import ch.qos.logback.classic.LoggerContext;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.core.env.ConfigurableEnvironment;
class LogbackAppenderInstaller {
@ -40,25 +42,18 @@ class LogbackAppenderInstaller {
}
}
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 otelSdkDisabled =
evaluateBooleanProperty(applicationEnvironmentPreparedEvent, "otel.sdk.disabled", false);
boolean logbackInstrumentationEnabled =
evaluateBooleanProperty(applicationEnvironmentPreparedEvent, property, true);
return !otelSdkDisabled && 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(
@ -224,18 +219,9 @@ class LogbackAppenderInstaller {
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, null), Boolean.class);
}
private static <T> Optional<T> findAppender(Class<T> appenderClass) {

View File

@ -7,10 +7,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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)

View File

@ -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 class R2dbcInstrumentationAutoConfiguration {
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
static R2dbcInstrumentingPostProcessor r2dbcInstrumentingPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
return new R2dbcInstrumentingPostProcessor(openTelemetryProvider, configPropertiesProvider);
ObjectProvider<InstrumentationConfig> configProvider) {
return new R2dbcInstrumentingPostProcessor(openTelemetryProvider, configProvider);
}
}

View File

@ -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 @@ import org.springframework.boot.r2dbc.OptionsCapableConnectionFactory;
class R2dbcInstrumentingPostProcessor implements BeanPostProcessor {
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
private final ObjectProvider<InstrumentationConfig> configProvider;
R2dbcInstrumentingPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
this.openTelemetryProvider = openTelemetryProvider;
this.configPropertiesProvider = configPropertiesProvider;
this.configProvider = configProvider;
}
@Override
@ -35,7 +35,7 @@ class R2dbcInstrumentingPostProcessor implements BeanPostProcessor {
return R2dbcTelemetry.builder(openTelemetryProvider.getObject())
.setStatementSanitizationEnabled(
InstrumentationConfigUtil.isStatementSanitizationEnabled(
configPropertiesProvider.getObject(),
configProvider.getObject(),
"otel.instrumentation.r2dbc.statement-sanitizer.enabled"))
.build()
.wrapConnectionFactory(connectionFactory, getConnectionFactoryOptions(connectionFactory));

View File

@ -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 class RuntimeMetricsAutoConfiguration {
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")));

View File

@ -9,6 +9,7 @@ import io.opentelemetry.api.OpenTelemetry;
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.incubator.semconv.util.ClassAndMetho
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<ClassAndMethod, Object> instrumenter;
public SpringSchedulingInstrumentationAspect(
OpenTelemetry openTelemetry, ConfigProperties configProperties) {
OpenTelemetry openTelemetry, InstrumentationConfig config) {
CodeAttributesGetter<ClassAndMethod> codedAttributesGetter =
ClassAndMethod.codeAttributesGetter();
InstrumenterBuilder<ClassAndMethod, Object> builder =
@ -52,7 +52,7 @@ final class 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"));

View File

@ -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 @@ import org.springframework.scheduling.annotation.Scheduled;
class SpringSchedulingInstrumentationAutoConfiguration {
@Bean
SpringSchedulingInstrumentationAspect springSchedulingInstrumentationAspect(
OpenTelemetry openTelemetry, ConfigProperties configProperties) {
return new SpringSchedulingInstrumentationAspect(openTelemetry, configProperties);
OpenTelemetry openTelemetry, InstrumentationConfig config) {
return new SpringSchedulingInstrumentationAspect(openTelemetry, config);
}
}

View File

@ -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<OpenTelemetry> openTelemetryProvider;
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
private final ObjectProvider<InstrumentationConfig> configProvider;
RestTemplateBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
this.openTelemetryProvider = openTelemetryProvider;
this.configPropertiesProvider = configPropertiesProvider;
this.configProvider = configProvider;
}
@Override
@ -31,8 +31,6 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
}
return RestTemplateInstrumentation.addIfNotPresent(
(RestTemplate) bean,
openTelemetryProvider.getObject(),
configPropertiesProvider.getObject());
(RestTemplate) bean, openTelemetryProvider.getObject(), configProvider.getObject());
}
}

View File

@ -7,10 +7,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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 @@ class RestTemplateInstrumentation {
@CanIgnoreReturnValue
static RestTemplate addIfNotPresent(
RestTemplate restTemplate, OpenTelemetry openTelemetry, ConfigProperties config) {
RestTemplate restTemplate, OpenTelemetry openTelemetry, InstrumentationConfig config) {
ClientHttpRequestInterceptor instrumentationInterceptor =
InstrumentationConfigUtil.configureClientBuilder(

View File

@ -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 class SpringWebInstrumentationAutoConfiguration {
@Bean
static RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
return new RestTemplateBeanPostProcessor(openTelemetryProvider, configPropertiesProvider);
ObjectProvider<InstrumentationConfig> configProvider) {
return new RestTemplateBeanPostProcessor(openTelemetryProvider, configProvider);
}
@Bean
RestTemplateCustomizer otelRestTemplateCustomizer(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
return restTemplate ->
RestTemplateInstrumentation.addIfNotPresent(
restTemplate, openTelemetryProvider.getObject(), configPropertiesProvider.getObject());
restTemplate, openTelemetryProvider.getObject(), configProvider.getObject());
}
}

View File

@ -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 class SpringWebfluxInstrumentationAutoConfiguration {
@Bean
static WebClientBeanPostProcessor otelWebClientBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
return new WebClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider);
ObjectProvider<InstrumentationConfig> 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();
}

View File

@ -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 @@ import org.springframework.web.reactive.function.client.WebClient;
final class WebClientBeanPostProcessor implements BeanPostProcessor {
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
private final ObjectProvider<InstrumentationConfig> configProvider;
WebClientBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> 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 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor {
}
static SpringWebfluxServerTelemetry getWebfluxServerTelemetry(
OpenTelemetry openTelemetry, ConfigProperties config) {
OpenTelemetry openTelemetry, InstrumentationConfig config) {
return InstrumentationConfigUtil.configureServerBuilder(
config,
SpringWebfluxServerTelemetry.builder(openTelemetry),
@ -64,8 +64,7 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor {
private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) {
SpringWebfluxClientTelemetry instrumentation =
getWebfluxClientTelemetry(
openTelemetryProvider.getObject(), configPropertiesProvider.getObject());
getWebfluxClientTelemetry(openTelemetryProvider.getObject(), configProvider.getObject());
return webClientBuilder.filters(instrumentation::addFilter);
}
}

View File

@ -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 @@ import org.springframework.web.servlet.DispatcherServlet;
public class SpringWebMvc5InstrumentationAutoConfiguration {
@Bean
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) {
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, InstrumentationConfig config) {
return InstrumentationConfigUtil.configureServerBuilder(
config,
SpringWebMvcTelemetry.builder(openTelemetry),

View File

@ -5,8 +5,11 @@
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;
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 +27,16 @@ import javax.annotation.Nullable;
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
@ -113,19 +123,25 @@ public final class ConfigPropertiesBridge implements InstrumentationConfig {
@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 ConfigProvider getConfigProvider() {
// declarative config support will be added in the future
return null;
return configProvider;
}
}

View File

@ -9,7 +9,7 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
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 @@ public final class InstrumentationConfigUtil {
@CanIgnoreReturnValue
public static <T, REQUEST, RESPONSE> T configureClientBuilder(
ConfigProperties config,
InstrumentationConfig config,
T builder,
Function<T, DefaultHttpClientInstrumenterBuilder<REQUEST, RESPONSE>> getBuilder) {
getBuilder.apply(builder).configure(getConfig(config));
@ -30,18 +30,18 @@ public final class InstrumentationConfigUtil {
@CanIgnoreReturnValue
public static <T, REQUEST, RESPONSE> T configureServerBuilder(
ConfigProperties config,
InstrumentationConfig config,
T builder,
Function<T, DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE>> 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));
}

View File

@ -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<Resource> {
@Override
public Class<Resource> getType() {
return Resource.class;
}
@Override
public String getName() {
return "opentelemetry-spring-boot-starter";
}
@Override
public Resource create(DeclarativeConfigProperties config) {
return DistroVersionResourceProvider.get();
}
}

View File

@ -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,

View File

@ -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<String> 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<ExperimentalResourceDetectorModel> detectors =
Objects.requireNonNull(detectionModel.getDetectors());
Set<String> 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;
});
}
}

View File

@ -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 @@ import org.springframework.web.client.RestClient;
final class RestClientBeanPostProcessor implements BeanPostProcessor {
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
private final ObjectProvider<InstrumentationConfig> configProvider;
public RestClientBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> 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 @@ final class RestClientBeanPostProcessor implements BeanPostProcessor {
}
static ClientHttpRequestInterceptor getInterceptor(
OpenTelemetry openTelemetry, ConfigProperties config) {
OpenTelemetry openTelemetry, InstrumentationConfig config) {
return InstrumentationConfigUtil.configureClientBuilder(
config,
SpringWebTelemetry.builder(openTelemetry),

View File

@ -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.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -34,17 +34,17 @@ public class RestClientInstrumentationAutoConfiguration {
@Bean
static RestClientBeanPostProcessor otelRestClientBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
return new RestClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider);
ObjectProvider<InstrumentationConfig> configProvider) {
return new RestClientBeanPostProcessor(openTelemetryProvider, configProvider);
}
@Bean
RestClientCustomizer otelRestClientCustomizer(
ObjectProvider<OpenTelemetry> openTelemetryProvider,
ObjectProvider<ConfigProperties> configPropertiesProvider) {
ObjectProvider<InstrumentationConfig> configProvider) {
return builder ->
builder.requestInterceptor(
RestClientBeanPostProcessor.getInterceptor(
openTelemetryProvider.getObject(), configPropertiesProvider.getObject()));
openTelemetryProvider.getObject(), configProvider.getObject()));
}
}

View File

@ -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.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 +28,7 @@ import org.springframework.web.servlet.DispatcherServlet;
public class SpringWebMvc6InstrumentationAutoConfiguration {
@Bean
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) {
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, InstrumentationConfig config) {
return InstrumentationConfigUtil.configureServerBuilder(
config,
SpringWebMvcTelemetry.builder(openTelemetry),

View File

@ -26,7 +26,7 @@ import org.springframework.context.annotation.Bean;
/** 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 @@ class OpenTelemetryAutoConfigurationTest {
"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 ->
@ -152,10 +152,8 @@ class OpenTelemetryAutoConfigurationTest {
.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

View File

@ -10,8 +10,9 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STAT
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))

View File

@ -9,8 +9,9 @@ import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStability
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))

View File

@ -13,9 +13,10 @@ import io.opentelemetry.api.trace.Span;
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.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;
@ -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
@ -56,7 +57,8 @@ class SchedulingInstrumentationAspectTest {
SpringSchedulingInstrumentationAspect aspect =
newAspect(
testing.getOpenTelemetry(),
DefaultConfigProperties.createFromMap(Collections.emptyMap()));
new ConfigPropertiesBridge(
DefaultConfigProperties.createFromMap(Collections.emptyMap())));
factory.addAspect(aspect);
schedulingTester = factory.getProxy();

View File

@ -8,7 +8,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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));

View File

@ -8,7 +8,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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));

View File

@ -8,7 +8,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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));

View File

@ -8,7 +8,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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.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
@ -34,7 +36,7 @@ class WebClientBeanPostProcessorTest {
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 +48,7 @@ class WebClientBeanPostProcessorTest {
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 +60,7 @@ class WebClientBeanPostProcessorTest {
BeanPostProcessor underTest =
new WebClientBeanPostProcessor(
beanFactory.getBeanProvider(OpenTelemetry.class),
beanFactory.getBeanProvider(ConfigProperties.class));
beanFactory.getBeanProvider(InstrumentationConfig.class));
assertThat(
underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder"))
@ -71,7 +73,7 @@ class WebClientBeanPostProcessorTest {
BeanPostProcessor underTest =
new WebClientBeanPostProcessor(
beanFactory.getBeanProvider(OpenTelemetry.class),
beanFactory.getBeanProvider(ConfigProperties.class));
beanFactory.getBeanProvider(InstrumentationConfig.class));
WebClient webClient = WebClient.create();
Object processedWebClient =
@ -96,7 +98,7 @@ class WebClientBeanPostProcessorTest {
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");

View File

@ -9,7 +9,8 @@ import static org.assertj.core.api.Assertions.assertThat;
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));

View File

@ -86,9 +86,9 @@ class SpringConfigPropertiesTest {
.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

View File

@ -0,0 +1,123 @@
/*
* 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 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;
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 DeclarativeConfigTest {
@TestConfiguration
static class CustomTracerConfiguration {
@Bean
public OpenTelemetry customOpenTelemetry() {
return OpenTelemetry.noop();
}
}
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(OpenTelemetryAutoConfiguration.class))
// to load application.yaml
.withInitializer(new ConfigDataApplicationContextInitializer());
@Test
@DisplayName(
"when Application Context contains OpenTelemetry bean should NOT initialize openTelemetry")
void customOpenTelemetry() {
this.contextRunner
.withUserConfiguration(CustomTracerConfiguration.class)
.withPropertyValues("otel.file_format=1.0-rc.1")
.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.run(
context ->
assertThat(context)
.hasBean("openTelemetry")
.hasBean("otelProperties")
.getBean(InstrumentationConfig.class)
.isNotNull()
.satisfies(
c ->
assertThat(c.getDeclarativeConfig("foo"))
.isNotNull()
.satisfies(
instrumentationConfig ->
assertThat(instrumentationConfig.getString("bar"))
.isEqualTo("baz"))));
}
@Test
void shouldInitializeSdkWhenNotDisabled() {
this.contextRunner
.withPropertyValues("otel.file_format=1.0-rc.1", "otel.disabled=false")
.run(
context ->
assertThat(context).getBean("openTelemetry").isInstanceOf(OpenTelemetrySdk.class));
}
@Test
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"));
}
}

View File

@ -0,0 +1,10 @@
otel:
# "file_format" serves as opt-in to the new file format
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
instrumentation/development:
java:
foo:
bar: baz

View File

@ -8,7 +8,8 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumen
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));

View File

@ -9,7 +9,8 @@ import static org.assertj.core.api.Assertions.assertThat;
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));

View File

@ -30,3 +30,22 @@ configurations.configureEach {
force("org.slf4j:slf4j-api:1.7.36")
}
}
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-web:2.6.15")
implementation("org.springframework.boot:spring-boot-starter-test:2.6.15")
}
}
}
}
tasks {
check {
dependsOn(testing.suites)
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
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;
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;
@SpringBootTest(
classes = {
OtelSpringStarterSmokeTestApplication.class,
AbstractOtelSpringStarterSmokeTest.TestConfiguration.class,
SpringSmokeOtelConfiguration.class
},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
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")
.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)
.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));
}
}

View File

@ -0,0 +1,47 @@
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
tracer_provider:
processors:
- simple:
exporter:
test:
- simple:
exporter:
console:
logger_provider:
processors:
- simple:
exporter:
test:
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:
propagator:
composite:
- tracecontext:
- baggage:
instrumentation/development:
java:
runtime-telemetry:
emit_experimental_telemetry: true
http:
client:
emit_experimental_telemetry: true

View File

@ -7,6 +7,9 @@ package io.opentelemetry.spring.smoketest;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
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;
@ -36,6 +39,11 @@ public final class SpringSmokeTestRunner extends InstrumentationTestRunner {
testSpanExporter = InMemorySpanExporter.create();
testMetricExporter = InMemoryMetricExporter.create(AggregationTemporality.DELTA);
testLogRecordExporter = InMemoryLogRecordExporter.create();
// for declarative config
TestLogRecordExporterComponentProvider.setLogRecordExporter(testLogRecordExporter);
TestMetricExporterComponentProvider.setMetricExporter(testMetricExporter);
TestSpanExporterComponentProvider.setSpanExporter(testSpanExporter);
}
@Override