Fix warnings from the spring boot starter (#10086)

This commit is contained in:
Lauri Tulmin 2023-12-22 11:00:01 +02:00 committed by GitHub
parent 1ee51e410e
commit 04da58e5e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 81 additions and 30 deletions

View File

@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.Otlp
import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpMetricExporterAutoConfiguration;
import io.opentelemetry.instrumentation.spring.autoconfigure.exporters.otlp.OtlpSpanExporterAutoConfiguration;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.MapConverter;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import io.opentelemetry.instrumentation.spring.autoconfigure.resources.OtelResourceAutoConfiguration;
import io.opentelemetry.instrumentation.spring.autoconfigure.resources.SpringResourceConfigProperties;
import io.opentelemetry.sdk.OpenTelemetrySdk;
@ -34,7 +35,9 @@ import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -42,6 +45,7 @@ import org.springframework.boot.context.properties.ConfigurationPropertiesBindin
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.core.env.Environment;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@ -189,4 +193,12 @@ public class OpenTelemetryAutoConfiguration {
return OpenTelemetry.noop();
}
}
@Bean
// we declared this bean as an infrastructure bean to avoid warning from BeanPostProcessorChecker
// when it is injected into a BeanPostProcessor
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static OpenTelemetrySupplier openTelemetrySupplier(BeanFactory beanFactory) {
return () -> beanFactory.getBean(OpenTelemetry.class);
}
}

View File

@ -5,17 +5,18 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.kafka;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import io.opentelemetry.instrumentation.spring.kafka.v2_7.SpringKafkaTelemetry;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
class ConcurrentKafkaListenerContainerFactoryPostProcessor implements BeanPostProcessor {
private final OpenTelemetry openTelemetry;
private final OpenTelemetrySupplier openTelemetrySupplier;
ConcurrentKafkaListenerContainerFactoryPostProcessor(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
ConcurrentKafkaListenerContainerFactoryPostProcessor(
OpenTelemetrySupplier openTelemetrySupplier) {
this.openTelemetrySupplier = openTelemetrySupplier;
}
@Override
@ -26,7 +27,8 @@ class ConcurrentKafkaListenerContainerFactoryPostProcessor implements BeanPostPr
ConcurrentKafkaListenerContainerFactory<?, ?> listenerContainerFactory =
(ConcurrentKafkaListenerContainerFactory<?, ?>) bean;
SpringKafkaTelemetry springKafkaTelemetry = SpringKafkaTelemetry.create(openTelemetry);
SpringKafkaTelemetry springKafkaTelemetry =
SpringKafkaTelemetry.create(openTelemetrySupplier.get());
listenerContainerFactory.setBatchInterceptor(springKafkaTelemetry.createBatchInterceptor());
listenerContainerFactory.setRecordInterceptor(springKafkaTelemetry.createRecordInterceptor());

View File

@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.ka
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.kafkaclients.v2_6.KafkaTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -30,8 +31,9 @@ public class KafkaInstrumentationAutoConfiguration {
}
@Bean
ConcurrentKafkaListenerContainerFactoryPostProcessor
otelKafkaListenerContainerFactoryBeanPostProcessor(OpenTelemetry openTelemetry) {
return new ConcurrentKafkaListenerContainerFactoryPostProcessor(openTelemetry);
static ConcurrentKafkaListenerContainerFactoryPostProcessor
otelKafkaListenerContainerFactoryBeanPostProcessor(
OpenTelemetrySupplier openTelemetrySupplier) {
return new ConcurrentKafkaListenerContainerFactoryPostProcessor(openTelemetrySupplier);
}
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import io.opentelemetry.instrumentation.spring.web.v3_1.SpringWebTelemetry;
import java.util.List;
import org.springframework.beans.factory.config.BeanPostProcessor;
@ -14,10 +14,10 @@ import org.springframework.web.client.RestTemplate;
final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
private final OpenTelemetry openTelemetry;
private final OpenTelemetrySupplier openTelemetrySupplier;
RestTemplateBeanPostProcessor(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
RestTemplateBeanPostProcessor(OpenTelemetrySupplier openTelemetrySupplier) {
this.openTelemetrySupplier = openTelemetrySupplier;
}
@Override
@ -28,7 +28,7 @@ final class RestTemplateBeanPostProcessor implements BeanPostProcessor {
RestTemplate restTemplate = (RestTemplate) bean;
ClientHttpRequestInterceptor interceptor =
SpringWebTelemetry.create(openTelemetry).newInterceptor();
SpringWebTelemetry.create(openTelemetrySupplier.get()).newInterceptor();
addRestTemplateInterceptorIfNotPresent(restTemplate, interceptor);
return restTemplate;
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.web;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -24,8 +25,11 @@ import org.springframework.web.client.RestTemplate;
@Configuration
public class SpringWebInstrumentationAutoConfiguration {
public SpringWebInstrumentationAutoConfiguration() {}
@Bean
RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor(OpenTelemetry openTelemetry) {
return new RestTemplateBeanPostProcessor(openTelemetry);
static RestTemplateBeanPostProcessor otelRestTemplateBeanPostProcessor(
OpenTelemetrySupplier openTelemetrySupplier) {
return new RestTemplateBeanPostProcessor(openTelemetrySupplier);
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -24,8 +25,11 @@ import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class SpringWebfluxInstrumentationAutoConfiguration {
public SpringWebfluxInstrumentationAutoConfiguration() {}
@Bean
WebClientBeanPostProcessor otelWebClientBeanPostProcessor(OpenTelemetry openTelemetry) {
return new WebClientBeanPostProcessor(openTelemetry);
static WebClientBeanPostProcessor otelWebClientBeanPostProcessor(
OpenTelemetrySupplier openTelemetrySupplier) {
return new WebClientBeanPostProcessor(openTelemetrySupplier);
}
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.web.reactive.function.client.WebClient;
@ -17,10 +17,10 @@ import org.springframework.web.reactive.function.client.WebClient;
*/
final class WebClientBeanPostProcessor implements BeanPostProcessor {
private final OpenTelemetry openTelemetry;
private final OpenTelemetrySupplier openTelemetrySupplier;
WebClientBeanPostProcessor(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
WebClientBeanPostProcessor(OpenTelemetrySupplier openTelemetrySupplier) {
this.openTelemetrySupplier = openTelemetrySupplier;
}
@Override
@ -36,7 +36,8 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor {
}
private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) {
SpringWebfluxTelemetry instrumentation = SpringWebfluxTelemetry.create(openTelemetry);
SpringWebfluxTelemetry instrumentation =
SpringWebfluxTelemetry.create(openTelemetrySupplier.get());
return webClientBuilder.filters(instrumentation::addClientTracingFilter);
}
}

View File

@ -0,0 +1,17 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.spring.autoconfigure.internal;
import io.opentelemetry.api.OpenTelemetry;
import java.util.function.Supplier;
/**
* Used to provide access to the OpenTelemetry instance in bean post processors.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public interface OpenTelemetrySupplier extends Supplier<OpenTelemetry> {}

View File

@ -10,6 +10,7 @@ import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satis
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
import io.opentelemetry.semconv.SemanticAttributes;
import java.time.Duration;
@ -68,6 +69,10 @@ class KafkaIntegrationTest {
KafkaInstrumentationAutoConfiguration.class,
TestConfig.class))
.withBean("openTelemetry", OpenTelemetry.class, testing::getOpenTelemetry)
.withBean(
"openTelemetrySupplier",
OpenTelemetrySupplier.class,
() -> testing::getOpenTelemetry)
.withPropertyValues(
"spring.kafka.bootstrap-servers=" + kafka.getBootstrapServers(),
"spring.kafka.consumer.auto-offset-reset=earliest",

View File

@ -19,7 +19,7 @@ class RestTemplateBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is not of type RestTemplate should return object")
void returnsObject() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(() -> OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
@ -28,7 +28,7 @@ class RestTemplateBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is of type RestTemplate should return RestTemplate")
void returnsRestTemplate() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(() -> OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new RestTemplate(), "testRestTemplate"))
.isInstanceOf(RestTemplate.class);
@ -37,7 +37,7 @@ class RestTemplateBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is of type RestTemplate should add ONE RestTemplateInterceptor")
void addsRestTemplateInterceptor() {
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new RestTemplateBeanPostProcessor(() -> OpenTelemetry.noop());
RestTemplate restTemplate = new RestTemplate();

View File

@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@ -17,6 +18,7 @@ class SpringWebInstrumentationAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withBean(OpenTelemetrySupplier.class, () -> OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(SpringWebInstrumentationAutoConfiguration.class));

View File

@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.OpenTelemetrySupplier;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@ -17,6 +18,7 @@ class SpringWebfluxInstrumentationAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
.withBean(OpenTelemetrySupplier.class, () -> OpenTelemetry::noop)
.withConfiguration(
AutoConfigurations.of(SpringWebfluxInstrumentationAutoConfiguration.class));

View File

@ -20,7 +20,7 @@ class WebClientBeanPostProcessorTest {
@DisplayName(
"when processed bean is NOT of type WebClient or WebClientBuilder should return Object")
void returnsObject() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new WebClientBeanPostProcessor(() -> OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject"))
.isExactlyInstanceOf(Object.class);
@ -29,7 +29,7 @@ class WebClientBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is of type WebClient should return WebClient")
void returnsWebClient() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new WebClientBeanPostProcessor(() -> OpenTelemetry.noop());
assertThat(underTest.postProcessAfterInitialization(WebClient.create(), "testWebClient"))
.isInstanceOf(WebClient.class);
@ -38,7 +38,7 @@ class WebClientBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is of type WebClientBuilder should return WebClientBuilder")
void returnsWebClientBuilder() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new WebClientBeanPostProcessor(() -> OpenTelemetry.noop());
assertThat(
underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder"))
@ -48,7 +48,7 @@ class WebClientBeanPostProcessorTest {
@Test
@DisplayName("when processed bean is of type WebClient should add exchange filter to WebClient")
void addsExchangeFilterWebClient() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new WebClientBeanPostProcessor(() -> OpenTelemetry.noop());
WebClient webClient = WebClient.create();
Object processedWebClient =
@ -70,7 +70,7 @@ class WebClientBeanPostProcessorTest {
@DisplayName(
"when processed bean is of type WebClientBuilder should add ONE exchange filter to WebClientBuilder")
void addsExchangeFilterWebClientBuilder() {
BeanPostProcessor underTest = new WebClientBeanPostProcessor(OpenTelemetry.noop());
BeanPostProcessor underTest = new WebClientBeanPostProcessor(() -> OpenTelemetry.noop());
WebClient.Builder webClientBuilder = WebClient.builder();
underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder");