diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java index bdf00acf732b..76288e4952df 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/SpringWebfluxInstrumentationAutoConfiguration.java @@ -40,7 +40,7 @@ static WebClientBeanPostProcessor otelWebClientBeanPostProcessor( @Bean WebFilter telemetryFilter(OpenTelemetry openTelemetry, ConfigProperties config) { - return WebClientBeanPostProcessor.getWebfluxTelemetry(openTelemetry, config) + return WebClientBeanPostProcessor.getWebfluxServerTelemetry(openTelemetry, config) .createWebFilterAndRegisterReactorHook(); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java index 90dde820c4a9..13a74048d3eb 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/webflux/WebClientBeanPostProcessor.java @@ -7,7 +7,8 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxClientTelemetry; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxServerTelemetry; import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import org.springframework.beans.factory.ObjectProvider; @@ -31,12 +32,20 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor { this.configPropertiesProvider = configPropertiesProvider; } - static SpringWebfluxTelemetry getWebfluxTelemetry( + static SpringWebfluxClientTelemetry getWebfluxClientTelemetry( OpenTelemetry openTelemetry, ConfigProperties config) { - return InstrumentationConfigUtil.configureClientAndServerBuilder( + return InstrumentationConfigUtil.configureClientBuilder( config, - SpringWebfluxTelemetry.builder(openTelemetry), - SpringWebfluxBuilderUtil.getClientBuilderExtractor(), + SpringWebfluxClientTelemetry.builder(openTelemetry), + SpringWebfluxBuilderUtil.getClientBuilderExtractor()) + .build(); + } + + static SpringWebfluxServerTelemetry getWebfluxServerTelemetry( + OpenTelemetry openTelemetry, ConfigProperties config) { + return InstrumentationConfigUtil.configureServerBuilder( + config, + SpringWebfluxServerTelemetry.builder(openTelemetry), SpringWebfluxBuilderUtil.getServerBuilderExtractor()) .build(); } @@ -54,9 +63,9 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { } private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) { - SpringWebfluxTelemetry instrumentation = - getWebfluxTelemetry( + SpringWebfluxClientTelemetry instrumentation = + getWebfluxClientTelemetry( openTelemetryProvider.getObject(), configPropertiesProvider.getObject()); - return webClientBuilder.filters(instrumentation::addClientTracingFilter); + return webClientBuilder.filters(instrumentation::addFilter); } } diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java index 747cf33dcb09..fb5e582bfaa5 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/properties/InstrumentationConfigUtil.java @@ -19,21 +19,6 @@ public final class InstrumentationConfigUtil { private InstrumentationConfigUtil() {} - @CanIgnoreReturnValue - public static - T configureClientAndServerBuilder( - ConfigProperties config, - T builder, - Function> - getClientBuilder, - Function> - getServerBuilder) { - CommonConfig commonConfig = getConfig(config); - getClientBuilder.apply(builder).configure(commonConfig); - getServerBuilder.apply(builder).configure(commonConfig); - return builder; - } - @CanIgnoreReturnValue public static T configureClientBuilder( ConfigProperties config, diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/README.md b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/README.md index a3c7f07aff7c..c02da7e3382a 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/README.md +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/README.md @@ -9,6 +9,7 @@ For this instrumentation, the minimum supported version of Spring Webflux is 5.3 For Maven, add to your `pom.xml`: ```xml + io.opentelemetry.instrumentation @@ -59,23 +60,24 @@ import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemet @Configuration public class WebClientConfig { - private final SpringWebfluxTelemetry webfluxTelemetry; + private final SpringWebfluxClientTelemetry webfluxClientTelemetry; + private final SpringWebfluxServerTelemetry webfluxServerTelemetry; public WebClientConfig(OpenTelemetry openTelemetry) { - this.webfluxTelemetry = SpringWebfluxTelemetry.builder(openTelemetry).build(); + this.webfluxClientTelemetry = SpringWebfluxClientTelemetry.builder(openTelemetry).build(); } // Adds instrumentation to WebClients @Bean public WebClient.Builder webClient() { WebClient webClient = WebClient.create(); - return webClient.mutate().filters(webfluxTelemetry::addClientTracingFilter); + return webClient.mutate().filters(webfluxClientTelemetry::addFilter); } // Adds instrumentation to Webflux server @Bean public WebFilter webFilter() { - return webfluxTelemetry.createWebFilterAndRegisterReactorHook(); + return webfluxServerTelemetry.createWebFilterAndRegisterReactorHook(); } } ``` diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetry.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetry.java new file mode 100644 index 000000000000..75bb07ce6f6a --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetry.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientTracingFilter; +import java.util.List; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; + +/** Entrypoint for instrumenting Spring Webflux HTTP clients. */ +public final class SpringWebfluxClientTelemetry { + + /** + * Returns a new {@link SpringWebfluxClientTelemetry} configured with the given {@link + * OpenTelemetry}. + */ + public static SpringWebfluxClientTelemetry create(OpenTelemetry openTelemetry) { + return builder(openTelemetry).build(); + } + + /** + * Returns a new {@link SpringWebfluxClientTelemetryBuilder} configured with the given {@link + * OpenTelemetry}. + */ + public static SpringWebfluxClientTelemetryBuilder builder(OpenTelemetry openTelemetry) { + return new SpringWebfluxClientTelemetryBuilder(openTelemetry); + } + + private final Instrumenter clientInstrumenter; + private final ContextPropagators propagators; + + SpringWebfluxClientTelemetry( + Instrumenter clientInstrumenter, + ContextPropagators propagators) { + this.clientInstrumenter = clientInstrumenter; + this.propagators = propagators; + } + + public void addFilter(List exchangeFilterFunctions) { + for (ExchangeFilterFunction filterFunction : exchangeFilterFunctions) { + if (filterFunction instanceof WebClientTracingFilter) { + return; + } + } + exchangeFilterFunctions.add(new WebClientTracingFilter(clientInstrumenter, propagators)); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetryBuilder.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetryBuilder.java new file mode 100644 index 000000000000..3c99207b9f8d --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientTelemetryBuilder.java @@ -0,0 +1,115 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.Experimental; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientHttpAttributesGetter; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ClientResponse; + +/** A builder of {@link SpringWebfluxClientTelemetry}. */ +public final class SpringWebfluxClientTelemetryBuilder { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3"; + + private final DefaultHttpClientInstrumenterBuilder builder; + private final OpenTelemetry openTelemetry; + + static { + SpringWebfluxBuilderUtil.setClientBuilderExtractor(builder -> builder.builder); + Experimental.setSetEmitExperimentalClientTelemetry( + (builder, emit) -> builder.builder.setEmitExperimentalHttpClientMetrics(emit)); + } + + SpringWebfluxClientTelemetryBuilder(OpenTelemetry openTelemetry) { + builder = + DefaultHttpClientInstrumenterBuilder.create( + INSTRUMENTATION_NAME, openTelemetry, WebClientHttpAttributesGetter.INSTANCE); + this.openTelemetry = openTelemetry; + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items for WebClient. + */ + @CanIgnoreReturnValue + public SpringWebfluxClientTelemetryBuilder addAttributesExtractor( + AttributesExtractor attributesExtractor) { + builder.addAttributesExtractor(attributesExtractor); + return this; + } + + /** + * Configures the HTTP WebClient request headers that will be captured as span attributes. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public SpringWebfluxClientTelemetryBuilder setCapturedRequestHeaders( + List requestHeaders) { + builder.setCapturedRequestHeaders(requestHeaders); + return this; + } + + /** + * Configures the HTTP WebClient response headers that will be captured as span attributes. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public SpringWebfluxClientTelemetryBuilder setCapturedResponseHeaders( + List responseHeaders) { + builder.setCapturedResponseHeaders(responseHeaders); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public SpringWebfluxClientTelemetryBuilder setKnownMethods(Set knownMethods) { + builder.setKnownMethods(knownMethods); + return this; + } + + /** Sets custom client {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public SpringWebfluxClientTelemetryBuilder setSpanNameExtractor( + Function< + SpanNameExtractor, + ? extends SpanNameExtractor> + clientSpanNameExtractor) { + builder.setSpanNameExtractor(clientSpanNameExtractor); + return this; + } + + /** + * Returns a new {@link SpringWebfluxClientTelemetry} with the settings of this {@link + * SpringWebfluxClientTelemetryBuilder}. + */ + public SpringWebfluxClientTelemetry build() { + return new SpringWebfluxClientTelemetry(builder.build(), openTelemetry.getPropagators()); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetry.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetry.java new file mode 100644 index 000000000000..f3c1dacca15f --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetry.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.reactor.v3_1.ContextPropagationOperator; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilter; + +/** Entrypoint for instrumenting Spring Webflux HTTP services. */ +public final class SpringWebfluxServerTelemetry { + + /** + * Returns a new {@link SpringWebfluxServerTelemetry} configured with the given {@link + * OpenTelemetry}. + */ + public static SpringWebfluxServerTelemetry create(OpenTelemetry openTelemetry) { + return builder(openTelemetry).build(); + } + + /** + * Returns a new {@link SpringWebfluxServerTelemetryBuilder} configured with the given {@link + * OpenTelemetry}. + */ + public static SpringWebfluxServerTelemetryBuilder builder(OpenTelemetry openTelemetry) { + return new SpringWebfluxServerTelemetryBuilder(openTelemetry); + } + + // We use ServerWebExchange (which holds both the request and response) + // because we need it to get the HTTP route while instrumenting. + private final Instrumenter serverInstrumenter; + + SpringWebfluxServerTelemetry( + Instrumenter serverInstrumenter) { + this.serverInstrumenter = serverInstrumenter; + } + + public WebFilter createWebFilter() { + return new TelemetryProducingWebFilter(serverInstrumenter); + } + + public WebFilter createWebFilterAndRegisterReactorHook() { + registerReactorHook(); + return this.createWebFilter(); + } + + private static void registerReactorHook() { + ContextPropagationOperator.builder().build().registerOnEachOperator(); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetryBuilder.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetryBuilder.java new file mode 100644 index 000000000000..b00dec6ffefb --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxServerTelemetryBuilder.java @@ -0,0 +1,116 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.Experimental; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import org.springframework.web.server.ServerWebExchange; + +/** A builder of {@link SpringWebfluxServerTelemetry}. */ +public final class SpringWebfluxServerTelemetryBuilder { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3"; + + private final DefaultHttpServerInstrumenterBuilder builder; + + static { + SpringWebfluxBuilderUtil.setServerBuilderExtractor(builder -> builder.builder); + Experimental.setSetEmitExperimentalServerTelemetry( + (builder, emit) -> builder.builder.setEmitExperimentalHttpServerMetrics(emit)); + } + + SpringWebfluxServerTelemetryBuilder(OpenTelemetry openTelemetry) { + builder = + DefaultHttpServerInstrumenterBuilder.create( + INSTRUMENTATION_NAME, + openTelemetry, + WebfluxServerHttpAttributesGetter.INSTANCE, + WebfluxTextMapGetter.INSTANCE); + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. + */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder addAttributesExtractor( + AttributesExtractor attributesExtractor) { + builder.addAttributesExtractor(attributesExtractor); + return this; + } + + /** + * Configures the HTTP request headers that will be captured as span attributes from server + * instrumentation. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder setCapturedRequestHeaders( + List requestHeaders) { + builder.setCapturedRequestHeaders(requestHeaders); + return this; + } + + /** + * Configures the HTTP response headers that will be captured as span attributes from server + * instrumentation. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder setCapturedResponseHeaders( + List responseHeaders) { + builder.setCapturedResponseHeaders(responseHeaders); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpServerAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder setKnownMethods(Set knownMethods) { + builder.setKnownMethods(knownMethods); + return this; + } + + /** Sets custom server {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder setSpanNameExtractor( + Function< + SpanNameExtractor, + ? extends SpanNameExtractor> + serverSpanNameExtractor) { + builder.setSpanNameExtractor(serverSpanNameExtractor); + return this; + } + + /** + * Returns a new {@link SpringWebfluxTelemetry} with the settings of this {@link + * SpringWebfluxServerTelemetryBuilder}. + */ + public SpringWebfluxServerTelemetry build() { + return new SpringWebfluxServerTelemetry(builder.build()); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetry.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetry.java index 27021d22ea40..eb534f4962c8 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetry.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetry.java @@ -17,12 +17,22 @@ import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; -/** Entrypoint for instrumenting Spring Webflux HTTP clients. */ +/** + * Entrypoint for instrumenting Spring Webflux HTTP clients and services. + * + * @deprecated Use {@link SpringWebfluxClientTelemetry} and {@link SpringWebfluxServerTelemetry} + * instead. + */ +@Deprecated public final class SpringWebfluxTelemetry { /** * Returns a new {@link SpringWebfluxTelemetry} configured with the given {@link OpenTelemetry}. + * + * @deprecated Use {@link SpringWebfluxClientTelemetry#create(OpenTelemetry)} and {@link + * SpringWebfluxServerTelemetry#create(OpenTelemetry)} instead. */ + @Deprecated public static SpringWebfluxTelemetry create(OpenTelemetry openTelemetry) { return builder(openTelemetry).build(); } @@ -30,7 +40,11 @@ public static SpringWebfluxTelemetry create(OpenTelemetry openTelemetry) { /** * Returns a new {@link SpringWebfluxTelemetryBuilder} configured with the given {@link * OpenTelemetry}. + * + * @deprecated Use {@link SpringWebfluxClientTelemetry#builder(OpenTelemetry)} and {@link + * SpringWebfluxServerTelemetry#builder(OpenTelemetry)} instead. */ + @Deprecated public static SpringWebfluxTelemetryBuilder builder(OpenTelemetry openTelemetry) { return new SpringWebfluxTelemetryBuilder(openTelemetry); } @@ -50,6 +64,10 @@ public static SpringWebfluxTelemetryBuilder builder(OpenTelemetry openTelemetry) this.propagators = propagators; } + /** + * @deprecated Use {@link SpringWebfluxClientTelemetry#addFilter(List)} instead. + */ + @Deprecated public void addClientTracingFilter(List exchangeFilterFunctions) { for (ExchangeFilterFunction filterFunction : exchangeFilterFunctions) { if (filterFunction instanceof WebClientTracingFilter) { @@ -59,10 +77,19 @@ public void addClientTracingFilter(List exchangeFilterFu exchangeFilterFunctions.add(new WebClientTracingFilter(clientInstrumenter, propagators)); } + /** + * @deprecated Use {@link SpringWebfluxServerTelemetry#createWebFilter()} instead. + */ + @Deprecated public WebFilter createWebFilter() { return new TelemetryProducingWebFilter(serverInstrumenter); } + /** + * @deprecated Use {@link SpringWebfluxServerTelemetry#createWebFilterAndRegisterReactorHook()} + * instead. + */ + @Deprecated public WebFilter createWebFilterAndRegisterReactorHook() { registerReactorHook(); return this.createWebFilter(); diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java index 7ecca97596fd..678f83608a22 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxTelemetryBuilder.java @@ -13,7 +13,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.SpringWebfluxBuilderUtil; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.Experimental; import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientHttpAttributesGetter; import java.util.List; import java.util.Set; @@ -22,7 +22,13 @@ import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; -/** A builder of {@link SpringWebfluxTelemetry}. */ +/** + * A builder of {@link SpringWebfluxTelemetry}. + * + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder} and {@link + * SpringWebfluxServerTelemetryBuilder} instead. + */ +@Deprecated public final class SpringWebfluxTelemetryBuilder { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3"; @@ -31,13 +37,6 @@ public final class SpringWebfluxTelemetryBuilder { serverBuilder; private final OpenTelemetry openTelemetry; - static { - SpringWebfluxBuilderUtil.setClientBuilderExtractor( - SpringWebfluxTelemetryBuilder::getClientBuilder); - SpringWebfluxBuilderUtil.setServerBuilderExtractor( - SpringWebfluxTelemetryBuilder::getServerBuilder); - } - SpringWebfluxTelemetryBuilder(OpenTelemetry openTelemetry) { clientBuilder = DefaultHttpClientInstrumenterBuilder.create( @@ -54,7 +53,11 @@ public final class SpringWebfluxTelemetryBuilder { /** * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented * items for WebClient. + * + * @deprecated Use {@link + * SpringWebfluxClientTelemetryBuilder#addAttributesExtractor(AttributesExtractor)} instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder addClientAttributesExtractor( AttributesExtractor attributesExtractor) { @@ -66,7 +69,10 @@ public SpringWebfluxTelemetryBuilder addClientAttributesExtractor( * Configures the HTTP WebClient request headers that will be captured as span attributes. * * @param requestHeaders A list of HTTP header names. + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder#setCapturedRequestHeaders(List)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedClientRequestHeaders( List requestHeaders) { @@ -78,7 +84,10 @@ public SpringWebfluxTelemetryBuilder setCapturedClientRequestHeaders( * Configures the HTTP WebClient response headers that will be captured as span attributes. * * @param responseHeaders A list of HTTP header names. + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder#setCapturedResponseHeaders(List)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedClientResponseHeaders( List responseHeaders) { @@ -89,7 +98,11 @@ public SpringWebfluxTelemetryBuilder setCapturedClientResponseHeaders( /** * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented * items. + * + * @deprecated Use {@link + * SpringWebfluxServerTelemetryBuilder#addAttributesExtractor(AttributesExtractor)} instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder addServerAttributesExtractor( AttributesExtractor attributesExtractor) { @@ -102,7 +115,10 @@ public SpringWebfluxTelemetryBuilder addServerAttributesExtractor( * instrumentation. * * @param requestHeaders A list of HTTP header names. + * @deprecated Use {@link SpringWebfluxServerTelemetryBuilder#setCapturedRequestHeaders(List)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedServerRequestHeaders( List requestHeaders) { @@ -115,7 +131,10 @@ public SpringWebfluxTelemetryBuilder setCapturedServerRequestHeaders( * instrumentation. * * @param responseHeaders A list of HTTP header names. + * @deprecated Use {@link SpringWebfluxServerTelemetryBuilder#setCapturedResponseHeaders(List)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setCapturedServerResponseHeaders( List responseHeaders) { @@ -136,7 +155,10 @@ public SpringWebfluxTelemetryBuilder setCapturedServerResponseHeaders( * @param knownMethods A set of recognized HTTP request methods. * @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set) * @see HttpServerAttributesExtractorBuilder#setKnownMethods(Set) + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder#setKnownMethods(Set)} and {@link + * SpringWebfluxServerTelemetryBuilder#setKnownMethods(Set)} instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setKnownMethods(Set knownMethods) { clientBuilder.setKnownMethods(knownMethods); @@ -149,7 +171,11 @@ public SpringWebfluxTelemetryBuilder setKnownMethods(Set knownMethods) { * * @param emitExperimentalHttpClientTelemetry {@code true} if the experimental HTTP client metrics * are to be emitted. + * @deprecated Use {@link + * Experimental#setEmitExperimentalTelemetry(SpringWebfluxClientTelemetryBuilder, boolean)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpClientTelemetry( boolean emitExperimentalHttpClientTelemetry) { @@ -162,7 +188,11 @@ public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpClientTelemetry( * * @param emitExperimentalHttpServerTelemetry {@code true} if the experimental HTTP server metrics * are to be emitted. + * @deprecated Use {@link + * Experimental#setEmitExperimentalTelemetry(SpringWebfluxServerTelemetryBuilder, boolean)} + * instead. */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpServerTelemetry( boolean emitExperimentalHttpServerTelemetry) { @@ -170,7 +200,13 @@ public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpServerTelemetry( return this; } - /** Sets custom client {@link SpanNameExtractor} via transform function. */ + /** + * Sets custom client {@link SpanNameExtractor} via transform function. + * + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder#setSpanNameExtractor(Function)} + * instead. + */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setClientSpanNameExtractor( Function< @@ -181,7 +217,13 @@ public SpringWebfluxTelemetryBuilder setClientSpanNameExtractor( return this; } - /** Sets custom server {@link SpanNameExtractor} via transform function. */ + /** + * Sets custom server {@link SpanNameExtractor} via transform function. + * + * @deprecated Use {@link SpringWebfluxServerTelemetryBuilder#setSpanNameExtractor(Function)} + * instead. + */ + @Deprecated @CanIgnoreReturnValue public SpringWebfluxTelemetryBuilder setServerSpanNameExtractor( Function< @@ -195,18 +237,13 @@ public SpringWebfluxTelemetryBuilder setServerSpanNameExtractor( /** * Returns a new {@link SpringWebfluxTelemetry} with the settings of this {@link * SpringWebfluxTelemetryBuilder}. + * + * @deprecated Use {@link SpringWebfluxClientTelemetryBuilder#build()} and {@link + * SpringWebfluxServerTelemetryBuilder#build()} instead. */ + @Deprecated public SpringWebfluxTelemetry build() { return new SpringWebfluxTelemetry( clientBuilder.build(), serverBuilder.build(), openTelemetry.getPropagators()); } - - private DefaultHttpClientInstrumenterBuilder getClientBuilder() { - return clientBuilder; - } - - private DefaultHttpServerInstrumenterBuilder - getServerBuilder() { - return serverBuilder; - } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/Experimental.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/Experimental.java new file mode 100644 index 000000000000..d20a6da4251f --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/Experimental.java @@ -0,0 +1,53 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal; + +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxClientTelemetryBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxServerTelemetryBuilder; +import java.util.function.BiConsumer; +import javax.annotation.Nullable; + +/** + * This class is internal and experimental. Its APIs are unstable and can change at any time. Its + * APIs (or a version of them) may be promoted to the public stable API in the future, but no + * guarantees are made. + */ +public final class Experimental { + + @Nullable + private static volatile BiConsumer + setEmitExperimentalClientTelemetry; + + @Nullable + private static volatile BiConsumer + setEmitExperimentalServerTelemetry; + + public static void setEmitExperimentalTelemetry( + SpringWebfluxClientTelemetryBuilder builder, boolean emitExperimentalTelemetry) { + if (setEmitExperimentalClientTelemetry != null) { + setEmitExperimentalClientTelemetry.accept(builder, emitExperimentalTelemetry); + } + } + + public static void setEmitExperimentalTelemetry( + SpringWebfluxServerTelemetryBuilder builder, boolean emitExperimentalTelemetry) { + if (setEmitExperimentalServerTelemetry != null) { + setEmitExperimentalServerTelemetry.accept(builder, emitExperimentalTelemetry); + } + } + + public static void setSetEmitExperimentalClientTelemetry( + BiConsumer setEmitExperimentalClientTelemetry) { + Experimental.setEmitExperimentalClientTelemetry = setEmitExperimentalClientTelemetry; + } + + public static void setSetEmitExperimentalServerTelemetry( + BiConsumer setEmitExperimentalServerTelemetry) { + Experimental.setEmitExperimentalServerTelemetry = setEmitExperimentalServerTelemetry; + } + + private Experimental() {} +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java index ec1d643b1d88..e2e9ebf87b08 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/SpringWebfluxBuilderUtil.java @@ -7,7 +7,8 @@ import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetryBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxClientTelemetryBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxServerTelemetryBuilder; import java.util.function.Function; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; @@ -22,18 +23,18 @@ private SpringWebfluxBuilderUtil() {} // allows access to the private field for the spring starter private static Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxClientTelemetryBuilder, DefaultHttpClientInstrumenterBuilder> clientBuilderExtractor; // allows access to the private field for the spring starter private static Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxServerTelemetryBuilder, DefaultHttpServerInstrumenterBuilder> serverBuilderExtractor; public static Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxServerTelemetryBuilder, DefaultHttpServerInstrumenterBuilder> getServerBuilderExtractor() { return serverBuilderExtractor; @@ -41,14 +42,14 @@ private SpringWebfluxBuilderUtil() {} public static void setServerBuilderExtractor( Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxServerTelemetryBuilder, DefaultHttpServerInstrumenterBuilder> serverBuilderExtractor) { SpringWebfluxBuilderUtil.serverBuilderExtractor = serverBuilderExtractor; } public static Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxClientTelemetryBuilder, DefaultHttpClientInstrumenterBuilder> getClientBuilderExtractor() { return clientBuilderExtractor; @@ -56,7 +57,7 @@ public static void setServerBuilderExtractor( public static void setClientBuilderExtractor( Function< - SpringWebfluxTelemetryBuilder, + SpringWebfluxClientTelemetryBuilder, DefaultHttpClientInstrumenterBuilder> clientBuilderExtractor) { SpringWebfluxBuilderUtil.clientBuilderExtractor = clientBuilderExtractor; diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxClientInstrumentationOldTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxClientInstrumentationOldTest.java new file mode 100644 index 000000000000..3b346b42176d --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxClientInstrumentationOldTest.java @@ -0,0 +1,35 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.old.v5_3; + +import io.opentelemetry.instrumentation.spring.webflux.client.AbstractSpringWebfluxClientInstrumentationTest; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import java.util.Collections; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.springframework.web.reactive.function.client.WebClient; + +@SuppressWarnings("deprecation") // testing deprecated API +class SpringWebfluxClientInstrumentationOldTest + extends AbstractSpringWebfluxClientInstrumentationTest { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forLibrary(); + + @Override + protected WebClient.Builder instrument(WebClient.Builder builder) { + io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry instrumentation = + io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry.builder( + testing.getOpenTelemetry()) + .setCapturedClientRequestHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_REQUEST_HEADER)) + .setCapturedClientResponseHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_RESPONSE_HEADER)) + .build(); + return builder.filters(instrumentation::addClientTracingFilter); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxServerInstrumentationOldTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxServerInstrumentationOldTest.java new file mode 100644 index 000000000000..c5fb0b745e83 --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/SpringWebfluxServerInstrumentationOldTest.java @@ -0,0 +1,70 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.old.v5_3; + +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerTestOptions; +import io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpRequest; +import io.opentelemetry.testing.internal.armeria.common.AggregatedHttpResponse; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.springframework.context.ConfigurableApplicationContext; + +@SuppressWarnings("deprecation") // testing deprecated API +public final class SpringWebfluxServerInstrumentationOldTest + extends AbstractHttpServerTest { + + private static final String CONTEXT_PATH = "/test"; + + @RegisterExtension + static final InstrumentationExtension testing = HttpServerInstrumentationExtension.forLibrary(); + + @Override + protected ConfigurableApplicationContext setupServer() { + return TestWebfluxSpringBootOldApp.start(port, CONTEXT_PATH); + } + + @Override + public void stopServer(ConfigurableApplicationContext applicationContext) { + applicationContext.close(); + } + + @Override + protected void configure(HttpServerTestOptions options) { + options.setContextPath(CONTEXT_PATH); + options.setTestPathParam(true); + options.setExpectedException(new RuntimeException(ServerEndpoint.EXCEPTION.getBody())); + + options.setExpectedHttpRoute( + (endpoint, method) -> { + if (endpoint == ServerEndpoint.PATH_PARAM) { + return CONTEXT_PATH + "/path/{id}/param"; + } + return expectedHttpRoute(endpoint, method); + }); + + options.disableTestNonStandardHttpMethod(); + } + + @Test + void noMono() { + ServerEndpoint endpoint = new ServerEndpoint("NO_MONO", "no-mono", 200, "success"); + String method = "GET"; + AggregatedHttpRequest request = request(endpoint, method); + AggregatedHttpResponse response = client.execute(request).aggregate().join(); + + assertThat(response.status().code()).isEqualTo(SUCCESS.getStatus()); + assertThat(response.contentUtf8()).isEqualTo(SUCCESS.getBody()); + + assertTheTraces(1, null, null, null, method, endpoint); + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/TestWebfluxSpringBootOldApp.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/TestWebfluxSpringBootOldApp.java new file mode 100644 index 000000000000..df8031e6d17c --- /dev/null +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/old/v5_3/TestWebfluxSpringBootOldApp.java @@ -0,0 +1,142 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.old.v5_3; + +import static io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest.controller; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.CAPTURE_HEADERS; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.ERROR; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.EXCEPTION; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.INDEXED_CHILD; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.PATH_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.QUERY_PARAM; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.REDIRECT; +import static io.opentelemetry.instrumentation.testing.junit.http.ServerEndpoint.SUCCESS; +import static java.util.Collections.singletonList; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerTest; +import java.net.URI; +import java.util.Properties; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.server.WebFilter; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Deprecated +@SpringBootApplication +class TestWebfluxSpringBootOldApp { + + static ConfigurableApplicationContext start(int port, String contextPath) { + Properties props = new Properties(); + props.put("server.port", port); + props.put("spring.webflux.base-path", contextPath); + + SpringApplication app = new SpringApplication(TestWebfluxSpringBootOldApp.class); + app.setDefaultProperties(props); + return app.run(); + } + + @Bean + WebFilter telemetryFilter() { + return io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry.builder( + GlobalOpenTelemetry.get()) + .setCapturedServerRequestHeaders(singletonList(AbstractHttpServerTest.TEST_REQUEST_HEADER)) + .setCapturedServerResponseHeaders( + singletonList(AbstractHttpServerTest.TEST_RESPONSE_HEADER)) + .build() + .createWebFilterAndRegisterReactorHook(); + } + + @Controller + static class TestController { + + @RequestMapping("/success") + @ResponseBody + Flux success() { + return Flux.defer(() -> Flux.just(controller(SUCCESS, SUCCESS::getBody))); + } + + @RequestMapping("/no-mono") + @ResponseBody + String noMono() { + return controller(SUCCESS, SUCCESS::getBody); + } + + @RequestMapping("/query") + @ResponseBody + Mono query_param(@RequestParam("some") String param) { + return Mono.just(controller(QUERY_PARAM, () -> "some=" + param)); + } + + @RequestMapping("/redirect") + @ResponseBody + Mono redirect(ServerHttpResponse response) { + response.setStatusCode(HttpStatus.FOUND); + response.getHeaders().setLocation(URI.create("/redirected")); + return controller(REDIRECT, response::setComplete); + } + + @RequestMapping("/error-status") + Mono> error() { + return Mono.just( + controller( + ERROR, + () -> new ResponseEntity<>(ERROR.getBody(), HttpStatus.valueOf(ERROR.getStatus())))); + } + + @RequestMapping("/exception") + Flux> exception() throws Exception { + return Flux.just( + controller( + EXCEPTION, + () -> { + throw new RuntimeException(EXCEPTION.getBody()); + })); + } + + @RequestMapping("/captureHeaders") + Mono> capture_headers( + @RequestHeader("X-Test-Request") String testRequestHeader) { + return Mono.just( + controller( + CAPTURE_HEADERS, + () -> + ResponseEntity.ok() + .header("X-Test-Response", testRequestHeader) + .body(CAPTURE_HEADERS.getBody()))); + } + + @RequestMapping("/path/{id}/param") + @ResponseBody + Mono path_param(@PathVariable("id") int id) { + return Mono.just(controller(PATH_PARAM, () -> String.valueOf(id))); + } + + @RequestMapping("/child") + @ResponseBody + Mono indexed_child(@RequestParam("id") String id) { + return Mono.just( + controller( + INDEXED_CHILD, + () -> { + INDEXED_CHILD.collectSpanAttributes(name -> name.equals("id") ? id : null); + return INDEXED_CHILD.getBody(); + })); + } + } +} diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientInstrumentationTest.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientInstrumentationTest.java index 6ed4170704ab..723c4fe63505 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientInstrumentationTest.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/SpringWebfluxClientInstrumentationTest.java @@ -21,13 +21,13 @@ class SpringWebfluxClientInstrumentationTest @Override protected WebClient.Builder instrument(WebClient.Builder builder) { - SpringWebfluxTelemetry instrumentation = - SpringWebfluxTelemetry.builder(testing.getOpenTelemetry()) - .setCapturedClientRequestHeaders( + SpringWebfluxClientTelemetry instrumentation = + SpringWebfluxClientTelemetry.builder(testing.getOpenTelemetry()) + .setCapturedRequestHeaders( Collections.singletonList(AbstractHttpClientTest.TEST_REQUEST_HEADER)) - .setCapturedClientResponseHeaders( + .setCapturedResponseHeaders( Collections.singletonList(AbstractHttpClientTest.TEST_RESPONSE_HEADER)) .build(); - return builder.filters(instrumentation::addClientTracingFilter); + return builder.filters(instrumentation::addFilter); } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java index c0eb9a65d91e..77afcf9881c0 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/TestWebfluxSpringBootApp.java @@ -52,10 +52,9 @@ static ConfigurableApplicationContext start(int port, String contextPath) { @Bean WebFilter telemetryFilter() { - return SpringWebfluxTelemetry.builder(GlobalOpenTelemetry.get()) - .setCapturedServerRequestHeaders(singletonList(AbstractHttpServerTest.TEST_REQUEST_HEADER)) - .setCapturedServerResponseHeaders( - singletonList(AbstractHttpServerTest.TEST_RESPONSE_HEADER)) + return SpringWebfluxServerTelemetry.builder(GlobalOpenTelemetry.get()) + .setCapturedRequestHeaders(singletonList(AbstractHttpServerTest.TEST_REQUEST_HEADER)) + .setCapturedResponseHeaders(singletonList(AbstractHttpServerTest.TEST_RESPONSE_HEADER)) .build() .createWebFilterAndRegisterReactorHook(); }