Refactor Spring starter's instrumentation auto configuration classes (#8950)

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Mateusz Rzeszutek 2023-07-21 13:35:41 +02:00 committed by GitHub
parent d17876eab9
commit fd8e361e6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 544 additions and 835 deletions

View File

@ -24,7 +24,7 @@ import net.bytebuddy.matcher.ElementMatcher;
public class AnnotationInstrumentationModule extends InstrumentationModule { public class AnnotationInstrumentationModule extends InstrumentationModule {
public AnnotationInstrumentationModule() { public AnnotationInstrumentationModule() {
super("opentelemetry-instrumentation-annotations"); super("opentelemetry-instrumentation-annotations", "annotations");
} }
@Override @Override

View File

@ -398,16 +398,16 @@ If an exporter is present in the classpath during runtime and a spring bean of t
##### Enabling/Disabling Features ##### Enabling/Disabling Features
| Feature | Property | Default Value | ConditionalOnClass | | Feature | Property | Default Value | ConditionalOnClass |
| ---------------- | ----------------------------------- | ------------- | ---------------------- | |------------------|---------------------------------------------|---------------|------------------------|
| spring-web | otel.springboot.httpclients.enabled | `true` | RestTemplate | | spring-web | otel.instrumentation.spring-webmvc.enabled | `true` | RestTemplate |
| spring-webmvc | otel.springboot.httpclients.enabled | `true` | OncePerRequestFilter | | spring-webmvc | otel.instrumentation.spring-web.enabled | `true` | OncePerRequestFilter |
| spring-webflux | otel.springboot.httpclients.enabled | `true` | WebClient | | spring-webflux | otel.instrumentation.spring-webflux.enabled | `true` | WebClient |
| @WithSpan | otel.springboot.aspects.enabled | `true` | WithSpan, Aspect | | @WithSpan | otel.instrumentation.annotations.enabled | `true` | WithSpan, Aspect |
| Otlp Exporter | otel.exporter.otlp.enabled | `true` | OtlpGrpcSpanExporter | | Otlp Exporter | otel.exporter.otlp.enabled | `true` | OtlpGrpcSpanExporter |
| Jaeger Exporter | otel.exporter.jaeger.enabled | `true` | JaegerGrpcSpanExporter | | Jaeger Exporter | otel.exporter.jaeger.enabled | `true` | JaegerGrpcSpanExporter |
| Zipkin Exporter | otel.exporter.zipkin.enabled | `true` | ZipkinSpanExporter | | Zipkin Exporter | otel.exporter.zipkin.enabled | `true` | ZipkinSpanExporter |
| Logging Exporter | otel.exporter.logging.enabled | `true` | LoggingSpanExporter | | Logging Exporter | otel.exporter.logging.enabled | `true` | LoggingSpanExporter |
<!-- Slf4j Log Correlation otel.springboot.loggers.slf4j.enabled true org.slf4j.MDC --> <!-- Slf4j Log Correlation otel.springboot.loggers.slf4j.enabled true org.slf4j.MDC -->

View File

@ -1,22 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects;
import org.springframework.boot.context.properties.ConfigurationProperties;
/** Configuration for enabling tracing aspects. */
@ConfigurationProperties(prefix = "otel.springboot.aspects")
public final class TraceAspectProperties {
private boolean enabled;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration for the tracing instrumentation of HTTP clients.
*
* <p>Sets default value of otel.springboot.httpclients.enabled to true if the configuration does
* not exist in application context.
*/
@ConfigurationProperties(prefix = "otel.springboot.httpclients")
public final class HttpClientsProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.HttpClientsProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* Configures {@link RestTemplate} for tracing.
*
* <p>Adds Open Telemetry instrumentation to RestTemplate beans after initialization
*/
@Configuration
@ConditionalOnClass(RestTemplate.class)
@EnableConfigurationProperties(HttpClientsProperties.class)
@ConditionalOnProperty(
prefix = "otel.springboot.httpclients",
name = "enabled",
matchIfMissing = true)
public class RestTemplateAutoConfiguration {
@Bean
public RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider) {
return new RestTemplateBeanPostProcessor(openTelemetryProvider);
}
}

View File

@ -1,37 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.HttpClientsProperties;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Configures {@link WebClient} for tracing.
*
* <p>Adds Open Telemetry instrumentation to WebClient beans after initialization
*/
@Configuration
@ConditionalOnClass(WebClient.class)
@EnableConfigurationProperties(HttpClientsProperties.class)
@ConditionalOnProperty(
prefix = "otel.springboot.httpclients",
name = "enabled",
matchIfMissing = true)
public class WebClientAutoConfiguration {
@Bean
public WebClientBeanPostProcessor otelWebClientBeanPostProcessor(
ObjectProvider<OpenTelemetry> openTelemetryProvider) {
return new WebClientBeanPostProcessor(openTelemetryProvider);
}
}

View File

@ -3,36 +3,36 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.annotations.WithSpan; import io.opentelemetry.instrumentation.annotations.WithSpan;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer;
/** Configures {@link WithSpanAspect} to trace bean methods annotated with {@link WithSpan}. */ /** Configures {@link WithSpanAspect} to trace bean methods annotated with {@link WithSpan}. */
@Configuration @ConditionalOnBean(OpenTelemetry.class)
@EnableConfigurationProperties(TraceAspectProperties.class)
@ConditionalOnProperty(prefix = "otel.springboot.aspects", name = "enabled", matchIfMissing = true)
@ConditionalOnClass(Aspect.class) @ConditionalOnClass(Aspect.class)
public class TraceAspectAutoConfiguration { @ConditionalOnProperty(name = "otel.instrumentation.annotations.enabled", matchIfMissing = true)
@Configuration
public class InstrumentationAnnotationsAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public ParameterNameDiscoverer parameterNameDiscoverer() { ParameterNameDiscoverer parameterNameDiscoverer() {
return new DefaultParameterNameDiscoverer(); return new DefaultParameterNameDiscoverer();
} }
@Bean @Bean
@ConditionalOnClass(WithSpan.class) @ConditionalOnClass(WithSpan.class)
public InstrumentationWithSpanAspect instrumentationWithSpanAspect( InstrumentationWithSpanAspect otelInstrumentationWithSpanAspect(
OpenTelemetry openTelemetry, ParameterNameDiscoverer parameterNameDiscoverer) { OpenTelemetry openTelemetry, ParameterNameDiscoverer parameterNameDiscoverer) {
return new InstrumentationWithSpanAspect(openTelemetry, parameterNameDiscoverer); return new InstrumentationWithSpanAspect(openTelemetry, parameterNameDiscoverer);
} }
@ -40,7 +40,7 @@ public class TraceAspectAutoConfiguration {
@Bean @Bean
@SuppressWarnings("deprecation") // instrumenting deprecated class for backwards compatibility @SuppressWarnings("deprecation") // instrumenting deprecated class for backwards compatibility
@ConditionalOnClass(io.opentelemetry.extension.annotations.WithSpan.class) @ConditionalOnClass(io.opentelemetry.extension.annotations.WithSpan.class)
public SdkExtensionWithSpanAspect sdkExtensionWithSpanAspect( SdkExtensionWithSpanAspect otelSdkExtensionWithSpanAspect(
OpenTelemetry openTelemetry, ParameterNameDiscoverer parameterNameDiscoverer) { OpenTelemetry openTelemetry, ParameterNameDiscoverer parameterNameDiscoverer) {
return new SdkExtensionWithSpanAspect(openTelemetry, parameterNameDiscoverer); return new SdkExtensionWithSpanAspect(openTelemetry, parameterNameDiscoverer);
} }

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.annotations.WithSpan; import io.opentelemetry.instrumentation.annotations.WithSpan;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesGetter; import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesGetter;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.Span;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import io.opentelemetry.instrumentation.annotations.SpanAttribute; import io.opentelemetry.instrumentation.annotations.SpanAttribute;
import io.opentelemetry.instrumentation.api.annotation.support.ParameterAttributeNamesExtractor; import io.opentelemetry.instrumentation.api.annotation.support.ParameterAttributeNamesExtractor;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.kafka; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry; import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry;

View File

@ -3,35 +3,35 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.kafka; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry; import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.kafka.DefaultKafkaProducerFactoryCustomizer; import org.springframework.boot.autoconfigure.kafka.DefaultKafkaProducerFactoryCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.KafkaTemplate; import org.springframework.kafka.core.KafkaTemplate;
@Configuration @ConditionalOnBean(OpenTelemetry.class)
@EnableConfigurationProperties(KafkaInstrumentationProperties.class)
@ConditionalOnProperty(name = "otel.springboot.kafka.enabled", matchIfMissing = true)
@ConditionalOnClass({KafkaTemplate.class, ConcurrentKafkaListenerContainerFactory.class}) @ConditionalOnClass({KafkaTemplate.class, ConcurrentKafkaListenerContainerFactory.class})
@ConditionalOnProperty(name = "otel.instrumentation.kafka.enabled", matchIfMissing = true)
@Configuration
public class KafkaInstrumentationAutoConfiguration { public class KafkaInstrumentationAutoConfiguration {
@Bean @Bean
public DefaultKafkaProducerFactoryCustomizer producerInstrumentation( DefaultKafkaProducerFactoryCustomizer otelKafkaProducerFactoryCustomizer(
OpenTelemetry openTelemetry) { OpenTelemetry openTelemetry) {
KafkaTelemetry kafkaTelemetry = KafkaTelemetry.create(openTelemetry); KafkaTelemetry kafkaTelemetry = KafkaTelemetry.create(openTelemetry);
return producerFactory -> producerFactory.addPostProcessor(kafkaTelemetry::wrap); return producerFactory -> producerFactory.addPostProcessor(kafkaTelemetry::wrap);
} }
@Bean @Bean
public ConcurrentKafkaListenerContainerFactoryPostProcessor ConcurrentKafkaListenerContainerFactoryPostProcessor
concurrentKafkaListenerContainerFactoryPostProcessor(OpenTelemetry openTelemetry) { otelKafkaListenerContainerFactoryBeanPostProcessor(OpenTelemetry openTelemetry) {
return new ConcurrentKafkaListenerContainerFactoryPostProcessor(openTelemetry); return new ConcurrentKafkaListenerContainerFactoryPostProcessor(openTelemetry);
} }
} }

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.logging; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@ -14,19 +14,16 @@ import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ConditionalOnBean(OpenTelemetry.class)
@Configuration @Configuration
@SuppressWarnings("OtelPrivateConstructorForUtilityClass") @SuppressWarnings("OtelPrivateConstructorForUtilityClass")
@ConditionalOnBean(OpenTelemetry.class)
public class OpenTelemetryAppenderAutoConfiguration { public class OpenTelemetryAppenderAutoConfiguration {
@Configuration @ConditionalOnClass(org.apache.logging.log4j.core.LoggerContext.class)
@ConditionalOnProperty( @ConditionalOnProperty(
prefix = "otel.springboot.log4j-appender", name = "otel.instrumentation.log4j-appender.enabled",
name = "enabled",
matchIfMissing = true) matchIfMissing = true)
@ConditionalOnClass({ @Configuration
io.opentelemetry.instrumentation.log4j.appender.v2_17.OpenTelemetryAppender.class
})
static class Log4jAppenderConfig { static class Log4jAppenderConfig {
@Bean @Bean
@ -39,14 +36,11 @@ public class OpenTelemetryAppenderAutoConfiguration {
} }
} }
@Configuration @ConditionalOnClass(ch.qos.logback.classic.LoggerContext.class)
@ConditionalOnProperty( @ConditionalOnProperty(
prefix = "otel.springboot.logback-appender", name = "otel.instrumentation.logback-appender.enabled",
name = "enabled",
matchIfMissing = true) matchIfMissing = true)
@ConditionalOnClass({ @Configuration
io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender.class
})
static class LogbackAppenderConfig { static class LogbackAppenderConfig {
@Bean @Bean

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.metrics; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer;
import io.micrometer.core.instrument.Clock; import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
@ -16,21 +16,19 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(MicrometerShimProperties.class)
@ConditionalOnProperty(name = "otel.springboot.micrometer.enabled", matchIfMissing = true)
@AutoConfigureAfter(MetricsAutoConfiguration.class) @AutoConfigureAfter(MetricsAutoConfiguration.class)
@AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class) @AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class)
@ConditionalOnBean(Clock.class) @ConditionalOnBean({Clock.class, OpenTelemetry.class})
@ConditionalOnClass(MeterRegistry.class) @ConditionalOnClass(MeterRegistry.class)
public class MicrometerShimAutoConfiguration { @ConditionalOnProperty(name = "otel.instrumentation.micrometer.enabled", matchIfMissing = true)
@Configuration
public class MicrometerBridgeAutoConfiguration {
@Bean @Bean
public MeterRegistry micrometerShim(OpenTelemetry openTelemetry, Clock micrometerClock) { MeterRegistry otelMeterRegistry(OpenTelemetry openTelemetry, Clock micrometerClock) {
return OpenTelemetryMeterRegistry.builder(openTelemetry).setClock(micrometerClock).build(); return OpenTelemetryMeterRegistry.builder(openTelemetry).setClock(micrometerClock).build();
} }
} }

View File

@ -3,21 +3,21 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry; import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
final class RestTemplateBeanPostProcessor implements BeanPostProcessor { final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
RestTemplateBeanPostProcessor(ObjectProvider<OpenTelemetry> openTelemetryProvider) { private final OpenTelemetry openTelemetry;
this.openTelemetryProvider = openTelemetryProvider;
RestTemplateBeanPostProcessor(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
} }
@Override @Override
@ -27,12 +27,9 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
} }
RestTemplate restTemplate = (RestTemplate) bean; RestTemplate restTemplate = (RestTemplate) bean;
OpenTelemetry openTelemetry = openTelemetryProvider.getIfUnique(); ClientHttpRequestInterceptor interceptor =
if (openTelemetry != null) { SpringWebTelemetry.create(openTelemetry).newInterceptor();
ClientHttpRequestInterceptor interceptor = addRestTemplateInterceptorIfNotPresent(restTemplate, interceptor);
SpringWebTelemetry.create(openTelemetry).newInterceptor();
addRestTemplateInterceptorIfNotPresent(restTemplate, interceptor);
}
return restTemplate; return restTemplate;
} }

View File

@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
import io.opentelemetry.api.OpenTelemetry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* Configures {@link RestTemplate} for tracing.
*
* <p>Adds Open Telemetry instrumentation to RestTemplate beans after initialization
*/
@ConditionalOnBean(OpenTelemetry.class)
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnProperty(name = "otel.instrumentation.spring-web.enabled", matchIfMissing = true)
@Configuration
public class SpringWebInstrumentationAutoConfiguration {
@Bean
RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor(OpenTelemetry openTelemetry) {
return new RestTemplateBeanPostProcessor(openTelemetry);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
import io.opentelemetry.api.OpenTelemetry;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Configures {@link WebClient} for tracing.
*
* <p>Adds Open Telemetry instrumentation to WebClient beans after initialization
*/
@ConditionalOnBean(OpenTelemetry.class)
@ConditionalOnClass(WebClient.class)
@ConditionalOnProperty(name = "otel.instrumentation.spring-webflux.enabled", matchIfMissing = true)
@Configuration
public class SpringWebfluxInstrumentationAutoConfiguration {
@Bean
WebClientBeanPostProcessor otelWebClientBeanPostProcessor(OpenTelemetry openTelemetry) {
return new WebClientBeanPostProcessor(openTelemetry);
}
}

View File

@ -3,11 +3,10 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient;
@ -18,33 +17,26 @@ import org.springframework.web.reactive.function.client.WebClient;
*/ */
final class WebClientBeanPostProcessor implements BeanPostProcessor { final class WebClientBeanPostProcessor implements BeanPostProcessor {
private final ObjectProvider<OpenTelemetry> openTelemetryProvider; private final OpenTelemetry openTelemetry;
WebClientBeanPostProcessor(ObjectProvider<OpenTelemetry> openTelemetryProvider) { WebClientBeanPostProcessor(OpenTelemetry openTelemetry) {
this.openTelemetryProvider = openTelemetryProvider; this.openTelemetry = openTelemetry;
} }
@Override @Override
public Object postProcessAfterInitialization(Object bean, String beanName) { public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof WebClient) { if (bean instanceof WebClient) {
WebClient webClient = (WebClient) bean; WebClient webClient = (WebClient) bean;
return wrapBuilder(openTelemetryProvider, webClient.mutate()).build(); return wrapBuilder(webClient.mutate()).build();
} else if (bean instanceof WebClient.Builder) { } else if (bean instanceof WebClient.Builder) {
WebClient.Builder webClientBuilder = (WebClient.Builder) bean; WebClient.Builder webClientBuilder = (WebClient.Builder) bean;
return wrapBuilder(openTelemetryProvider, webClientBuilder); return wrapBuilder(webClientBuilder);
} }
return bean; return bean;
} }
private static WebClient.Builder wrapBuilder( private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) {
ObjectProvider<OpenTelemetry> openTelemetryProvider, WebClient.Builder webClientBuilder) { SpringWebfluxTelemetry instrumentation = SpringWebfluxTelemetry.create(openTelemetry);
return webClientBuilder.filters(instrumentation::addClientTracingFilter);
OpenTelemetry openTelemetry = openTelemetryProvider.getIfUnique();
if (openTelemetry != null) {
SpringWebfluxTelemetry instrumentation = SpringWebfluxTelemetry.create(openTelemetry);
return webClientBuilder.filters(instrumentation::addClientTracingFilter);
} else {
return webClientBuilder;
}
} }
} }

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.webmvc; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetry; import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetry;
@ -11,22 +11,20 @@ import javax.servlet.Filter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
/** Configures {@link SpringWebMvcTelemetry} for tracing. */
@Configuration
@EnableConfigurationProperties(WebMvcProperties.class)
@ConditionalOnProperty(prefix = "otel.springboot.web", name = "enabled", matchIfMissing = true)
@ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class})
@ConditionalOnBean(OpenTelemetry.class) @ConditionalOnBean(OpenTelemetry.class)
public class WebMvcFilterAutoConfiguration { @ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class})
@ConditionalOnProperty(name = "otel.instrumentation.spring-webmvc.enabled", matchIfMissing = true)
@Configuration
@SuppressWarnings("OtelPrivateConstructorForUtilityClass")
public class SpringWebMvc5InstrumentationAutoConfiguration {
@Bean @Bean
public Filter otelWebMvcInstrumentationFilter(OpenTelemetry openTelemetry) { Filter otelWebMvcFilter(OpenTelemetry openTelemetry) {
return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter(); return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter();
} }
} }

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.webmvc; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc;
import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry; import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry;
@ -11,22 +11,20 @@ import jakarta.servlet.Filter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
/** Configures {@link SpringWebMvcTelemetry} for tracing. */
@Configuration
@EnableConfigurationProperties(WebMvcProperties.class)
@ConditionalOnProperty(prefix = "otel.springboot.web", name = "enabled", matchIfMissing = true)
@ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class})
@ConditionalOnBean(OpenTelemetry.class) @ConditionalOnBean(OpenTelemetry.class)
public class WebMvcFilterAutoConfigurationSpring6 { @ConditionalOnClass({Filter.class, OncePerRequestFilter.class, DispatcherServlet.class})
@ConditionalOnProperty(name = "otel.instrumentation.spring-webmvc.enabled", matchIfMissing = true)
@Configuration
@SuppressWarnings("OtelPrivateConstructorForUtilityClass")
public class SpringWebMvc6InstrumentationAutoConfiguration {
@Bean @Bean
public Filter otelWebMvcInstrumentationFilter(OpenTelemetry openTelemetry) { Filter otelWebMvcFilter(OpenTelemetry openTelemetry) {
return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter(); return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter();
} }
} }

View File

@ -1,22 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.kafka;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "otel.springboot.kafka")
public class KafkaInstrumentationProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.metrics;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "otel.springboot.micrometer")
public class MicrometerShimProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.webmvc;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration for the tracing instrumentation of Spring WebMVC
*
* <p>Sets default value of otel.springboot.web.enabled to true if the configuration does not exist
* in application context
*/
@ConfigurationProperties(prefix = "otel.springboot.web")
public final class WebMvcProperties {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View File

@ -1,17 +1,17 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.aspects.TraceAspectAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpanExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate.RestTemplateAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient.WebClientAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka.KafkaInstrumentationAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.kafka.KafkaInstrumentationAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.logging.OpenTelemetryAppenderAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer.MicrometerBridgeAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.metrics.MicrometerShimAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.SpringWebInstrumentationAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration,\
io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.webmvc.WebMvcFilterAutoConfiguration

View File

@ -1,16 +1,16 @@
io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.aspects.TraceAspectAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpanExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.jaeger.JaegerSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.logging.LoggingSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpLoggerExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.exporters.zipkin.ZipkinSpanExporterAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate.RestTemplateAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations.InstrumentationAnnotationsAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient.WebClientAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka.KafkaInstrumentationAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.kafka.KafkaInstrumentationAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging.OpenTelemetryAppenderAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.logging.OpenTelemetryAppenderAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer.MicrometerBridgeAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.metrics.MicrometerShimAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web.SpringWebInstrumentationAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.propagators.PropagationAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration
io.opentelemetry.instrumentation.spring.autoconfigure.webmvc.WebMvcFilterAutoConfigurationSpring6

View File

@ -1,58 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/** Spring Boot auto configuration test for {@link TraceAspectAutoConfiguration}. */
public class TraceAspectAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class, TraceAspectAutoConfiguration.class));
@Test
@DisplayName("when aspects are ENABLED should initialize WithSpanAspect bean")
void aspectsEnabled() {
this.contextRunner
.withPropertyValues("otel.springboot.aspects.enabled=true")
.run(
context ->
assertThat(context)
.hasBean("instrumentationWithSpanAspect")
.hasBean("sdkExtensionWithSpanAspect"));
}
@Test
@DisplayName("when aspects are DISABLED should NOT initialize WithSpanAspect bean")
void disabledProperty() {
this.contextRunner
.withPropertyValues("otel.springboot.aspects.enabled=false")
.run(
context ->
assertThat(context)
.doesNotHaveBean("instrumentationWithSpanAspect")
.doesNotHaveBean("sdkExtensionWithSpanAspect"));
}
@Test
@DisplayName("when aspects enabled property is MISSING should initialize WithSpanAspect bean")
void noProperty() {
this.contextRunner.run(
context ->
assertThat(context)
.hasBean("instrumentationWithSpanAspect")
.hasBean("sdkExtensionWithSpanAspect"));
}
}

View File

@ -1,103 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
@ExtendWith(MockitoExtension.class)
class RestTemplateBeanPostProcessorTest {
@Mock ObjectProvider<OpenTelemetry> openTelemetryProvider;
RestTemplateBeanPostProcessor restTemplateBeanPostProcessor;
@BeforeEach
void setUp() {
restTemplateBeanPostProcessor = new RestTemplateBeanPostProcessor(openTelemetryProvider);
}
@Test
@DisplayName("when processed bean is not of type RestTemplate should return object")
void returnsObject() {
assertThat(
restTemplateBeanPostProcessor.postProcessAfterInitialization(
new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
verifyNoInteractions(openTelemetryProvider);
}
@Test
@DisplayName("when processed bean is of type RestTemplate should return RestTemplate")
void returnsRestTemplate() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
assertThat(
restTemplateBeanPostProcessor.postProcessAfterInitialization(
new RestTemplate(), "testRestTemplate"))
.isInstanceOf(RestTemplate.class);
verify(openTelemetryProvider).getIfUnique();
}
@Test
@DisplayName("when processed bean is of type RestTemplate should add ONE RestTemplateInterceptor")
void addsRestTemplateInterceptor() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
RestTemplate restTemplate = new RestTemplate();
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
assertThat(
restTemplate.getInterceptors().stream()
.filter(RestTemplateBeanPostProcessorTest::isOtelInstrumentationInterceptor)
.count())
.isEqualTo(1);
verify(openTelemetryProvider, times(3)).getIfUnique();
}
@Test
@DisplayName("when OpenTelemetry is not available should NOT add RestTemplateInterceptor")
void doesNotAddRestTemplateInterceptorIfOpenTelemetryUnavailable() {
when(openTelemetryProvider.getIfUnique()).thenReturn(null);
RestTemplate restTemplate = new RestTemplate();
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
restTemplateBeanPostProcessor.postProcessAfterInitialization(restTemplate, "testRestTemplate");
assertThat(
restTemplate.getInterceptors().stream()
.filter(RestTemplateBeanPostProcessorTest::isOtelInstrumentationInterceptor)
.count())
.isEqualTo(0);
verify(openTelemetryProvider, times(3)).getIfUnique();
}
private static boolean isOtelInstrumentationInterceptor(ClientHttpRequestInterceptor rti) {
return rti.getClass().getName().startsWith("io.opentelemetry.instrumentation");
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/** Spring Boot auto configuration test for {@link WebClientAutoConfiguration}. */
class WebClientAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class, WebClientAutoConfiguration.class));
@Test
@DisplayName("when httpclients are ENABLED should initialize WebClientBeanPostProcessor bean")
void httpClientsEnabled() {
this.contextRunner
.withPropertyValues("otel.springboot.httpclients.enabled=true")
.run(
context ->
assertThat(
context.getBean(
"otelWebClientBeanPostProcessor", WebClientBeanPostProcessor.class))
.isNotNull());
}
@Test
@DisplayName(
"when httpclients are DISABLED should NOT initialize WebClientBeanPostProcessor bean")
void disabledProperty() {
this.contextRunner
.withPropertyValues("otel.springboot.httpclients.enabled=false")
.run(
context ->
assertThat(context.containsBean("otelWebClientBeanPostProcessor")).isFalse());
}
@Test
@DisplayName(
"when httpclients enabled property is MISSING should initialize WebClientBeanPostProcessor bean")
void noProperty() {
this.contextRunner.run(
context ->
assertThat(
context.getBean(
"otelWebClientBeanPostProcessor", WebClientBeanPostProcessor.class))
.isNotNull());
}
}

View File

@ -1,141 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.webclient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
@ExtendWith(MockitoExtension.class)
class WebClientBeanPostProcessorTest {
@Mock ObjectProvider<OpenTelemetry> openTelemetryProvider;
WebClientBeanPostProcessor webClientBeanPostProcessor;
@BeforeEach
void setUp() {
webClientBeanPostProcessor = new WebClientBeanPostProcessor(openTelemetryProvider);
}
@Test
@DisplayName(
"when processed bean is NOT of type WebClient or WebClientBuilder should return Object")
void returnsObject() {
assertThat(
webClientBeanPostProcessor.postProcessAfterInitialization(new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
verifyNoInteractions(openTelemetryProvider);
}
@Test
@DisplayName("when processed bean is of type WebClient should return WebClient")
void returnsWebClient() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
assertThat(
webClientBeanPostProcessor.postProcessAfterInitialization(
WebClient.create(), "testWebClient"))
.isInstanceOf(WebClient.class);
verify(openTelemetryProvider).getIfUnique();
}
@Test
@DisplayName("when processed bean is of type WebClientBuilder should return WebClientBuilder")
void returnsWebClientBuilder() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
assertThat(
webClientBeanPostProcessor.postProcessAfterInitialization(
WebClient.builder(), "testWebClientBuilder"))
.isInstanceOf(WebClient.Builder.class);
verify(openTelemetryProvider).getIfUnique();
}
@Test
@DisplayName("when processed bean is of type WebClient should add exchange filter to WebClient")
void addsExchangeFilterWebClient() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
WebClient webClient = WebClient.create();
Object processedWebClient =
webClientBeanPostProcessor.postProcessAfterInitialization(webClient, "testWebClient");
assertThat(processedWebClient).isInstanceOf(WebClient.class);
((WebClient) processedWebClient)
.mutate()
.filters(
functions ->
assertThat(functions.stream().filter(wctf -> isOtelExchangeFilter(wctf)).count())
.isEqualTo(1));
verify(openTelemetryProvider).getIfUnique();
}
@Test
@DisplayName(
"when processed bean is of type WebClient and OpenTelemetry is not available should NOT add exchange filter to WebClient")
void doesNotAddExchangeFilterWebClientIfOpenTelemetryUnavailable() {
when(openTelemetryProvider.getIfUnique()).thenReturn(null);
WebClient webClient = WebClient.create();
Object processedWebClient =
webClientBeanPostProcessor.postProcessAfterInitialization(webClient, "testWebClient");
assertThat(processedWebClient).isInstanceOf(WebClient.class);
((WebClient) processedWebClient)
.mutate()
.filters(
functions ->
assertThat(functions.stream().filter(wctf -> isOtelExchangeFilter(wctf)).count())
.isEqualTo(0));
verify(openTelemetryProvider).getIfUnique();
}
@Test
@DisplayName(
"when processed bean is of type WebClientBuilder should add ONE exchange filter to WebClientBuilder")
void addsExchangeFilterWebClientBuilder() {
when(openTelemetryProvider.getIfUnique()).thenReturn(OpenTelemetry.noop());
WebClient.Builder webClientBuilder = WebClient.builder();
webClientBeanPostProcessor.postProcessAfterInitialization(
webClientBuilder, "testWebClientBuilder");
webClientBeanPostProcessor.postProcessAfterInitialization(
webClientBuilder, "testWebClientBuilder");
webClientBeanPostProcessor.postProcessAfterInitialization(
webClientBuilder, "testWebClientBuilder");
webClientBuilder.filters(
functions ->
assertThat(functions.stream().filter(wctf -> isOtelExchangeFilter(wctf)).count())
.isEqualTo(1));
verify(openTelemetryProvider, times(3)).getIfUnique();
}
private static boolean isOtelExchangeFilter(ExchangeFilterFunction wctf) {
return wctf.getClass().getName().startsWith("io.opentelemetry.instrumentation");
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.api.trace.SpanKind.CLIENT; import static io.opentelemetry.api.trace.SpanKind.CLIENT;

View File

@ -0,0 +1,53 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class InstrumentationAnnotationsAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(InstrumentationAnnotationsAutoConfiguration.class));
@Test
void instrumentationEnabled() {
contextRunner
.withPropertyValues("otel.instrumentation.annotations.enabled=true")
.run(
context ->
assertThat(context)
.hasBean("otelInstrumentationWithSpanAspect")
.hasBean("otelSdkExtensionWithSpanAspect"));
}
@Test
void instrumentationDisabled() {
contextRunner
.withPropertyValues("otel.instrumentation.annotations.enabled=false")
.run(
context ->
assertThat(context)
.doesNotHaveBean("otelInstrumentationWithSpanAspect")
.doesNotHaveBean("otelSdkExtensionWithSpanAspect"));
}
@Test
void defaultConfiguration() {
contextRunner.run(
context ->
assertThat(context)
.hasBean("otelInstrumentationWithSpanAspect")
.hasBean("otelSdkExtensionWithSpanAspect"));
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import static io.opentelemetry.api.trace.SpanKind.CLIENT; import static io.opentelemetry.api.trace.SpanKind.CLIENT;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.aspects; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.annotations;
import static io.opentelemetry.api.trace.SpanKind.CLIENT; import static io.opentelemetry.api.trace.SpanKind.CLIENT;

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.kafka; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;

View File

@ -3,34 +3,33 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.metrics; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.micrometer;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.MeterRegistry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.micrometer.v1_5.OpenTelemetryMeterRegistry; import io.opentelemetry.instrumentation.micrometer.v1_5.OpenTelemetryMeterRegistry;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class MicrometerShimAutoConfigurationTest { class MicrometerBridgeAutoConfigurationTest {
private final ApplicationContextRunner runner = private final ApplicationContextRunner runner =
new ApplicationContextRunner() new ApplicationContextRunner()
.withConfiguration( .withBean(OpenTelemetry.class, OpenTelemetry::noop)
AutoConfigurations.of( .withConfiguration(AutoConfigurations.of(MicrometerBridgeAutoConfiguration.class));
OpenTelemetryAutoConfiguration.class, MicrometerShimAutoConfiguration.class));
@Test @Test
void metricsEnabled() { void metricsEnabled() {
runner runner
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
.withPropertyValues("otel.springboot.micrometer.enabled = true") .withPropertyValues("otel.instrumentation.micrometer.enabled = true")
.run( .run(
context -> context ->
assertThat(context.getBean("micrometerShim", MeterRegistry.class)) assertThat(context.getBean("otelMeterRegistry", MeterRegistry.class))
.isNotNull() .isNotNull()
.isInstanceOf(OpenTelemetryMeterRegistry.class)); .isInstanceOf(OpenTelemetryMeterRegistry.class));
} }
@ -41,7 +40,7 @@ class MicrometerShimAutoConfigurationTest {
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
.run( .run(
context -> context ->
assertThat(context.getBean("micrometerShim", MeterRegistry.class)) assertThat(context.getBean("otelMeterRegistry", MeterRegistry.class))
.isNotNull() .isNotNull()
.isInstanceOf(OpenTelemetryMeterRegistry.class)); .isInstanceOf(OpenTelemetryMeterRegistry.class));
} }
@ -50,14 +49,14 @@ class MicrometerShimAutoConfigurationTest {
void metricsDisabled() { void metricsDisabled() {
runner runner
.withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class)) .withConfiguration(AutoConfigurations.of(MetricsAutoConfiguration.class))
.withPropertyValues("otel.springboot.micrometer.enabled = false") .withPropertyValues("otel.instrumentation.micrometer.enabled = false")
.run(context -> assertThat(context.containsBean("micrometerShim")).isFalse()); .run(context -> assertThat(context.containsBean("otelMeterRegistry")).isFalse());
} }
@Test @Test
void noActuatorAutoConfiguration() { void noActuatorAutoConfiguration() {
runner runner
.withPropertyValues("otel.springboot.micrometer.enabled = true") .withPropertyValues("otel.instrumentation.micrometer.enabled = true")
.run(context -> assertThat(context.containsBean("micrometerShim")).isFalse()); .run(context -> assertThat(context.containsBean("otelMeterRegistry")).isFalse());
} }
} }

View File

@ -0,0 +1,58 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
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.beans.factory.config.BeanPostProcessor;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
class RestTemplateBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is not of type RestTemplate should return object")
void returnsObject() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
}
@Test
@DisplayName("when processed bean is of type RestTemplate should return RestTemplate")
void returnsRestTemplate() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new RestTemplate(), "testRestTemplate"))
.isInstanceOf(RestTemplate.class);
}
@Test
@DisplayName("when processed bean is of type RestTemplate should add ONE RestTemplateInterceptor")
void addsRestTemplateInterceptor() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
RestTemplate restTemplate = new RestTemplate();
underTest.postProcessAfterInitialization(restTemplate, "testRestTemplate");
underTest.postProcessAfterInitialization(restTemplate, "testRestTemplate");
underTest.postProcessAfterInitialization(restTemplate, "testRestTemplate");
assertThat(
restTemplate.getInterceptors().stream()
.filter(RestTemplateBeanPostProcessorTest::isOtelInstrumentationInterceptor)
.count())
.isEqualTo(1);
}
private static boolean isOtelInstrumentationInterceptor(ClientHttpRequestInterceptor rti) {
return rti.getClass().getName().startsWith("io.opentelemetry.instrumentation");
}
}

View File

@ -3,30 +3,27 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.httpclients.resttemplate; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration; import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/** Spring Boot auto configuration test for {@link RestTemplateAutoConfiguration}. */ class SpringWebInstrumentationAutoConfigurationTest {
class RestTemplateAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner() new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withConfiguration( .withConfiguration(
AutoConfigurations.of( AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class));
OpenTelemetryAutoConfiguration.class, RestTemplateAutoConfiguration.class));
@Test @Test
@DisplayName("when httpclients are ENABLED should initialize RestTemplateInterceptor bean") void instrumentationEnabled() {
void httpClientsEnabled() { contextRunner
this.contextRunner .withPropertyValues("otel.instrumentation.spring-web.enabled=true")
.withPropertyValues("otel.springboot.httpclients.enabled=true")
.run( .run(
context -> context ->
assertThat( assertThat(
@ -37,20 +34,17 @@ class RestTemplateAutoConfigurationTest {
} }
@Test @Test
@DisplayName("when httpclients are DISABLED should NOT initialize RestTemplateInterceptor bean") void instrumentationDisabled() {
void disabledProperty() { contextRunner
this.contextRunner .withPropertyValues("otel.instrumentation.spring-web.enabled=false")
.withPropertyValues("otel.springboot.httpclients.enabled=false")
.run( .run(
context -> context ->
assertThat(context.containsBean("otelRestTemplateBeanPostProcessor")).isFalse()); assertThat(context.containsBean("otelRestTemplateBeanPostProcessor")).isFalse());
} }
@Test @Test
@DisplayName( void defaultConfiguration() {
"when httpclients enabled property is MISSING should initialize RestTemplateInterceptor bean") contextRunner.run(
void noProperty() {
this.contextRunner.run(
context -> context ->
assertThat( assertThat(
context.getBean( context.getBean(

View File

@ -0,0 +1,53 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.OpenTelemetry;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class SpringWebfluxInstrumentationAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(SpringWebfluxInstrumentationAutoConfiguration.class));
@Test
void instrumentationEnabled() {
contextRunner
.withPropertyValues("otel.instrumentation.spring-webflux.enabled=true")
.run(
context ->
assertThat(
context.getBean(
"otelWebClientBeanPostProcessor", WebClientBeanPostProcessor.class))
.isNotNull());
}
@Test
void instrumentationDisabled() {
contextRunner
.withPropertyValues("otel.instrumentation.spring-webflux.enabled=false")
.run(
context ->
assertThat(context.containsBean("otelWebClientBeanPostProcessor")).isFalse());
}
@Test
void defaultConfiguration() {
contextRunner.run(
context ->
assertThat(
context.getBean(
"otelWebClientBeanPostProcessor", WebClientBeanPostProcessor.class))
.isNotNull());
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
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.beans.factory.config.BeanPostProcessor;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
class WebClientBeanPostProcessorTest {
@Test
@DisplayName(
"when processed bean is NOT of type WebClient or WebClientBuilder should return Object")
void returnsObject() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
}
@Test
@DisplayName("when processed bean is of type WebClient should return WebClient")
void returnsWebClient() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(WebClient.create(), "testWebClient"))
.isInstanceOf(WebClient.class);
}
@Test
@DisplayName("when processed bean is of type WebClientBuilder should return WebClientBuilder")
void returnsWebClientBuilder() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
assertThat(
underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder"))
.isInstanceOf(WebClient.Builder.class);
}
@Test
@DisplayName("when processed bean is of type WebClient should add exchange filter to WebClient")
void addsExchangeFilterWebClient() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
WebClient webClient = WebClient.create();
Object processedWebClient =
underTest.postProcessAfterInitialization(webClient, "testWebClient");
assertThat(processedWebClient).isInstanceOf(WebClient.class);
((WebClient) processedWebClient)
.mutate()
.filters(
functions ->
assertThat(
functions.stream()
.filter(WebClientBeanPostProcessorTest::isOtelExchangeFilter)
.count())
.isEqualTo(1));
}
@Test
@DisplayName(
"when processed bean is of type WebClientBuilder should add ONE exchange filter to WebClientBuilder")
void addsExchangeFilterWebClientBuilder() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
WebClient.Builder webClientBuilder = WebClient.builder();
underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder");
underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder");
underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder");
webClientBuilder.filters(
functions ->
assertThat(
functions.stream()
.filter(WebClientBeanPostProcessorTest::isOtelExchangeFilter)
.count())
.isEqualTo(1));
}
private static boolean isOtelExchangeFilter(ExchangeFilterFunction wctf) {
return wctf.getClass().getName().startsWith("io.opentelemetry.instrumentation");
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import io.opentelemetry.api.OpenTelemetry;
import javax.servlet.Filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class SpringWebMvcInstrumentation5AutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(SpringWebMvc5InstrumentationAutoConfiguration.class));
@BeforeEach
void setUp() {
assumeFalse(Boolean.getBoolean("testLatestDeps"));
}
@Test
void instrumentationEnabled() {
contextRunner
.withPropertyValues("otel.instrumentation.spring-webmvc.enabled=true")
.run(context -> assertThat(context.getBean("otelWebMvcFilter", Filter.class)).isNotNull());
}
@Test
void instrumentationDisabled() {
contextRunner
.withPropertyValues("otel.instrumentation.spring-webmvc.enabled=false")
.run(context -> assertThat(context.containsBean("otelWebMvcFilter")).isFalse());
}
@Test
void defaultConfiguration() {
contextRunner.run(
context -> assertThat(context.getBean("otelWebMvcFilter", Filter.class)).isNotNull());
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webmvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import io.opentelemetry.api.OpenTelemetry;
import jakarta.servlet.Filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
class SpringWebMvcInstrumentation6AutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(SpringWebMvc6InstrumentationAutoConfiguration.class));
@BeforeEach
void setUp() {
assumeTrue(Boolean.getBoolean("testLatestDeps"));
}
@Test
void instrumentationEnabled() {
this.contextRunner
.withPropertyValues("otel.instrumentation.spring-webmvc.enabled=true")
.run(context -> assertThat(context.getBean("otelWebMvcFilter", Filter.class)).isNotNull());
}
@Test
void instrumentationDisabled() {
this.contextRunner
.withPropertyValues("otel.instrumentation.spring-webmvc.enabled=false")
.run(context -> assertThat(context.containsBean("otelWebMvcFilter")).isFalse());
}
@Test
void defaultConfiguration() {
this.contextRunner.run(
context -> assertThat(context.getBean("otelWebMvcFilter", Filter.class)).isNotNull());
}
}

View File

@ -1,62 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.webmvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import jakarta.servlet.Filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/** Spring Boot auto configuration test for {@link WebMvcFilterAutoConfigurationSpring6}. */
class WebMvcFilterAutoConfigurationSpring6Test {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class,
WebMvcFilterAutoConfigurationSpring6.class));
@BeforeEach
void setUp() {
assumeTrue(Boolean.getBoolean("testLatestDeps"));
}
@Test
@DisplayName("when web is ENABLED should initialize WebMvcTracingFilter bean")
void webEnabled() {
this.contextRunner
.withPropertyValues("otel.springboot.web.enabled=true")
.run(
context ->
assertThat(context.getBean("otelWebMvcInstrumentationFilter", Filter.class))
.isNotNull());
}
@Test
@DisplayName("when web is DISABLED should NOT initialize WebMvcTracingFilter bean")
void disabledProperty() {
this.contextRunner
.withPropertyValues("otel.springboot.web.enabled=false")
.run(
context ->
assertThat(context.containsBean("otelWebMvcInstrumentationFilter")).isFalse());
}
@Test
@DisplayName("when web property is MISSING should initialize WebMvcTracingFilter bean")
void noProperty() {
this.contextRunner.run(
context ->
assertThat(context.getBean("otelWebMvcInstrumentationFilter", Filter.class))
.isNotNull());
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.webmvc;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
import javax.servlet.Filter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
/** Spring Boot auto configuration test for {@link WebMvcFilterAutoConfiguration}. */
class WebMvcFilterAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(
OpenTelemetryAutoConfiguration.class, WebMvcFilterAutoConfiguration.class));
@BeforeEach
void setUp() {
assumeFalse(Boolean.getBoolean("testLatestDeps"));
}
@Test
@DisplayName("when web is ENABLED should initialize WebMvcTracingFilter bean")
void webEnabled() {
this.contextRunner
.withPropertyValues("otel.springboot.web.enabled=true")
.run(
context ->
assertThat(context.getBean("otelWebMvcInstrumentationFilter", Filter.class))
.isNotNull());
}
@Test
@DisplayName("when web is DISABLED should NOT initialize WebMvcTracingFilter bean")
void disabledProperty() {
this.contextRunner
.withPropertyValues("otel.springboot.web.enabled=false")
.run(
context ->
assertThat(context.containsBean("otelWebMvcInstrumentationFilter")).isFalse());
}
@Test
@DisplayName("when web property is MISSING should initialize WebMvcTracingFilter bean")
void noProperty() {
this.contextRunner.run(
context ->
assertThat(context.getBean("otelWebMvcInstrumentationFilter", Filter.class))
.isNotNull());
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
package io.opentelemetry.instrumentation.spring.autoconfigure.logging; package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.logging;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;