Add builders for setting optional attributes on HTTP extractors (#5347)

* Add builders for setting optional attributes on HTTP extractors

* errorprone

* fix compilation failure
This commit is contained in:
Mateusz Rzeszutek 2022-03-08 17:21:14 +01:00 committed by GitHub
parent d80b6f54fd
commit 4a98dae431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 166 additions and 35 deletions

View File

@ -43,8 +43,9 @@ public class InstrumenterBenchmark {
"benchmark",
HttpSpanNameExtractor.create(ConstantHttpAttributesGetter.INSTANCE))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(
ConstantHttpAttributesGetter.INSTANCE, CapturedHttpHeaders.empty()))
HttpClientAttributesExtractor.builder(ConstantHttpAttributesGetter.INSTANCE)
.captureHttpHeaders(CapturedHttpHeaders.empty())
.build())
.addAttributesExtractor(
NetServerAttributesExtractor.create(new ConstantNetAttributesGetter()))
.newInstrumenter();

View File

@ -7,7 +7,6 @@ package io.opentelemetry.instrumentation.api.instrumenter.http;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import javax.annotation.Nullable;
@ -27,23 +26,33 @@ public final class HttpClientAttributesExtractor<REQUEST, RESPONSE>
/** Creates the HTTP client attributes extractor with default configuration. */
public static <REQUEST, RESPONSE> HttpClientAttributesExtractor<REQUEST, RESPONSE> create(
HttpClientAttributesGetter<REQUEST, RESPONSE> getter) {
return create(getter, CapturedHttpHeaders.client(Config.get()));
return builder(getter).build();
}
// TODO: there should be a builder for all optional attributes
/**
* Creates the HTTP client attributes extractor.
*
* @param capturedHttpHeaders A configuration object specifying which HTTP request and response
* headers should be captured as span attributes.
* @deprecated Use {@link #builder(HttpClientAttributesGetter)} instead.
*/
@Deprecated
public static <REQUEST, RESPONSE> HttpClientAttributesExtractor<REQUEST, RESPONSE> create(
HttpClientAttributesGetter<REQUEST, RESPONSE> getter,
CapturedHttpHeaders capturedHttpHeaders) {
return new HttpClientAttributesExtractor<>(getter, capturedHttpHeaders);
return builder(getter).captureHttpHeaders(capturedHttpHeaders).build();
}
private HttpClientAttributesExtractor(
/**
* Returns a new {@link HttpClientAttributesExtractorBuilder} that can be used to configure the
* HTTP client attributes extractor.
*/
public static <REQUEST, RESPONSE> HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> builder(
HttpClientAttributesGetter<REQUEST, RESPONSE> getter) {
return new HttpClientAttributesExtractorBuilder<>(getter);
}
HttpClientAttributesExtractor(
HttpClientAttributesGetter<REQUEST, RESPONSE> getter,
CapturedHttpHeaders capturedHttpHeaders) {
super(getter, capturedHttpHeaders);

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.http;
import io.opentelemetry.instrumentation.api.config.Config;
/** A builder of {@link HttpClientAttributesExtractor}. */
public final class HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
final HttpClientAttributesGetter<REQUEST, RESPONSE> getter;
CapturedHttpHeaders capturedHttpHeaders = CapturedHttpHeaders.client(Config.get());
HttpClientAttributesExtractorBuilder(HttpClientAttributesGetter<REQUEST, RESPONSE> getter) {
this.getter = getter;
}
/**
* Configures the HTTP headers that will be captured as span attributes.
*
* @param capturedHttpHeaders A configuration object specifying which HTTP request and response
* headers should be captured as span attributes.
*/
public HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> captureHttpHeaders(
CapturedHttpHeaders capturedHttpHeaders) {
this.capturedHttpHeaders = capturedHttpHeaders;
return this;
}
/**
* Returns a new {@link HttpClientAttributesExtractor} with the settings of this {@link
* HttpClientAttributesExtractorBuilder}.
*/
public HttpClientAttributesExtractor<REQUEST, RESPONSE> build() {
return new HttpClientAttributesExtractor<>(getter, capturedHttpHeaders);
}
}

View File

@ -12,7 +12,6 @@ import static io.opentelemetry.instrumentation.api.instrumenter.http.ForwardedHe
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.config.Config;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.function.Function;
import javax.annotation.Nullable;
@ -33,25 +32,40 @@ public final class HttpServerAttributesExtractor<REQUEST, RESPONSE>
/** Creates the HTTP server attributes extractor with default configuration. */
public static <REQUEST, RESPONSE> HttpServerAttributesExtractor<REQUEST, RESPONSE> create(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
return create(getter, CapturedHttpHeaders.server(Config.get()));
return builder(getter).build();
}
// TODO: there should be a builder for all optional attributes
/**
* Creates the HTTP server attributes extractor.
*
* @param capturedHttpHeaders A configuration object specifying which HTTP request and response
* headers should be captured as span attributes.
* @deprecated Use {@link #builder(HttpServerAttributesGetter)} instead.
*/
@Deprecated
public static <REQUEST, RESPONSE> HttpServerAttributesExtractor<REQUEST, RESPONSE> create(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter,
CapturedHttpHeaders capturedHttpHeaders) {
return new HttpServerAttributesExtractor<>(
getter, capturedHttpHeaders, HttpRouteHolder::getRoute);
return builder(getter).captureHttpHeaders(capturedHttpHeaders).build();
}
/**
* Returns a new {@link HttpServerAttributesExtractorBuilder} that can be used to configure the
* HTTP client attributes extractor.
*/
public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> builder(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
return new HttpServerAttributesExtractorBuilder<>(getter);
}
private final Function<Context, String> httpRouteHolderGetter;
HttpServerAttributesExtractor(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter,
CapturedHttpHeaders capturedHttpHeaders) {
this(getter, capturedHttpHeaders, HttpRouteHolder::getRoute);
}
// visible for tests
HttpServerAttributesExtractor(
HttpServerAttributesGetter<REQUEST, RESPONSE> getter,

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.http;
import io.opentelemetry.instrumentation.api.config.Config;
/** A builder of {@link HttpServerAttributesExtractor}. */
public final class HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> {
final HttpServerAttributesGetter<REQUEST, RESPONSE> getter;
CapturedHttpHeaders capturedHttpHeaders = CapturedHttpHeaders.server(Config.get());
HttpServerAttributesExtractorBuilder(HttpServerAttributesGetter<REQUEST, RESPONSE> getter) {
this.getter = getter;
}
/**
* Configures the HTTP headers that will be captured as span attributes.
*
* @param capturedHttpHeaders A configuration object specifying which HTTP request and response
* headers should be captured as span attributes.
*/
public HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> captureHttpHeaders(
CapturedHttpHeaders capturedHttpHeaders) {
this.capturedHttpHeaders = capturedHttpHeaders;
return this;
}
/**
* Returns a new {@link HttpServerAttributesExtractor} with the settings of this {@link
* HttpServerAttributesExtractorBuilder}.
*/
public HttpServerAttributesExtractor<REQUEST, RESPONSE> build() {
return new HttpServerAttributesExtractor<>(getter, capturedHttpHeaders);
}
}

View File

@ -104,10 +104,12 @@ class HttpClientAttributesExtractorTest {
response.put("header.custom-response-header", "654,321");
HttpClientAttributesExtractor<Map<String, String>, Map<String, String>> extractor =
HttpClientAttributesExtractor.create(
new TestHttpClientAttributesGetter(),
CapturedHttpHeaders.create(
singletonList("Custom-Request-Header"), singletonList("Custom-Response-Header")));
HttpClientAttributesExtractor.builder(new TestHttpClientAttributesGetter())
.captureHttpHeaders(
CapturedHttpHeaders.create(
singletonList("Custom-Request-Header"),
singletonList("Custom-Response-Header")))
.build();
AttributesBuilder attributes = Attributes.builder();
extractor.onStart(attributes, Context.root(), request);
@ -148,8 +150,9 @@ class HttpClientAttributesExtractorTest {
response.put("statusCode", "0");
HttpClientAttributesExtractor<Map<String, String>, Map<String, String>> extractor =
HttpClientAttributesExtractor.create(
new TestHttpClientAttributesGetter(), CapturedHttpHeaders.empty());
HttpClientAttributesExtractor.builder(new TestHttpClientAttributesGetter())
.captureHttpHeaders(CapturedHttpHeaders.empty())
.build();
AttributesBuilder attributes = Attributes.builder();
extractor.onStart(attributes, Context.root(), request);

View File

@ -184,8 +184,9 @@ class HttpServerAttributesExtractorTest {
request.put("header.x-forwarded-for", "1.1.1.1");
HttpServerAttributesExtractor<Map<String, String>, Map<String, String>> extractor =
HttpServerAttributesExtractor.create(
new TestHttpServerAttributesExtractor(), CapturedHttpHeaders.empty());
HttpServerAttributesExtractor.builder(new TestHttpServerAttributesExtractor())
.captureHttpHeaders(CapturedHttpHeaders.empty())
.build();
AttributesBuilder attributes = Attributes.builder();
extractor.onStart(attributes, Context.root(), request);
@ -203,8 +204,9 @@ class HttpServerAttributesExtractorTest {
request.put("header.x-forwarded-proto", "https");
HttpServerAttributesExtractor<Map<String, String>, Map<String, String>> extractor =
HttpServerAttributesExtractor.create(
new TestHttpServerAttributesExtractor(), CapturedHttpHeaders.empty());
HttpServerAttributesExtractor.builder(new TestHttpServerAttributesExtractor())
.captureHttpHeaders(CapturedHttpHeaders.empty())
.build();
AttributesBuilder attributes = Attributes.builder();
extractor.onStart(attributes, Context.root(), request);

View File

@ -75,7 +75,9 @@ public final class ApacheHttpClientTracingBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpClientAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractors(additionalExtractors)
// We manually inject because we need to inject internal requests for redirects.

View File

@ -135,7 +135,9 @@ public final class ArmeriaTracingBuilder {
HttpSpanStatusExtractor.create(clientAttributesGetter)))
.addAttributesExtractor(netClientAttributesExtractor)
.addAttributesExtractor(
HttpClientAttributesExtractor.create(clientAttributesGetter, capturedHttpClientHeaders))
HttpClientAttributesExtractor.builder(clientAttributesGetter)
.captureHttpHeaders(capturedHttpClientHeaders)
.build())
.addRequestMetrics(HttpClientMetrics.get());
serverInstrumenterBuilder
.setSpanStatusExtractor(
@ -144,7 +146,9 @@ public final class ArmeriaTracingBuilder {
.addAttributesExtractor(
NetServerAttributesExtractor.create(new ArmeriaNetServerAttributesGetter()))
.addAttributesExtractor(
HttpServerAttributesExtractor.create(serverAttributesGetter, capturedHttpServerHeaders))
HttpServerAttributesExtractor.builder(serverAttributesGetter)
.captureHttpHeaders(capturedHttpServerHeaders)
.build())
.addRequestMetrics(HttpServerMetrics.get())
.addContextCustomizer(HttpRouteHolder.get());

View File

@ -61,7 +61,9 @@ public final class JettyClientInstrumenterBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpClientAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpClientMetrics.get())

View File

@ -102,7 +102,7 @@ class KtorServerTracing private constructor(
with(instrumenterBuilder) {
setSpanStatusExtractor(configuration.statusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)))
addAttributesExtractor(NetServerAttributesExtractor.create(KtorNetServerAttributesGetter()))
addAttributesExtractor(HttpServerAttributesExtractor.create(httpAttributesGetter, configuration.capturedHttpHeaders))
addAttributesExtractor(HttpServerAttributesExtractor.builder(httpAttributesGetter).captureHttpHeaders(configuration.capturedHttpHeaders).build())
addRequestMetrics(HttpServerMetrics.get())
addContextCustomizer(HttpRouteHolder.get())
}

View File

@ -70,7 +70,9 @@ public final class OkHttpTracingBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpClientAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetClientAttributesExtractor.create(attributesGetter))
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpClientMetrics.get())

View File

@ -111,7 +111,9 @@ public final class RatpackTracingBuilder {
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributes))
.addAttributesExtractor(NetServerAttributesExtractor.create(netAttributes))
.addAttributesExtractor(
HttpServerAttributesExtractor.create(httpAttributes, capturedHttpServerHeaders))
HttpServerAttributesExtractor.builder(httpAttributes)
.captureHttpHeaders(capturedHttpServerHeaders)
.build())
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpServerMetrics.get())
.newServerInstrumenter(RatpackGetter.INSTANCE);
@ -128,7 +130,9 @@ public final class RatpackTracingBuilder {
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributes))
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributes))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributes, capturedHttpClientHeaders))
HttpClientAttributesExtractor.builder(httpAttributes)
.captureHttpHeaders(capturedHttpClientHeaders)
.build())
.addAttributesExtractors(additionalHttpClientExtractors)
.addRequestMetrics(HttpServerMetrics.get())
.newClientInstrumenter(RequestHeaderSetter.INSTANCE);

View File

@ -70,7 +70,9 @@ public final class RestletTracingBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetServerAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpServerMetrics.get())

View File

@ -45,7 +45,9 @@ public class RestletInstrumenterFactory {
openTelemetry, INSTRUMENTATION_NAME, HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetServerAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpServerMetrics.get())

View File

@ -70,7 +70,9 @@ public final class SpringWebTracingBuilder {
HttpSpanNameExtractor.create(httpAttributeGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributeGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributeGetter, capturedHttpHeaders))
HttpClientAttributesExtractor.builder(httpAttributeGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractors(additionalExtractors)
.addRequestMetrics(HttpClientMetrics.get())

View File

@ -76,7 +76,9 @@ public final class SpringWebfluxTracingBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpClientAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(attributesExtractor)
.addAttributesExtractor(PeerServiceAttributesExtractor.create(attributesGetter))
.addAttributesExtractors(additionalExtractors)

View File

@ -71,7 +71,9 @@ public final class SpringWebMvcTracingBuilder {
HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.create(httpAttributesGetter, capturedHttpHeaders))
HttpServerAttributesExtractor.builder(httpAttributesGetter)
.captureHttpHeaders(capturedHttpHeaders)
.build())
.addAttributesExtractor(new StatusCodeExtractor())
.addAttributesExtractor(
NetServerAttributesExtractor.create(new SpringWebMvcNetAttributesGetter()))