Skip to content

Commit

Permalink
Use HTTP instead of non-known method in http span name (#9441)
Browse files Browse the repository at this point in the history
Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
  • Loading branch information
laurit and Mateusz Rzeszutek authored Sep 13, 2023
1 parent 2d505eb commit d157b68
Show file tree
Hide file tree
Showing 59 changed files with 301 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package io.opentelemetry.instrumentation.api.instrumenter.http;

import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;

/**
Expand All @@ -17,25 +19,39 @@
public final class HttpSpanNameExtractor<REQUEST> implements SpanNameExtractor<REQUEST> {

/**
* Returns a {@link SpanNameExtractor} which should be used for HTTP requests. HTTP attributes
* will be examined to determine the name of the span.
* Returns a {@link SpanNameExtractor} which should be used for HTTP requests with default
* configuration. HTTP attributes will be examined to determine the name of the span.
*/
public static <REQUEST> SpanNameExtractor<REQUEST> create(
HttpCommonAttributesGetter<REQUEST, ?> getter) {
return new HttpSpanNameExtractor<>(getter);
return builder(getter).build();
}

/**
* Returns a new {@link HttpSpanNameExtractorBuilder} that can be used to configure the HTTP span
* name extractor.
*/
public static <REQUEST> HttpSpanNameExtractorBuilder<REQUEST> builder(
HttpCommonAttributesGetter<REQUEST, ?> getter) {
return new HttpSpanNameExtractorBuilder<>(getter);
}

private final HttpCommonAttributesGetter<REQUEST, ?> getter;
private final Set<String> knownMethods;

private HttpSpanNameExtractor(HttpCommonAttributesGetter<REQUEST, ?> getter) {
this.getter = getter;
HttpSpanNameExtractor(HttpSpanNameExtractorBuilder<REQUEST> builder) {
this.getter = builder.httpAttributesGetter;
this.knownMethods = new HashSet<>(builder.knownMethods);
}

@Override
public String extract(REQUEST request) {
String method = getter.getHttpRequestMethod(request);
String route = extractRoute(request);
if (method != null) {
if (!knownMethods.contains(method)) {
method = "HTTP";
}
return route == null ? method : method + " " + route;
}
return "HTTP";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.instrumenter.http;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import java.util.HashSet;
import java.util.Set;

/** A builder of {@link HttpSpanNameExtractor}. */
public final class HttpSpanNameExtractorBuilder<REQUEST> {

final HttpCommonAttributesGetter<REQUEST, ?> httpAttributesGetter;
Set<String> knownMethods = HttpConstants.KNOWN_METHODS;

HttpSpanNameExtractorBuilder(HttpCommonAttributesGetter<REQUEST, ?> httpAttributesGetter) {
this.httpAttributesGetter = httpAttributesGetter;
}

/**
* Configures the extractor to recognize an alternative set of HTTP request methods.
*
* <p>By default, this extractor 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>. If an
* unknown method is encountered, the extractor will use the value {@value HttpConstants#_OTHER}
* instead of it and put the original value in an extra {@code http.request.method_original}
* attribute.
*
* <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.
*/
@CanIgnoreReturnValue
public HttpSpanNameExtractorBuilder<REQUEST> setKnownMethods(Set<String> knownMethods) {
this.knownMethods = new HashSet<>(knownMethods);
return this;
}

/**
* Returns a new {@link HttpSpanNameExtractor} with the settings of this {@link
* HttpSpanNameExtractorBuilder}.
*/
public SpanNameExtractor<REQUEST> build() {
return new HttpSpanNameExtractor<>(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ public class AkkaHttpClientSingletons {
Instrumenter.<HttpRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
AkkaHttpUtil.instrumentationName(),
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ public final class AkkaHttpServerSingletons {
Instrumenter.<HttpRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
AkkaHttpUtil.instrumentationName(),
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public final class ApacheHttpAsyncClientSingletons {
Instrumenter.<ApacheHttpClientRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public final class ApacheHttpClientSingletons {
Instrumenter.<HttpMethod, HttpMethod>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public final class ApacheHttpClientSingletons {
Instrumenter.<ApacheHttpClientRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientExperimentalMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractorBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -34,6 +35,8 @@ public final class ApacheHttpClientTelemetryBuilder {
private final HttpClientAttributesExtractorBuilder<ApacheHttpClientRequest, HttpResponse>
httpAttributesExtractorBuilder =
HttpClientAttributesExtractor.builder(ApacheHttpClientHttpAttributesGetter.INSTANCE);
private final HttpSpanNameExtractorBuilder<ApacheHttpClientRequest> httpSpanNameExtractorBuilder =
HttpSpanNameExtractor.builder(ApacheHttpClientHttpAttributesGetter.INSTANCE);
private boolean emitExperimentalHttpClientMetrics = false;

ApacheHttpClientTelemetryBuilder(OpenTelemetry openTelemetry) {
Expand Down Expand Up @@ -90,6 +93,7 @@ public ApacheHttpClientTelemetryBuilder setCapturedResponseHeaders(List<String>
@CanIgnoreReturnValue
public ApacheHttpClientTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
httpAttributesExtractorBuilder.setKnownMethods(knownMethods);
httpSpanNameExtractorBuilder.setKnownMethods(knownMethods);
return this;
}

Expand All @@ -116,9 +120,7 @@ public ApacheHttpClientTelemetry build() {

InstrumenterBuilder<ApacheHttpClientRequest, HttpResponse> builder =
Instrumenter.<ApacheHttpClientRequest, HttpResponse>builder(
openTelemetry,
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
openTelemetry, INSTRUMENTATION_NAME, httpSpanNameExtractorBuilder.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(httpAttributesExtractorBuilder.build())
.addAttributesExtractors(additionalExtractors)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public final class ApacheHttpClientSingletons {
Instrumenter.<HttpRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerMetrics;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerRoute;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractorBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
import io.opentelemetry.instrumentation.armeria.v1_3.internal.ArmeriaHttpClientAttributesGetter;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
Expand Down Expand Up @@ -56,6 +57,11 @@ public final class ArmeriaTelemetryBuilder {
httpServerAttributesExtractorBuilder =
HttpServerAttributesExtractor.builder(ArmeriaHttpServerAttributesGetter.INSTANCE);

private final HttpSpanNameExtractorBuilder<RequestContext> httpClientSpanNameExtractorBuilder =
HttpSpanNameExtractor.builder(ArmeriaHttpClientAttributesGetter.INSTANCE);
private final HttpSpanNameExtractorBuilder<RequestContext> httpServerSpanNameExtractorBuilder =
HttpSpanNameExtractor.builder(ArmeriaHttpServerAttributesGetter.INSTANCE);

private Function<
SpanStatusExtractor<RequestContext, RequestLog>,
? extends SpanStatusExtractor<? super RequestContext, ? super RequestLog>>
Expand Down Expand Up @@ -167,6 +173,8 @@ public ArmeriaTelemetryBuilder setCapturedServerResponseHeaders(List<String> res
public ArmeriaTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
httpClientAttributesExtractorBuilder.setKnownMethods(knownMethods);
httpServerAttributesExtractorBuilder.setKnownMethods(knownMethods);
httpClientSpanNameExtractorBuilder.setKnownMethods(knownMethods);
httpServerSpanNameExtractorBuilder.setKnownMethods(knownMethods);
return this;
}

Expand Down Expand Up @@ -204,14 +212,10 @@ public ArmeriaTelemetry build() {

InstrumenterBuilder<ClientRequestContext, RequestLog> clientInstrumenterBuilder =
Instrumenter.builder(
openTelemetry,
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(clientAttributesGetter));
openTelemetry, INSTRUMENTATION_NAME, httpClientSpanNameExtractorBuilder.build());
InstrumenterBuilder<ServiceRequestContext, RequestLog> serverInstrumenterBuilder =
Instrumenter.builder(
openTelemetry,
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(serverAttributesGetter));
openTelemetry, INSTRUMENTATION_NAME, httpServerSpanNameExtractorBuilder.build());

Stream.of(clientInstrumenterBuilder, serverInstrumenterBuilder)
.forEach(instrumenter -> instrumenter.addAttributesExtractors(additionalExtractors));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public final class AsyncHttpClientSingletons {
Instrumenter.<Request, Response>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public final class AsyncHttpClientSingletons {
Instrumenter.<RequestContext, Response>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ public class GoogleHttpClientSingletons {
Instrumenter.<HttpRequest, HttpResponse>builder(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public final class GrizzlySingletons {
Instrumenter.<HttpRequestPacket, HttpResponsePacket>builder(
GlobalOpenTelemetry.get(),
"io.opentelemetry.grizzly-2.3",
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public final class HttpUrlConnectionSingletons {
Instrumenter.<HttpURLConnection, Integer>builder(
GlobalOpenTelemetry.get(),
"io.opentelemetry.http-url-connection",
HttpSpanNameExtractor.create(httpAttributesGetter))
HttpSpanNameExtractor.builder(httpAttributesGetter)
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods())
.build())
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpClientAttributesExtractor.builder(httpAttributesGetter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class JavaHttpClientSingletons {
.setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders())
.setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders())
.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()),
builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()),
singletonList(
PeerServiceAttributesExtractor.create(
JavaHttpClientAttributesGetter.INSTANCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractorBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractorBuilder;
import io.opentelemetry.instrumentation.httpclient.internal.HttpHeadersSetter;
import io.opentelemetry.instrumentation.httpclient.internal.JavaHttpClientInstrumenterFactory;
import java.net.http.HttpRequest;
Expand All @@ -25,9 +26,10 @@ public final class JavaHttpClientTelemetryBuilder {

private final List<AttributesExtractor<? super HttpRequest, ? super HttpResponse<?>>>
additionalExtractors = new ArrayList<>();

private Consumer<HttpClientAttributesExtractorBuilder<HttpRequest, HttpResponse<?>>>
extractorConfigurer = builder -> {};
private Consumer<HttpSpanNameExtractorBuilder<HttpRequest>> spanNameExtractorConfigurer =
builder -> {};
private boolean emitExperimentalHttpClientMetrics = false;

JavaHttpClientTelemetryBuilder(OpenTelemetry openTelemetry) {
Expand Down Expand Up @@ -86,6 +88,8 @@ public JavaHttpClientTelemetryBuilder setCapturedResponseHeaders(List<String> re
public JavaHttpClientTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
extractorConfigurer =
extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods));
spanNameExtractorConfigurer =
spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods));
return this;
}

Expand All @@ -107,6 +111,7 @@ public JavaHttpClientTelemetry build() {
JavaHttpClientInstrumenterFactory.createInstrumenter(
openTelemetry,
extractorConfigurer,
spanNameExtractorConfigurer,
additionalExtractors,
emitExperimentalHttpClientMetrics);

Expand Down
Loading

0 comments on commit d157b68

Please sign in to comment.