Use config properties for spring starter (http server) (#11667)
Co-authored-by: Lauri Tulmin <tulmin@gmail.com> Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
parent
e36fc46fd5
commit
9bbfe7fe4e
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.incubator.builder.internal;
|
||||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.context.propagation.TextMapGetter;
|
||||
import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesGetter;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
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.
|
||||
*/
|
||||
public final class DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> {
|
||||
|
||||
private final String instrumentationName;
|
||||
private final OpenTelemetry openTelemetry;
|
||||
|
||||
private final List<AttributesExtractor<? super REQUEST, ? super RESPONSE>> additionalExtractors =
|
||||
new ArrayList<>();
|
||||
private Function<
|
||||
SpanStatusExtractor<? super REQUEST, ? super RESPONSE>,
|
||||
? extends SpanStatusExtractor<? super REQUEST, ? super RESPONSE>>
|
||||
statusExtractorTransformer = Function.identity();
|
||||
private final HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE>
|
||||
httpAttributesExtractorBuilder;
|
||||
private final HttpSpanNameExtractorBuilder<REQUEST> httpSpanNameExtractorBuilder;
|
||||
|
||||
@Nullable private TextMapGetter<REQUEST> headerGetter;
|
||||
private Function<SpanNameExtractor<REQUEST>, ? extends SpanNameExtractor<? super REQUEST>>
|
||||
spanNameExtractorTransformer = Function.identity();
|
||||
private final HttpServerRouteBuilder<REQUEST> httpServerRouteBuilder;
|
||||
private final HttpServerAttributesGetter<REQUEST, RESPONSE> attributesGetter;
|
||||
private boolean emitExperimentalHttpServerMetrics = false;
|
||||
|
||||
public DefaultHttpServerInstrumenterBuilder(
|
||||
String instrumentationName,
|
||||
OpenTelemetry openTelemetry,
|
||||
HttpServerAttributesGetter<REQUEST, RESPONSE> attributesGetter) {
|
||||
this.instrumentationName = instrumentationName;
|
||||
this.openTelemetry = openTelemetry;
|
||||
httpAttributesExtractorBuilder = HttpServerAttributesExtractor.builder(attributesGetter);
|
||||
httpSpanNameExtractorBuilder = HttpSpanNameExtractor.builder(attributesGetter);
|
||||
httpServerRouteBuilder = HttpServerRoute.builder(attributesGetter);
|
||||
this.attributesGetter = attributesGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented
|
||||
* items.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> addAttributesExtractor(
|
||||
AttributesExtractor<? super REQUEST, ? super RESPONSE> attributesExtractor) {
|
||||
additionalExtractors.add(attributesExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setStatusExtractor(
|
||||
Function<
|
||||
SpanStatusExtractor<? super REQUEST, ? super RESPONSE>,
|
||||
? extends SpanStatusExtractor<? super REQUEST, ? super RESPONSE>>
|
||||
statusExtractor) {
|
||||
this.statusExtractorTransformer = statusExtractor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the HTTP request headers that will be captured as span attributes.
|
||||
*
|
||||
* @param requestHeaders A list of HTTP header names.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setCapturedRequestHeaders(
|
||||
List<String> requestHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the HTTP response headers that will be captured as span attributes.
|
||||
*
|
||||
* @param responseHeaders A list of HTTP header names.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setCapturedResponseHeaders(
|
||||
List<String> responseHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the instrumentation to recognize an alternative set of HTTP request methods.
|
||||
*
|
||||
* <p>By default, this instrumentation defines "known" methods as the ones listed in <a
|
||||
* href="https://www.rfc-editor.org/rfc/rfc9110.html#name-methods">RFC9110</a> and the PATCH
|
||||
* method defined in <a href="https://www.rfc-editor.org/rfc/rfc5789.html">RFC5789</a>.
|
||||
*
|
||||
* <p>Note: calling this method <b>overrides</b> 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 DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setKnownMethods(
|
||||
Set<String> knownMethods) {
|
||||
httpAttributesExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpSpanNameExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpServerRouteBuilder.setKnownMethods(knownMethods);
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setHeaderGetter(
|
||||
@Nullable TextMapGetter<REQUEST> headerGetter) {
|
||||
this.headerGetter = headerGetter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the instrumentation to emit experimental HTTP server metrics.
|
||||
*
|
||||
* @param emitExperimentalHttpServerMetrics {@code true} if the experimental HTTP server metrics
|
||||
* are to be emitted.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE>
|
||||
setEmitExperimentalHttpServerMetrics(boolean emitExperimentalHttpServerMetrics) {
|
||||
this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets custom {@link SpanNameExtractor} via transform function. */
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> setSpanNameExtractor(
|
||||
Function<SpanNameExtractor<REQUEST>, ? extends SpanNameExtractor<? super REQUEST>>
|
||||
spanNameExtractorTransformer) {
|
||||
this.spanNameExtractorTransformer = spanNameExtractorTransformer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Instrumenter<REQUEST, RESPONSE> build() {
|
||||
InstrumenterBuilder<REQUEST, RESPONSE> builder = builder();
|
||||
|
||||
if (headerGetter != null) {
|
||||
return builder.buildServerInstrumenter(headerGetter);
|
||||
}
|
||||
return builder.buildInstrumenter(SpanKindExtractor.alwaysServer());
|
||||
}
|
||||
|
||||
private InstrumenterBuilder<REQUEST, RESPONSE> builder() {
|
||||
SpanNameExtractor<? super REQUEST> spanNameExtractor =
|
||||
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());
|
||||
|
||||
InstrumenterBuilder<REQUEST, RESPONSE> builder =
|
||||
Instrumenter.<REQUEST, RESPONSE>builder(
|
||||
openTelemetry, instrumentationName, spanNameExtractor)
|
||||
.setSpanStatusExtractor(
|
||||
statusExtractorTransformer.apply(HttpSpanStatusExtractor.create(attributesGetter)))
|
||||
.addAttributesExtractor(httpAttributesExtractorBuilder.build())
|
||||
.addAttributesExtractors(additionalExtractors)
|
||||
.addContextCustomizer(httpServerRouteBuilder.build())
|
||||
.addOperationMetrics(HttpServerMetrics.get());
|
||||
if (emitExperimentalHttpServerMetrics) {
|
||||
builder
|
||||
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(attributesGetter))
|
||||
.addOperationMetrics(HttpServerExperimentalMetrics.get());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE> configure(CommonConfig config) {
|
||||
set(config::getKnownHttpRequestMethods, this::setKnownMethods);
|
||||
set(config::getServerRequestHeaders, this::setCapturedRequestHeaders);
|
||||
set(config::getServerResponseHeaders, this::setCapturedResponseHeaders);
|
||||
set(
|
||||
config::shouldEmitExperimentalHttpServerTelemetry,
|
||||
this::setEmitExperimentalHttpServerMetrics);
|
||||
return this;
|
||||
}
|
||||
|
||||
private static <T> void set(Supplier<T> supplier, Consumer<T> consumer) {
|
||||
T t = supplier.get();
|
||||
if (t != null) {
|
||||
consumer.accept(t);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,7 +56,7 @@ public final class RestClientBeanPostProcessor implements BeanPostProcessor {
|
|||
|
||||
static ClientHttpRequestInterceptor getInterceptor(
|
||||
OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
return InstrumentationConfigUtil.configureBuilder(
|
||||
return InstrumentationConfigUtil.configureClientBuilder(
|
||||
config,
|
||||
SpringWebTelemetry.builder(openTelemetry),
|
||||
WebTelemetryUtil.getBuilderExtractor())
|
||||
|
|
|
@ -8,7 +8,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.jd
|
|||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.jdbc.datasource.JdbcTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.aop.scope.ScopedProxyUtils;
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.mongodb.MongoClientSettings;
|
|||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.mongo.v3_1.MongoTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
|
|
|
@ -7,7 +7,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.r2
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.r2dbc.v1_0.R2dbcTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import io.r2dbc.spi.ConnectionFactoryOptions;
|
||||
|
|
|
@ -24,7 +24,7 @@ class RestTemplateInstrumentation {
|
|||
RestTemplate restTemplate, OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
|
||||
ClientHttpRequestInterceptor instrumentationInterceptor =
|
||||
InstrumentationConfigUtil.configureBuilder(
|
||||
InstrumentationConfigUtil.configureClientBuilder(
|
||||
config,
|
||||
SpringWebTelemetry.builder(openTelemetry),
|
||||
WebTelemetryUtil.getBuilderExtractor())
|
||||
|
|
|
@ -7,7 +7,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
|
||||
import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -30,14 +30,14 @@ public class SpringWebfluxInstrumentationAutoConfiguration {
|
|||
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
|
||||
@Bean
|
||||
static WebClientBeanPostProcessor otelWebClientBeanPostProcessor(
|
||||
ObjectProvider<OpenTelemetry> openTelemetryProvider) {
|
||||
return new WebClientBeanPostProcessor(openTelemetryProvider);
|
||||
ObjectProvider<OpenTelemetry> openTelemetryProvider,
|
||||
ObjectProvider<ConfigProperties> configPropertiesProvider) {
|
||||
return new WebClientBeanPostProcessor(openTelemetryProvider, configPropertiesProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
WebFilter telemetryFilter(OpenTelemetry openTelemetry) {
|
||||
return SpringWebfluxTelemetry.builder(openTelemetry)
|
||||
.build()
|
||||
WebFilter telemetryFilter(OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
return WebClientBeanPostProcessor.getWebfluxTelemetry(openTelemetry, config)
|
||||
.createWebFilterAndRegisterReactorHook();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.webflux;
|
||||
|
||||
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.internal.SpringWebfluxBuilderUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
@ -19,9 +22,23 @@ import org.springframework.web.reactive.function.client.WebClient;
|
|||
final class WebClientBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final ObjectProvider<OpenTelemetry> openTelemetryProvider;
|
||||
private final ObjectProvider<ConfigProperties> configPropertiesProvider;
|
||||
|
||||
WebClientBeanPostProcessor(ObjectProvider<OpenTelemetry> openTelemetryProvider) {
|
||||
WebClientBeanPostProcessor(
|
||||
ObjectProvider<OpenTelemetry> openTelemetryProvider,
|
||||
ObjectProvider<ConfigProperties> configPropertiesProvider) {
|
||||
this.openTelemetryProvider = openTelemetryProvider;
|
||||
this.configPropertiesProvider = configPropertiesProvider;
|
||||
}
|
||||
|
||||
static SpringWebfluxTelemetry getWebfluxTelemetry(
|
||||
OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
return InstrumentationConfigUtil.configureClientAndServerBuilder(
|
||||
config,
|
||||
SpringWebfluxTelemetry.builder(openTelemetry),
|
||||
SpringWebfluxBuilderUtil.getClientBuilderExtractor(),
|
||||
SpringWebfluxBuilderUtil.getServerBuilderExtractor())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,7 +55,8 @@ final class WebClientBeanPostProcessor implements BeanPostProcessor {
|
|||
|
||||
private WebClient.Builder wrapBuilder(WebClient.Builder webClientBuilder) {
|
||||
SpringWebfluxTelemetry instrumentation =
|
||||
SpringWebfluxTelemetry.create(openTelemetryProvider.getObject());
|
||||
getWebfluxTelemetry(
|
||||
openTelemetryProvider.getObject(), configPropertiesProvider.getObject());
|
||||
return webClientBuilder.filters(instrumentation::addClientTracingFilter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal.SpringMvcBuilderUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import javax.servlet.Filter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -22,7 +25,12 @@ import org.springframework.web.servlet.DispatcherServlet;
|
|||
public class SpringWebMvc5InstrumentationAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
Filter otelWebMvcFilter(OpenTelemetry openTelemetry) {
|
||||
return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter();
|
||||
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
return InstrumentationConfigUtil.configureServerBuilder(
|
||||
config,
|
||||
SpringWebMvcTelemetry.builder(openTelemetry),
|
||||
SpringMvcBuilderUtil.getBuilderExtractor())
|
||||
.build()
|
||||
.createServletFilter();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation;
|
||||
import io.opentelemetry.instrumentation.spring.autoconfigure.internal.properties.InstrumentationConfigUtil;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetry;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal.SpringMvcBuilderUtil;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import jakarta.servlet.Filter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -22,7 +25,12 @@ import org.springframework.web.servlet.DispatcherServlet;
|
|||
public class SpringWebMvc6InstrumentationAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
Filter otelWebMvcFilter(OpenTelemetry openTelemetry) {
|
||||
return SpringWebMvcTelemetry.create(openTelemetry).createServletFilter();
|
||||
Filter otelWebMvcFilter(OpenTelemetry openTelemetry, ConfigProperties config) {
|
||||
return InstrumentationConfigUtil.configureServerBuilder(
|
||||
config,
|
||||
SpringWebMvcTelemetry.builder(openTelemetry),
|
||||
SpringMvcBuilderUtil.getBuilderExtractor())
|
||||
.build()
|
||||
.createServletFilter();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.spring.autoconfigure.internal;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public class InstrumentationConfigUtil {
|
||||
private InstrumentationConfigUtil() {}
|
||||
|
||||
public static boolean isStatementSanitizationEnabled(ConfigProperties config, String key) {
|
||||
return config.getBoolean(
|
||||
key, config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true));
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.internal.propertie
|
|||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import java.util.function.Function;
|
||||
|
@ -15,15 +16,48 @@ import java.util.function.Function;
|
|||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public class InstrumentationConfigUtil {
|
||||
public final class InstrumentationConfigUtil {
|
||||
private InstrumentationConfigUtil() {}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public static <T, REQUEST, RESPONSE> T configureBuilder(
|
||||
public static <T, CLIENTREQUEST, CLIENTRESPONSE, SERVERREQUEST, SERVERRESPONSE>
|
||||
T configureClientAndServerBuilder(
|
||||
ConfigProperties config,
|
||||
T builder,
|
||||
Function<T, DefaultHttpClientInstrumenterBuilder<CLIENTREQUEST, CLIENTRESPONSE>>
|
||||
getClientBuilder,
|
||||
Function<T, DefaultHttpServerInstrumenterBuilder<SERVERREQUEST, SERVERRESPONSE>>
|
||||
getServerBuilder) {
|
||||
CommonConfig commonConfig = getConfig(config);
|
||||
getClientBuilder.apply(builder).configure(commonConfig);
|
||||
getServerBuilder.apply(builder).configure(commonConfig);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public static <T, REQUEST, RESPONSE> T configureClientBuilder(
|
||||
ConfigProperties config,
|
||||
T builder,
|
||||
Function<T, DefaultHttpClientInstrumenterBuilder<REQUEST, RESPONSE>> getBuilder) {
|
||||
getBuilder.apply(builder).configure(new CommonConfig(new ConfigPropertiesBridge(config)));
|
||||
getBuilder.apply(builder).configure(getConfig(config));
|
||||
return builder;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public static <T, REQUEST, RESPONSE> T configureServerBuilder(
|
||||
ConfigProperties config,
|
||||
T builder,
|
||||
Function<T, DefaultHttpServerInstrumenterBuilder<REQUEST, RESPONSE>> getBuilder) {
|
||||
getBuilder.apply(builder).configure(getConfig(config));
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static CommonConfig getConfig(ConfigProperties config) {
|
||||
return new CommonConfig(new ConfigPropertiesBridge(config));
|
||||
}
|
||||
|
||||
public static boolean isStatementSanitizationEnabled(ConfigProperties config, String key) {
|
||||
return config.getBoolean(
|
||||
key, config.getBoolean("otel.instrumentation.common.db-statement-sanitizer.enabled", true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -312,6 +312,22 @@
|
|||
"description": "Configures the instrumentation to recognize an alternative set of HTTP request methods. All other methods will be treated as <code>_OTHER</code>.",
|
||||
"defaultValue": "CONNECT,DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,TRACE"
|
||||
},
|
||||
{
|
||||
"name": "otel.instrumentation.http.server.capture-request-headers",
|
||||
"type": "java.util.List<java.lang.String>",
|
||||
"description": "List of HTTP request headers to capture in HTTP servers."
|
||||
},
|
||||
{
|
||||
"name": "otel.instrumentation.http.server.capture-response-headers",
|
||||
"type": "java.util.List<java.lang.String>",
|
||||
"description": "List of HTTP response headers to capture in HTTP servers."
|
||||
},
|
||||
{
|
||||
"name": "otel.instrumentation.http.server.emit-experimental-telemetry",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable the capture of experimental HTTP server telemetry. Add the <code>http.request.body.size</code> and <code>http.response.body.size</code> attributes to spans, and record the <code>http.server.request.body.size</code> and <code>http.server.response.body.size</code> metrics.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "otel.instrumentation.jdbc.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
|
|
@ -8,6 +8,9 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import java.util.Collections;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
@ -17,6 +20,9 @@ class SpringWebfluxInstrumentationAutoConfigurationTest {
|
|||
private final ApplicationContextRunner contextRunner =
|
||||
new ApplicationContextRunner()
|
||||
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
|
||||
.withBean(
|
||||
ConfigProperties.class,
|
||||
() -> DefaultConfigProperties.createFromMap(Collections.emptyMap()))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SpringWebfluxInstrumentationAutoConfiguration.class));
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ package io.opentelemetry.instrumentation.spring.autoconfigure.instrumentation.we
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import java.util.Collections;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
|
@ -20,6 +23,8 @@ class WebClientBeanPostProcessorTest {
|
|||
|
||||
static {
|
||||
beanFactory.registerSingleton("openTelemetry", OpenTelemetry.noop());
|
||||
beanFactory.registerSingleton(
|
||||
"configProperties", DefaultConfigProperties.createFromMap(Collections.emptyMap()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -27,7 +32,9 @@ class WebClientBeanPostProcessorTest {
|
|||
"when processed bean is NOT of type WebClient or WebClientBuilder should return Object")
|
||||
void returnsObject() {
|
||||
BeanPostProcessor underTest =
|
||||
new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class));
|
||||
new WebClientBeanPostProcessor(
|
||||
beanFactory.getBeanProvider(OpenTelemetry.class),
|
||||
beanFactory.getBeanProvider(ConfigProperties.class));
|
||||
|
||||
assertThat(underTest.postProcessAfterInitialization(new Object(), "testObject"))
|
||||
.isExactlyInstanceOf(Object.class);
|
||||
|
@ -37,7 +44,9 @@ class WebClientBeanPostProcessorTest {
|
|||
@DisplayName("when processed bean is of type WebClient should return WebClient")
|
||||
void returnsWebClient() {
|
||||
BeanPostProcessor underTest =
|
||||
new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class));
|
||||
new WebClientBeanPostProcessor(
|
||||
beanFactory.getBeanProvider(OpenTelemetry.class),
|
||||
beanFactory.getBeanProvider(ConfigProperties.class));
|
||||
|
||||
assertThat(underTest.postProcessAfterInitialization(WebClient.create(), "testWebClient"))
|
||||
.isInstanceOf(WebClient.class);
|
||||
|
@ -47,7 +56,9 @@ class WebClientBeanPostProcessorTest {
|
|||
@DisplayName("when processed bean is of type WebClientBuilder should return WebClientBuilder")
|
||||
void returnsWebClientBuilder() {
|
||||
BeanPostProcessor underTest =
|
||||
new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class));
|
||||
new WebClientBeanPostProcessor(
|
||||
beanFactory.getBeanProvider(OpenTelemetry.class),
|
||||
beanFactory.getBeanProvider(ConfigProperties.class));
|
||||
|
||||
assertThat(
|
||||
underTest.postProcessAfterInitialization(WebClient.builder(), "testWebClientBuilder"))
|
||||
|
@ -58,7 +69,9 @@ class WebClientBeanPostProcessorTest {
|
|||
@DisplayName("when processed bean is of type WebClient should add exchange filter to WebClient")
|
||||
void addsExchangeFilterWebClient() {
|
||||
BeanPostProcessor underTest =
|
||||
new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class));
|
||||
new WebClientBeanPostProcessor(
|
||||
beanFactory.getBeanProvider(OpenTelemetry.class),
|
||||
beanFactory.getBeanProvider(ConfigProperties.class));
|
||||
|
||||
WebClient webClient = WebClient.create();
|
||||
Object processedWebClient =
|
||||
|
@ -81,7 +94,9 @@ class WebClientBeanPostProcessorTest {
|
|||
"when processed bean is of type WebClientBuilder should add ONE exchange filter to WebClientBuilder")
|
||||
void addsExchangeFilterWebClientBuilder() {
|
||||
BeanPostProcessor underTest =
|
||||
new WebClientBeanPostProcessor(beanFactory.getBeanProvider(OpenTelemetry.class));
|
||||
new WebClientBeanPostProcessor(
|
||||
beanFactory.getBeanProvider(OpenTelemetry.class),
|
||||
beanFactory.getBeanProvider(ConfigProperties.class));
|
||||
|
||||
WebClient.Builder webClientBuilder = WebClient.builder();
|
||||
underTest.postProcessAfterInitialization(webClientBuilder, "testWebClientBuilder");
|
||||
|
|
|
@ -9,6 +9,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.junit.jupiter.api.Assumptions.assumeFalse;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import java.util.Collections;
|
||||
import javax.servlet.Filter;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -20,6 +23,9 @@ class SpringWebMvcInstrumentation5AutoConfigurationTest {
|
|||
private final ApplicationContextRunner contextRunner =
|
||||
new ApplicationContextRunner()
|
||||
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
|
||||
.withBean(
|
||||
ConfigProperties.class,
|
||||
() -> DefaultConfigProperties.createFromMap(Collections.emptyMap()))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SpringWebMvc5InstrumentationAutoConfiguration.class));
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import jakarta.servlet.Filter;
|
||||
import java.util.Collections;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
|
@ -20,6 +23,9 @@ class SpringWebMvcInstrumentation6AutoConfigurationTest {
|
|||
private final ApplicationContextRunner contextRunner =
|
||||
new ApplicationContextRunner()
|
||||
.withBean(OpenTelemetry.class, OpenTelemetry::noop)
|
||||
.withBean(
|
||||
ConfigProperties.class,
|
||||
() -> DefaultConfigProperties.createFromMap(Collections.emptyMap()))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SpringWebMvc6InstrumentationAutoConfiguration.class));
|
||||
|
||||
|
|
|
@ -5,17 +5,12 @@
|
|||
|
||||
package io.opentelemetry.javaagent.instrumentation.spring.webflux.v5_0.client;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.ClientInstrumenterFactory;
|
||||
import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientHttpAttributesGetter;
|
||||
import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.WebClientTracingFilter;
|
||||
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
|
||||
import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
|
@ -23,20 +18,8 @@ import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
|||
public final class WebClientHelper {
|
||||
|
||||
private static final Instrumenter<ClientRequest, ClientResponse> instrumenter =
|
||||
ClientInstrumenterFactory.create(
|
||||
GlobalOpenTelemetry.get(),
|
||||
builder ->
|
||||
builder
|
||||
.setCapturedRequestHeaders(AgentCommonConfig.get().getClientRequestHeaders())
|
||||
.setCapturedResponseHeaders(AgentCommonConfig.get().getClientResponseHeaders())
|
||||
.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()),
|
||||
builder -> builder.setKnownMethods(AgentCommonConfig.get().getKnownHttpRequestMethods()),
|
||||
Function.identity(),
|
||||
singletonList(
|
||||
HttpClientPeerServiceAttributesExtractor.create(
|
||||
WebClientHttpAttributesGetter.INSTANCE,
|
||||
AgentCommonConfig.get().getPeerServiceResolver())),
|
||||
AgentCommonConfig.get().shouldEmitExperimentalHttpClientTelemetry());
|
||||
JavaagentHttpClientInstrumenters.create(
|
||||
"io.opentelemetry.spring-webflux-5.0", WebClientHttpAttributesGetter.INSTANCE);
|
||||
|
||||
public static void addFilter(List<ExchangeFilterFunction> exchangeFilterFunctions) {
|
||||
for (ExchangeFilterFunction filterFunction : exchangeFilterFunctions) {
|
||||
|
|
|
@ -7,26 +7,16 @@ 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.semconv.http.HttpExperimentalAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
|
||||
import io.opentelemetry.instrumentation.spring.webflux.v5_3.internal.ClientInstrumenterFactory;
|
||||
import java.util.ArrayList;
|
||||
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.Consumer;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
|
@ -36,38 +26,25 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
public final class SpringWebfluxTelemetryBuilder {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3";
|
||||
|
||||
private final OpenTelemetry openTelemetry;
|
||||
private final DefaultHttpClientInstrumenterBuilder<ClientRequest, ClientResponse> clientBuilder;
|
||||
private final DefaultHttpServerInstrumenterBuilder<ServerWebExchange, ServerWebExchange>
|
||||
serverBuilder;
|
||||
|
||||
private final List<AttributesExtractor<ClientRequest, ClientResponse>>
|
||||
clientAdditionalExtractors = new ArrayList<>();
|
||||
private final List<AttributesExtractor<ServerWebExchange, ServerWebExchange>>
|
||||
serverAdditionalExtractors = new ArrayList<>();
|
||||
|
||||
private final HttpServerAttributesExtractorBuilder<ServerWebExchange, ServerWebExchange>
|
||||
httpServerAttributesExtractorBuilder =
|
||||
HttpServerAttributesExtractor.builder(WebfluxServerHttpAttributesGetter.INSTANCE);
|
||||
private final HttpSpanNameExtractorBuilder<ServerWebExchange> httpServerSpanNameExtractorBuilder =
|
||||
HttpSpanNameExtractor.builder(WebfluxServerHttpAttributesGetter.INSTANCE);
|
||||
private final HttpServerRouteBuilder<ServerWebExchange> httpServerRouteBuilder =
|
||||
HttpServerRoute.builder(WebfluxServerHttpAttributesGetter.INSTANCE);
|
||||
|
||||
private Function<
|
||||
SpanNameExtractor<ClientRequest>, ? extends SpanNameExtractor<? super ClientRequest>>
|
||||
clientSpanNameExtractorTransformer = Function.identity();
|
||||
private Function<
|
||||
SpanNameExtractor<ServerWebExchange>,
|
||||
? extends SpanNameExtractor<? super ServerWebExchange>>
|
||||
serverSpanNameExtractorTransformer = Function.identity();
|
||||
|
||||
private Consumer<HttpClientAttributesExtractorBuilder<ClientRequest, ClientResponse>>
|
||||
clientExtractorConfigurer = builder -> {};
|
||||
private Consumer<HttpSpanNameExtractorBuilder<ClientRequest>> clientSpanNameExtractorConfigurer =
|
||||
builder -> {};
|
||||
private boolean emitExperimentalHttpClientTelemetry = false;
|
||||
private boolean emitExperimentalHttpServerTelemetry = false;
|
||||
static {
|
||||
SpringWebfluxBuilderUtil.setClientBuilderExtractor(
|
||||
SpringWebfluxTelemetryBuilder::getClientBuilder);
|
||||
SpringWebfluxBuilderUtil.setServerBuilderExtractor(
|
||||
SpringWebfluxTelemetryBuilder::getServerBuilder);
|
||||
}
|
||||
|
||||
SpringWebfluxTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||
this.openTelemetry = openTelemetry;
|
||||
clientBuilder =
|
||||
new DefaultHttpClientInstrumenterBuilder<>(
|
||||
INSTRUMENTATION_NAME, openTelemetry, WebClientHttpAttributesGetter.INSTANCE);
|
||||
serverBuilder =
|
||||
new DefaultHttpServerInstrumenterBuilder<>(
|
||||
INSTRUMENTATION_NAME, openTelemetry, WebfluxServerHttpAttributesGetter.INSTANCE)
|
||||
.setHeaderGetter(WebfluxTextMapGetter.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,7 +54,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder addClientAttributesExtractor(
|
||||
AttributesExtractor<ClientRequest, ClientResponse> attributesExtractor) {
|
||||
clientAdditionalExtractors.add(attributesExtractor);
|
||||
clientBuilder.addAttributeExtractor(attributesExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -89,9 +66,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setCapturedClientRequestHeaders(
|
||||
List<String> requestHeaders) {
|
||||
clientExtractorConfigurer =
|
||||
clientExtractorConfigurer.andThen(
|
||||
builder -> builder.setCapturedRequestHeaders(requestHeaders));
|
||||
clientBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -103,9 +78,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setCapturedClientResponseHeaders(
|
||||
List<String> responseHeaders) {
|
||||
clientExtractorConfigurer =
|
||||
clientExtractorConfigurer.andThen(
|
||||
builder -> builder.setCapturedResponseHeaders(responseHeaders));
|
||||
clientBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -116,7 +89,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder addServerAttributesExtractor(
|
||||
AttributesExtractor<ServerWebExchange, ServerWebExchange> attributesExtractor) {
|
||||
serverAdditionalExtractors.add(attributesExtractor);
|
||||
serverBuilder.addAttributesExtractor(attributesExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -129,7 +102,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setCapturedServerRequestHeaders(
|
||||
List<String> requestHeaders) {
|
||||
httpServerAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
serverBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -142,7 +115,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setCapturedServerResponseHeaders(
|
||||
List<String> responseHeaders) {
|
||||
httpServerAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
serverBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -162,13 +135,8 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
|
||||
clientExtractorConfigurer =
|
||||
clientExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods));
|
||||
clientSpanNameExtractorConfigurer =
|
||||
clientSpanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods));
|
||||
httpServerAttributesExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpServerSpanNameExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpServerRouteBuilder.setKnownMethods(knownMethods);
|
||||
clientBuilder.setKnownMethods(knownMethods);
|
||||
serverBuilder.setKnownMethods(knownMethods);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -181,7 +149,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpClientTelemetry(
|
||||
boolean emitExperimentalHttpClientTelemetry) {
|
||||
this.emitExperimentalHttpClientTelemetry = emitExperimentalHttpClientTelemetry;
|
||||
clientBuilder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientTelemetry);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -194,7 +162,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebfluxTelemetryBuilder setEmitExperimentalHttpServerTelemetry(
|
||||
boolean emitExperimentalHttpServerTelemetry) {
|
||||
this.emitExperimentalHttpServerTelemetry = emitExperimentalHttpServerTelemetry;
|
||||
serverBuilder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerTelemetry);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -203,7 +171,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
public SpringWebfluxTelemetryBuilder setClientSpanNameExtractor(
|
||||
Function<SpanNameExtractor<ClientRequest>, ? extends SpanNameExtractor<? super ClientRequest>>
|
||||
clientSpanNameExtractor) {
|
||||
this.clientSpanNameExtractorTransformer = clientSpanNameExtractor;
|
||||
clientBuilder.setSpanNameExtractor(clientSpanNameExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -214,7 +182,7 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
SpanNameExtractor<ServerWebExchange>,
|
||||
? extends SpanNameExtractor<? super ServerWebExchange>>
|
||||
serverSpanNameExtractor) {
|
||||
this.serverSpanNameExtractorTransformer = serverSpanNameExtractor;
|
||||
serverBuilder.setSpanNameExtractor(serverSpanNameExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -223,40 +191,18 @@ public final class SpringWebfluxTelemetryBuilder {
|
|||
* SpringWebfluxTelemetryBuilder}.
|
||||
*/
|
||||
public SpringWebfluxTelemetry build() {
|
||||
Instrumenter<ClientRequest, ClientResponse> clientInstrumenter =
|
||||
ClientInstrumenterFactory.create(
|
||||
openTelemetry,
|
||||
clientExtractorConfigurer,
|
||||
clientSpanNameExtractorConfigurer,
|
||||
clientSpanNameExtractorTransformer,
|
||||
clientAdditionalExtractors,
|
||||
emitExperimentalHttpClientTelemetry);
|
||||
|
||||
Instrumenter<ServerWebExchange, ServerWebExchange> serverInstrumenter =
|
||||
buildServerInstrumenter();
|
||||
|
||||
return new SpringWebfluxTelemetry(
|
||||
clientInstrumenter, serverInstrumenter, openTelemetry.getPropagators());
|
||||
clientBuilder.build(),
|
||||
serverBuilder.build(),
|
||||
clientBuilder.getOpenTelemetry().getPropagators());
|
||||
}
|
||||
|
||||
private Instrumenter<ServerWebExchange, ServerWebExchange> buildServerInstrumenter() {
|
||||
WebfluxServerHttpAttributesGetter getter = WebfluxServerHttpAttributesGetter.INSTANCE;
|
||||
SpanNameExtractor<? super ServerWebExchange> spanNameExtractor =
|
||||
serverSpanNameExtractorTransformer.apply(httpServerSpanNameExtractorBuilder.build());
|
||||
private DefaultHttpClientInstrumenterBuilder<ClientRequest, ClientResponse> getClientBuilder() {
|
||||
return clientBuilder;
|
||||
}
|
||||
|
||||
InstrumenterBuilder<ServerWebExchange, ServerWebExchange> builder =
|
||||
Instrumenter.<ServerWebExchange, ServerWebExchange>builder(
|
||||
openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor)
|
||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(getter))
|
||||
.addAttributesExtractor(httpServerAttributesExtractorBuilder.build())
|
||||
.addAttributesExtractors(serverAdditionalExtractors)
|
||||
.addContextCustomizer(httpServerRouteBuilder.build())
|
||||
.addOperationMetrics(HttpServerMetrics.get());
|
||||
if (emitExperimentalHttpServerTelemetry) {
|
||||
builder
|
||||
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(getter))
|
||||
.addOperationMetrics(HttpServerExperimentalMetrics.get());
|
||||
}
|
||||
return builder.buildServerInstrumenter(WebfluxTextMapGetter.INSTANCE);
|
||||
private DefaultHttpServerInstrumenterBuilder<ServerWebExchange, ServerWebExchange>
|
||||
getServerBuilder() {
|
||||
return serverBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal;
|
||||
|
||||
import static io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor.alwaysClient;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
// client builder is separate so that it can be used by javaagent instrumentation
|
||||
// which supports 5.0, without triggering the server instrumentation which depends on webflux 5.3
|
||||
public final class ClientInstrumenterFactory {
|
||||
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webflux-5.3";
|
||||
|
||||
public static Instrumenter<ClientRequest, ClientResponse> create(
|
||||
OpenTelemetry openTelemetry,
|
||||
Consumer<HttpClientAttributesExtractorBuilder<ClientRequest, ClientResponse>>
|
||||
extractorConfigurer,
|
||||
Consumer<HttpSpanNameExtractorBuilder<ClientRequest>> spanNameExtractorConfigurer,
|
||||
Function<SpanNameExtractor<ClientRequest>, ? extends SpanNameExtractor<? super ClientRequest>>
|
||||
spanNameExtractorTransformer,
|
||||
List<AttributesExtractor<ClientRequest, ClientResponse>> additionalExtractors,
|
||||
boolean emitExperimentalHttpClientTelemetry) {
|
||||
|
||||
WebClientHttpAttributesGetter httpAttributesGetter = WebClientHttpAttributesGetter.INSTANCE;
|
||||
|
||||
HttpClientAttributesExtractorBuilder<ClientRequest, ClientResponse> extractorBuilder =
|
||||
HttpClientAttributesExtractor.builder(httpAttributesGetter);
|
||||
extractorConfigurer.accept(extractorBuilder);
|
||||
|
||||
HttpSpanNameExtractorBuilder<ClientRequest> httpSpanNameExtractorBuilder =
|
||||
HttpSpanNameExtractor.builder(httpAttributesGetter);
|
||||
spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder);
|
||||
SpanNameExtractor<? super ClientRequest> spanNameExtractor =
|
||||
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());
|
||||
|
||||
InstrumenterBuilder<ClientRequest, ClientResponse> clientBuilder =
|
||||
Instrumenter.<ClientRequest, ClientResponse>builder(
|
||||
openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor)
|
||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
||||
.addAttributesExtractor(extractorBuilder.build())
|
||||
.addAttributesExtractors(additionalExtractors)
|
||||
.addOperationMetrics(HttpClientMetrics.get());
|
||||
|
||||
if (emitExperimentalHttpClientTelemetry) {
|
||||
clientBuilder
|
||||
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
|
||||
.addOperationMetrics(HttpClientExperimentalMetrics.get());
|
||||
}
|
||||
|
||||
// headers are injected elsewhere; ClientRequest is immutable
|
||||
return clientBuilder.buildInstrumenter(alwaysClient());
|
||||
}
|
||||
|
||||
private ClientInstrumenterFactory() {}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.spring.webflux.v5_3.internal;
|
||||
|
||||
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 java.util.function.Function;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class SpringWebfluxBuilderUtil {
|
||||
private SpringWebfluxBuilderUtil() {}
|
||||
|
||||
// allows access to the private field for the spring starter
|
||||
private static Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpClientInstrumenterBuilder<ClientRequest, ClientResponse>>
|
||||
clientBuilderExtractor;
|
||||
|
||||
// allows access to the private field for the spring starter
|
||||
private static Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<ServerWebExchange, ServerWebExchange>>
|
||||
serverBuilderExtractor;
|
||||
|
||||
public static Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<ServerWebExchange, ServerWebExchange>>
|
||||
getServerBuilderExtractor() {
|
||||
return serverBuilderExtractor;
|
||||
}
|
||||
|
||||
public static void setServerBuilderExtractor(
|
||||
Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<ServerWebExchange, ServerWebExchange>>
|
||||
serverBuilderExtractor) {
|
||||
SpringWebfluxBuilderUtil.serverBuilderExtractor = serverBuilderExtractor;
|
||||
}
|
||||
|
||||
public static Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpClientInstrumenterBuilder<ClientRequest, ClientResponse>>
|
||||
getClientBuilderExtractor() {
|
||||
return clientBuilderExtractor;
|
||||
}
|
||||
|
||||
public static void setClientBuilderExtractor(
|
||||
Function<
|
||||
SpringWebfluxTelemetryBuilder,
|
||||
DefaultHttpClientInstrumenterBuilder<ClientRequest, ClientResponse>>
|
||||
clientBuilderExtractor) {
|
||||
SpringWebfluxBuilderUtil.clientBuilderExtractor = clientBuilderExtractor;
|
||||
}
|
||||
}
|
|
@ -7,21 +7,11 @@ package io.opentelemetry.instrumentation.spring.webmvc.v5_3;
|
|||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
|
||||
import java.util.ArrayList;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal.SpringMvcBuilderUtil;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
@ -33,24 +23,18 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webmvc-5.3";
|
||||
|
||||
private final OpenTelemetry openTelemetry;
|
||||
private final List<AttributesExtractor<HttpServletRequest, HttpServletResponse>>
|
||||
additionalExtractors = new ArrayList<>();
|
||||
private final HttpServerAttributesExtractorBuilder<HttpServletRequest, HttpServletResponse>
|
||||
httpAttributesExtractorBuilder =
|
||||
HttpServerAttributesExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private final HttpSpanNameExtractorBuilder<HttpServletRequest> httpSpanNameExtractorBuilder =
|
||||
HttpSpanNameExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private final HttpServerRouteBuilder<HttpServletRequest> httpServerRouteBuilder =
|
||||
HttpServerRoute.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private Function<
|
||||
SpanNameExtractor<HttpServletRequest>,
|
||||
? extends SpanNameExtractor<? super HttpServletRequest>>
|
||||
spanNameExtractorTransformer = Function.identity();
|
||||
private boolean emitExperimentalHttpServerMetrics = false;
|
||||
private final DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>
|
||||
builder;
|
||||
|
||||
static {
|
||||
SpringMvcBuilderUtil.setBuilderExtractor(SpringWebMvcTelemetryBuilder::getBuilder);
|
||||
}
|
||||
|
||||
SpringWebMvcTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||
this.openTelemetry = openTelemetry;
|
||||
builder =
|
||||
new DefaultHttpServerInstrumenterBuilder<>(
|
||||
INSTRUMENTATION_NAME, openTelemetry, SpringWebMvcHttpAttributesGetter.INSTANCE)
|
||||
.setHeaderGetter(JavaxHttpServletRequestGetter.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +44,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder addAttributesExtractor(
|
||||
AttributesExtractor<HttpServletRequest, HttpServletResponse> attributesExtractor) {
|
||||
additionalExtractors.add(attributesExtractor);
|
||||
builder.addAttributesExtractor(attributesExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -71,7 +55,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List<String> requestHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
builder.setCapturedRequestHeaders(requestHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -82,7 +66,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setCapturedResponseHeaders(List<String> responseHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
builder.setCapturedResponseHeaders(responseHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -93,7 +77,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
SpanNameExtractor<HttpServletRequest>,
|
||||
? extends SpanNameExtractor<? super HttpServletRequest>>
|
||||
spanNameExtractor) {
|
||||
this.spanNameExtractorTransformer = spanNameExtractor;
|
||||
builder.setSpanNameExtractor(spanNameExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -112,9 +96,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
|
||||
httpAttributesExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpSpanNameExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpServerRouteBuilder.setKnownMethods(knownMethods);
|
||||
builder.setKnownMethods(knownMethods);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -127,7 +109,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics(
|
||||
boolean emitExperimentalHttpServerMetrics) {
|
||||
this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics;
|
||||
builder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerMetrics);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -136,26 +118,11 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
* SpringWebMvcTelemetryBuilder}.
|
||||
*/
|
||||
public SpringWebMvcTelemetry build() {
|
||||
SpringWebMvcHttpAttributesGetter httpAttributesGetter =
|
||||
SpringWebMvcHttpAttributesGetter.INSTANCE;
|
||||
SpanNameExtractor<? super HttpServletRequest> spanNameExtractor =
|
||||
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());
|
||||
return new SpringWebMvcTelemetry(builder.build());
|
||||
}
|
||||
|
||||
InstrumenterBuilder<HttpServletRequest, HttpServletResponse> builder =
|
||||
Instrumenter.<HttpServletRequest, HttpServletResponse>builder(
|
||||
openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor)
|
||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
||||
.addAttributesExtractor(httpAttributesExtractorBuilder.build())
|
||||
.addAttributesExtractors(additionalExtractors)
|
||||
.addContextCustomizer(httpServerRouteBuilder.build())
|
||||
.addOperationMetrics(HttpServerMetrics.get());
|
||||
if (emitExperimentalHttpServerMetrics) {
|
||||
builder
|
||||
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
|
||||
.addOperationMetrics(HttpServerExperimentalMetrics.get());
|
||||
}
|
||||
|
||||
return new SpringWebMvcTelemetry(
|
||||
builder.buildServerInstrumenter(JavaxHttpServletRequestGetter.INSTANCE));
|
||||
public DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>
|
||||
getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.spring.webmvc.v5_3.internal;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v5_3.SpringWebMvcTelemetryBuilder;
|
||||
import java.util.function.Function;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class SpringMvcBuilderUtil {
|
||||
private SpringMvcBuilderUtil() {}
|
||||
|
||||
// allows access to the private field for the spring starter
|
||||
private static Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
builderExtractor;
|
||||
|
||||
public static Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
getBuilderExtractor() {
|
||||
return builderExtractor;
|
||||
}
|
||||
|
||||
public static void setBuilderExtractor(
|
||||
Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
builderExtractor) {
|
||||
SpringMvcBuilderUtil.builderExtractor = builderExtractor;
|
||||
}
|
||||
}
|
|
@ -7,23 +7,13 @@ package io.opentelemetry.instrumentation.spring.webmvc.v6_0;
|
|||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpServerExperimentalMetrics;
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerMetrics;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRoute;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerRouteBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder;
|
||||
import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal.SpringMvcBuilderUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
@ -32,25 +22,18 @@ import java.util.function.Function;
|
|||
public final class SpringWebMvcTelemetryBuilder {
|
||||
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.spring-webmvc-6.0";
|
||||
private final DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>
|
||||
builder;
|
||||
|
||||
private final OpenTelemetry openTelemetry;
|
||||
private final List<AttributesExtractor<HttpServletRequest, HttpServletResponse>>
|
||||
additionalExtractors = new ArrayList<>();
|
||||
private final HttpServerAttributesExtractorBuilder<HttpServletRequest, HttpServletResponse>
|
||||
httpAttributesExtractorBuilder =
|
||||
HttpServerAttributesExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private final HttpSpanNameExtractorBuilder<HttpServletRequest> httpSpanNameExtractorBuilder =
|
||||
HttpSpanNameExtractor.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private final HttpServerRouteBuilder<HttpServletRequest> httpServerRouteBuilder =
|
||||
HttpServerRoute.builder(SpringWebMvcHttpAttributesGetter.INSTANCE);
|
||||
private Function<
|
||||
SpanNameExtractor<HttpServletRequest>,
|
||||
? extends SpanNameExtractor<? super HttpServletRequest>>
|
||||
spanNameExtractorTransformer = Function.identity();
|
||||
private boolean emitExperimentalHttpServerMetrics = false;
|
||||
static {
|
||||
SpringMvcBuilderUtil.setBuilderExtractor(SpringWebMvcTelemetryBuilder::getBuilder);
|
||||
}
|
||||
|
||||
SpringWebMvcTelemetryBuilder(OpenTelemetry openTelemetry) {
|
||||
this.openTelemetry = openTelemetry;
|
||||
builder =
|
||||
new DefaultHttpServerInstrumenterBuilder<>(
|
||||
INSTRUMENTATION_NAME, openTelemetry, SpringWebMvcHttpAttributesGetter.INSTANCE)
|
||||
.setHeaderGetter(JakartaHttpServletRequestGetter.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +43,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder addAttributesExtractor(
|
||||
AttributesExtractor<HttpServletRequest, HttpServletResponse> attributesExtractor) {
|
||||
additionalExtractors.add(attributesExtractor);
|
||||
builder.addAttributesExtractor(attributesExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -71,7 +54,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setCapturedRequestHeaders(List<String> requestHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedRequestHeaders(requestHeaders);
|
||||
builder.setCapturedRequestHeaders(requestHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -82,7 +65,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setCapturedResponseHeaders(List<String> responseHeaders) {
|
||||
httpAttributesExtractorBuilder.setCapturedResponseHeaders(responseHeaders);
|
||||
builder.setCapturedResponseHeaders(responseHeaders);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -93,7 +76,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
SpanNameExtractor<HttpServletRequest>,
|
||||
? extends SpanNameExtractor<? super HttpServletRequest>>
|
||||
spanNameExtractor) {
|
||||
this.spanNameExtractorTransformer = spanNameExtractor;
|
||||
builder.setSpanNameExtractor(spanNameExtractor);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -112,9 +95,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
|
||||
httpAttributesExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpSpanNameExtractorBuilder.setKnownMethods(knownMethods);
|
||||
httpServerRouteBuilder.setKnownMethods(knownMethods);
|
||||
builder.setKnownMethods(knownMethods);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -127,7 +108,7 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
@CanIgnoreReturnValue
|
||||
public SpringWebMvcTelemetryBuilder setEmitExperimentalHttpServerMetrics(
|
||||
boolean emitExperimentalHttpServerMetrics) {
|
||||
this.emitExperimentalHttpServerMetrics = emitExperimentalHttpServerMetrics;
|
||||
builder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerMetrics);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -136,26 +117,11 @@ public final class SpringWebMvcTelemetryBuilder {
|
|||
* SpringWebMvcTelemetryBuilder}.
|
||||
*/
|
||||
public SpringWebMvcTelemetry build() {
|
||||
SpringWebMvcHttpAttributesGetter httpAttributesGetter =
|
||||
SpringWebMvcHttpAttributesGetter.INSTANCE;
|
||||
SpanNameExtractor<? super HttpServletRequest> spanNameExtractor =
|
||||
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());
|
||||
return new SpringWebMvcTelemetry(builder.build());
|
||||
}
|
||||
|
||||
InstrumenterBuilder<HttpServletRequest, HttpServletResponse> builder =
|
||||
Instrumenter.<HttpServletRequest, HttpServletResponse>builder(
|
||||
openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor)
|
||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
||||
.addAttributesExtractor(httpAttributesExtractorBuilder.build())
|
||||
.addAttributesExtractors(additionalExtractors)
|
||||
.addContextCustomizer(httpServerRouteBuilder.build())
|
||||
.addOperationMetrics(HttpServerMetrics.get());
|
||||
if (emitExperimentalHttpServerMetrics) {
|
||||
builder
|
||||
.addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter))
|
||||
.addOperationMetrics(HttpServerExperimentalMetrics.get());
|
||||
}
|
||||
|
||||
return new SpringWebMvcTelemetry(
|
||||
builder.buildServerInstrumenter(JakartaHttpServletRequestGetter.INSTANCE));
|
||||
public DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>
|
||||
getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.spring.webmvc.v6_0.internal;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
|
||||
import io.opentelemetry.instrumentation.spring.webmvc.v6_0.SpringWebMvcTelemetryBuilder;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class SpringMvcBuilderUtil {
|
||||
private SpringMvcBuilderUtil() {}
|
||||
|
||||
// allows access to the private field for the spring starter
|
||||
private static Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
builderExtractor;
|
||||
|
||||
public static Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
getBuilderExtractor() {
|
||||
return builderExtractor;
|
||||
}
|
||||
|
||||
public static void setBuilderExtractor(
|
||||
Function<
|
||||
SpringWebMvcTelemetryBuilder,
|
||||
DefaultHttpServerInstrumenterBuilder<HttpServletRequest, HttpServletResponse>>
|
||||
builderExtractor) {
|
||||
SpringMvcBuilderUtil.builderExtractor = builderExtractor;
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest {
|
|||
|
||||
private static void assertClient(TraceAssert traceAssert) {
|
||||
traceAssert.hasSpansSatisfyingExactly(
|
||||
span -> AbstractOtelSpringStarterSmokeTest.assertClientSpan(span, "/ping"),
|
||||
span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"),
|
||||
span -> span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"),
|
||||
span -> withSpanAssert(span));
|
||||
}
|
||||
|
|
|
@ -21,20 +21,17 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
|||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import io.opentelemetry.sdk.logs.data.LogRecordData;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
|
||||
import io.opentelemetry.semconv.ClientAttributes;
|
||||
import io.opentelemetry.semconv.HttpAttributes;
|
||||
import io.opentelemetry.semconv.ServerAttributes;
|
||||
import io.opentelemetry.semconv.UrlAttributes;
|
||||
import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes;
|
||||
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
|
||||
import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes;
|
||||
import io.opentelemetry.semconv.incubating.ServiceIncubatingAttributes;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.assertj.core.api.AbstractCharSequenceAssert;
|
||||
import org.assertj.core.api.AbstractIterableAssert;
|
||||
import org.assertj.core.api.AbstractLongAssert;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
|
@ -155,8 +152,8 @@ class AbstractOtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest
|
|||
ServerAttributes.SERVER_PORT,
|
||||
integerAssert -> integerAssert.isNotZero())),
|
||||
serverSpan ->
|
||||
serverSpan
|
||||
.hasKind(SpanKind.SERVER)
|
||||
HttpSpanDataAssert.create(serverSpan)
|
||||
.assertServerGetRequest("/ping")
|
||||
.hasResourceSatisfying(
|
||||
r ->
|
||||
r.hasAttribute(
|
||||
|
@ -235,18 +232,9 @@ class AbstractOtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest
|
|||
testing.waitAndAssertTraces(
|
||||
traceAssert ->
|
||||
traceAssert.hasSpansSatisfyingExactly(
|
||||
span -> assertClientSpan(span, "/ping"),
|
||||
span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/ping"),
|
||||
span ->
|
||||
span.hasKind(SpanKind.SERVER).hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"),
|
||||
span -> withSpanAssert(span)));
|
||||
}
|
||||
|
||||
public static void assertClientSpan(SpanDataAssert span, String path) {
|
||||
span.hasKind(SpanKind.CLIENT)
|
||||
.hasAttributesSatisfying(
|
||||
satisfies(UrlAttributes.URL_FULL, a -> a.endsWith(path)),
|
||||
// this attribute is set by the experimental http instrumentation
|
||||
satisfies(
|
||||
HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE, AbstractLongAssert::isPositive));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ otel:
|
|||
http:
|
||||
client:
|
||||
emit-experimental-telemetry: true
|
||||
server:
|
||||
emit-experimental-telemetry: true
|
||||
propagators:
|
||||
- b3
|
||||
resource:
|
||||
|
|
|
@ -8,8 +8,6 @@ package io.opentelemetry.spring.smoketest;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.trace.SpanKind;
|
||||
import io.opentelemetry.semconv.HttpAttributes;
|
||||
import io.opentelemetry.semconv.UrlAttributes;
|
||||
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -52,17 +50,8 @@ public class AbstractOtelReactiveSpringStarterSmokeTest extends AbstractSpringSt
|
|||
trace.hasSpansSatisfyingExactly(span -> span.hasName("CREATE TABLE testdb.player")),
|
||||
trace ->
|
||||
trace.hasSpansSatisfyingExactly(
|
||||
span ->
|
||||
span.hasKind(SpanKind.CLIENT)
|
||||
.hasName("GET")
|
||||
.hasAttributesSatisfying(
|
||||
a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/webflux")),
|
||||
span ->
|
||||
span.hasKind(SpanKind.SERVER)
|
||||
.hasName("GET /webflux")
|
||||
.hasAttribute(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
|
||||
.hasAttribute(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L)
|
||||
.hasAttribute(HttpAttributes.HTTP_ROUTE, "/webflux"),
|
||||
span -> HttpSpanDataAssert.create(span).assertClientGetRequest("/webflux"),
|
||||
span -> HttpSpanDataAssert.create(span).assertServerGetRequest("/webflux"),
|
||||
span ->
|
||||
span.hasKind(SpanKind.CLIENT)
|
||||
.satisfies(
|
||||
|
|
|
@ -3,6 +3,11 @@ otel:
|
|||
common:
|
||||
db-statement-sanitizer:
|
||||
enabled: false
|
||||
http:
|
||||
client:
|
||||
emit-experimental-telemetry: true
|
||||
server:
|
||||
emit-experimental-telemetry: true
|
||||
|
||||
spring:
|
||||
r2dbc:
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.spring.smoketest;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
|
||||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.trace.SpanKind;
|
||||
import io.opentelemetry.sdk.testing.assertj.ResourceAssert;
|
||||
import io.opentelemetry.sdk.testing.assertj.SpanDataAssert;
|
||||
import io.opentelemetry.semconv.HttpAttributes;
|
||||
import io.opentelemetry.semconv.UrlAttributes;
|
||||
import io.opentelemetry.semconv.incubating.HttpIncubatingAttributes;
|
||||
import java.util.function.Consumer;
|
||||
import org.assertj.core.api.AbstractLongAssert;
|
||||
|
||||
public final class HttpSpanDataAssert {
|
||||
|
||||
private final SpanDataAssert span;
|
||||
|
||||
private HttpSpanDataAssert(SpanDataAssert span) {
|
||||
this.span = span;
|
||||
}
|
||||
|
||||
public static HttpSpanDataAssert create(SpanDataAssert serverSpan) {
|
||||
return new HttpSpanDataAssert(serverSpan);
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public HttpSpanDataAssert assertClientGetRequest(String path) {
|
||||
span.hasKind(SpanKind.CLIENT)
|
||||
.hasAttributesSatisfying(
|
||||
satisfies(UrlAttributes.URL_FULL, a -> a.endsWith(path)),
|
||||
// this attribute is set by the experimental http instrumentation
|
||||
satisfies(
|
||||
HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE,
|
||||
AbstractLongAssert::isNotNegative));
|
||||
return this;
|
||||
}
|
||||
|
||||
@CanIgnoreReturnValue
|
||||
public HttpSpanDataAssert assertServerGetRequest(String route) {
|
||||
span.hasKind(SpanKind.SERVER)
|
||||
.hasAttributesSatisfying(
|
||||
equalTo(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
|
||||
equalTo(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 200L),
|
||||
equalTo(HttpAttributes.HTTP_ROUTE, route),
|
||||
// this attribute is set by the experimental http instrumentation
|
||||
satisfies(
|
||||
HttpIncubatingAttributes.HTTP_RESPONSE_BODY_SIZE,
|
||||
AbstractLongAssert::isNotNegative));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanDataAssert hasResourceSatisfying(Consumer<ResourceAssert> resource) {
|
||||
return span.hasResourceSatisfying(resource);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue