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..22d06fe358c3 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::addTracingFilter); } } 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/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..94139e19949e --- /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 addTracingFilter(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..0c5330db4766 --- /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,127 @@ +/* + * 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( + SpringWebfluxClientTelemetryBuilder::getBuilder); + } + + 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.addAttributeExtractor(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; + } + + /** + * Can be used via the unstable method {@link + * Experimental#setEmitExperimentalHttpClientMetrics(SpringWebfluxClientTelemetryBuilder, + * boolean)}. + */ + void setEmitExperimentalHttpClientTelemetry(boolean emitExperimentalHttpClientTelemetry) { + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientTelemetry); + } + + /** + * Returns a new {@link SpringWebfluxClientTelemetry} with the settings of this {@link + * SpringWebfluxClientTelemetryBuilder}. + */ + public SpringWebfluxClientTelemetry build() { + return new SpringWebfluxClientTelemetry(builder.build(), openTelemetry.getPropagators()); + } + + private DefaultHttpClientInstrumenterBuilder getBuilder() { + return builder; + } +} 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..ae1046b43e0b --- /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,130 @@ +/* + * 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 + serverBuilder; + + static { + SpringWebfluxBuilderUtil.setServerBuilderExtractor( + SpringWebfluxServerTelemetryBuilder::getServerBuilder); + } + + SpringWebfluxServerTelemetryBuilder(OpenTelemetry openTelemetry) { + serverBuilder = + 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) { + serverBuilder.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) { + serverBuilder.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) { + serverBuilder.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) { + serverBuilder.setKnownMethods(knownMethods); + return this; + } + + /** Sets custom server {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public SpringWebfluxServerTelemetryBuilder setSpanNameExtractor( + Function< + SpanNameExtractor, + ? extends SpanNameExtractor> + serverSpanNameExtractor) { + serverBuilder.setSpanNameExtractor(serverSpanNameExtractor); + return this; + } + + /** + * Can be used via the unstable method {@link + * Experimental#setEmitExperimentalHttpServerMetrics(SpringWebfluxServerTelemetryBuilder, + * boolean)}. + */ + void setEmitExperimentalHttpServerTelemetry(boolean emitExperimentalHttpServerTelemetry) { + serverBuilder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerTelemetry); + } + + /** + * Returns a new {@link SpringWebfluxTelemetry} with the settings of this {@link + * SpringWebfluxServerTelemetryBuilder}. + */ + public SpringWebfluxServerTelemetry build() { + return new SpringWebfluxServerTelemetry(serverBuilder.build()); + } + + 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/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..622b671fb0b9 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#addTracingFilter(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 602ded9c1d4d..8d2ec24084c0 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#setEmitExperimentalHttpClientMetrics(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#setEmitExperimentalHttpServerMetrics(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..0b1dd41a0320 --- /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,86 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal; + +import static java.util.logging.Level.FINE; + +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxClientTelemetryBuilder; +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxServerTelemetryBuilder; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +// TODO (trask) update the above javadoc similar to +// https://github.com/open-telemetry/opentelemetry-java/pull/6886 +public class Experimental { + + private static final Logger logger = Logger.getLogger(Experimental.class.getName()); + + @Nullable + private static final Method emitExperimentalHttpClientMetricsMethod = + getEmitExperimentalHttpClientMetricsMethod(); + + @Nullable + private static final Method emitExperimentalHttpServerMetricsMethod = + getEmitExperimentalHttpServerMetricsMethod(); + + public void setEmitExperimentalHttpClientMetrics( + SpringWebfluxClientTelemetryBuilder builder, boolean emitExperimentalHttpClientMetrics) { + + if (emitExperimentalHttpClientMetricsMethod != null) { + try { + emitExperimentalHttpClientMetricsMethod.invoke(builder, emitExperimentalHttpClientMetrics); + } catch (IllegalAccessException | InvocationTargetException e) { + logger.log(FINE, e.getMessage(), e); + } + } + } + + public void setEmitExperimentalHttpServerMetrics( + SpringWebfluxServerTelemetryBuilder builder, boolean emitExperimentalHttpServerMetrics) { + + if (emitExperimentalHttpServerMetricsMethod != null) { + try { + emitExperimentalHttpServerMetricsMethod.invoke(builder, emitExperimentalHttpServerMetrics); + } catch (IllegalAccessException | InvocationTargetException e) { + logger.log(FINE, e.getMessage(), e); + } + } + } + + @Nullable + private static Method getEmitExperimentalHttpClientMetricsMethod() { + try { + Method method = + SpringWebfluxClientTelemetryBuilder.class.getDeclaredMethod( + "setEmitExperimentalHttpClientTelemetry", boolean.class); + method.setAccessible(true); + return method; + } catch (NoSuchMethodException e) { + logger.log(FINE, e.getMessage(), e); + return null; + } + } + + @Nullable + private static Method getEmitExperimentalHttpServerMetricsMethod() { + try { + Method method = + SpringWebfluxServerTelemetryBuilder.class.getDeclaredMethod( + "setEmitExperimentalHttpServerTelemetry", boolean.class); + method.setAccessible(true); + return method; + } catch (NoSuchMethodException e) { + logger.log(FINE, e.getMessage(), e); + return null; + } + } +} 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/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..e8980ef3d9fb 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::addTracingFilter); } } 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(); }