Skip to content

Commit

Permalink
Support the http.request.method_original attribute (#8779)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mateusz Rzeszutek authored Jul 17, 2023
1 parent 3650f16 commit cc8160c
Show file tree
Hide file tree
Showing 72 changed files with 833 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ final class HttpAttributes {

static final AttributeKey<String> HTTP_REQUEST_METHOD = stringKey("http.request.method");

static final AttributeKey<String> HTTP_REQUEST_METHOD_ORIGINAL =
stringKey("http.request.method_original");

static final AttributeKey<Long> HTTP_REQUEST_BODY_SIZE = longKey("http.request.body.size");

static final AttributeKey<Long> HTTP_RESPONSE_BODY_SIZE = longKey("http.response.body.size");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.List;
import java.util.Set;
import java.util.function.ToIntFunction;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -63,12 +64,14 @@ public static <REQUEST, RESPONSE> HttpClientAttributesExtractorBuilder<REQUEST,
HttpClientAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetClientAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders) {
List<String> capturedResponseHeaders,
Set<String> knownMethods) {
this(
httpAttributesGetter,
netAttributesGetter,
capturedRequestHeaders,
capturedResponseHeaders,
knownMethods,
HttpClientResend::getAndIncrement);
}

Expand All @@ -78,8 +81,9 @@ public static <REQUEST, RESPONSE> HttpClientAttributesExtractorBuilder<REQUEST,
NetClientAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders,
Set<String> knownMethods,
ToIntFunction<Context> resendCountIncrementer) {
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders, knownMethods);
HttpNetAddressPortExtractor<REQUEST> addressPortExtractor =
new HttpNetAddressPortExtractor<>(httpAttributesGetter);
internalNetExtractor =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesGetter;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import java.util.List;
import java.util.Set;

/** A builder of {@link HttpClientAttributesExtractor}. */
public final class HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
Expand All @@ -19,6 +21,7 @@ public final class HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> {
final NetClientAttributesGetter<REQUEST, RESPONSE> netAttributesGetter;
List<String> capturedRequestHeaders = emptyList();
List<String> capturedResponseHeaders = emptyList();
Set<String> knownMethods = HttpConstants.KNOWN_METHODS;

HttpClientAttributesExtractorBuilder(
HttpClientAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
Expand Down Expand Up @@ -64,12 +67,38 @@ public HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> setCapturedRespon
return this;
}

/**
* 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 HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> setKnownMethods(
Set<String> knownMethods) {
this.knownMethods = knownMethods;
return this;
}

/**
* Returns a new {@link HttpClientAttributesExtractor} with the settings of this {@link
* HttpClientAttributesExtractorBuilder}.
*/
public AttributesExtractor<REQUEST, RESPONSE> build() {
return new HttpClientAttributesExtractor<>(
httpAttributesGetter, netAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
httpAttributesGetter,
netAttributesGetter,
capturedRequestHeaders,
capturedResponseHeaders,
knownMethods);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeadersUtil.requestAttributeKey;
import static io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeadersUtil.responseAttributeKey;
import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;
import static io.opentelemetry.instrumentation.api.internal.HttpConstants._OTHER;
import static java.util.logging.Level.FINE;

import io.opentelemetry.api.common.AttributesBuilder;
Expand All @@ -17,7 +18,9 @@
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.FallbackAddressPortExtractor;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;
import javax.annotation.Nullable;

Expand All @@ -35,19 +38,29 @@ abstract class HttpCommonAttributesExtractor<
final GETTER getter;
private final List<String> capturedRequestHeaders;
private final List<String> capturedResponseHeaders;
private final Set<String> knownMethods;

HttpCommonAttributesExtractor(
GETTER getter, List<String> capturedRequestHeaders, List<String> capturedResponseHeaders) {
GETTER getter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders,
Set<String> knownMethods) {
this.getter = getter;
this.capturedRequestHeaders = lowercase(capturedRequestHeaders);
this.capturedResponseHeaders = lowercase(capturedResponseHeaders);
this.knownMethods = new HashSet<>(knownMethods);
}

@Override
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
String method = getter.getHttpRequestMethod(request);
if (SemconvStability.emitStableHttpSemconv()) {
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, method);
if (knownMethods.contains(method)) {
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, method);
} else {
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, _OTHER);
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD_ORIGINAL, method);
}
}
if (SemconvStability.emitOldHttpSemconv()) {
internalSet(attributes, SemanticAttributes.HTTP_METHOD, method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import javax.annotation.Nullable;

Expand Down Expand Up @@ -78,12 +79,14 @@ public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST,
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
NetServerAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders) {
List<String> capturedResponseHeaders,
Set<String> knownMethods) {
this(
httpAttributesGetter,
netAttributesGetter,
capturedRequestHeaders,
capturedResponseHeaders,
knownMethods,
HttpRouteHolder::getRoute);
}

Expand All @@ -93,8 +96,9 @@ public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST,
NetServerAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders,
Set<String> knownMethods,
Function<Context, String> httpRouteHolderGetter) {
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders, knownMethods);
HttpNetAddressPortExtractor<REQUEST> addressPortExtractor =
new HttpNetAddressPortExtractor<>(httpAttributesGetter);
internalUrlExtractor =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import java.util.List;
import java.util.Set;

/** A builder of {@link HttpServerAttributesExtractor}. */
public final class HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> {
Expand All @@ -19,6 +21,7 @@ public final class HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> {
final NetServerAttributesGetter<REQUEST, RESPONSE> netAttributesGetter;
List<String> capturedRequestHeaders = emptyList();
List<String> capturedResponseHeaders = emptyList();
Set<String> knownMethods = HttpConstants.KNOWN_METHODS;

HttpServerAttributesExtractorBuilder(
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
Expand Down Expand Up @@ -64,12 +67,38 @@ public HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> setCapturedRespon
return this;
}

/**
* 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 HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> setKnownMethods(
Set<String> knownMethods) {
this.knownMethods = knownMethods;
return this;
}

/**
* Returns a new {@link HttpServerAttributesExtractor} with the settings of this {@link
* HttpServerAttributesExtractorBuilder}.
*/
public AttributesExtractor<REQUEST, RESPONSE> build() {
return new HttpServerAttributesExtractor<>(
httpAttributesGetter, netAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
httpAttributesGetter,
netAttributesGetter,
capturedRequestHeaders,
capturedResponseHeaders,
knownMethods);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesGetter;
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -141,6 +142,7 @@ void normal() {
new TestNetClientAttributesGetter(),
singletonList("Custom-Request-Header"),
singletonList("Custom-Response-Header"),
HttpConstants.KNOWN_METHODS,
resendCountFromContext);

AttributesBuilder startAttributes = Attributes.builder();
Expand Down Expand Up @@ -311,6 +313,7 @@ void zeroResends() {
new TestNetClientAttributesGetter(),
emptyList(),
emptyList(),
HttpConstants.KNOWN_METHODS,
resendCountFromContext);

AttributesBuilder attributes = Attributes.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -162,6 +163,7 @@ void normal() {
new TestNetServerAttributesGetter(),
singletonList("Custom-Request-Header"),
singletonList("Custom-Response-Header"),
HttpConstants.KNOWN_METHODS,
routeFromContext);

AttributesBuilder startAttributes = Attributes.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -136,6 +137,7 @@ void normal() {
new TestNetClientAttributesGetter(),
singletonList("Custom-Request-Header"),
singletonList("Custom-Response-Header"),
HttpConstants.KNOWN_METHODS,
resendCountFromContext);

AttributesBuilder startAttributes = Attributes.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -156,6 +157,7 @@ void normal() {
new TestNetServerAttributesGetter(),
singletonList("Custom-Request-Header"),
singletonList("Custom-Response-Header"),
HttpConstants.KNOWN_METHODS,
routeFromContext);

AttributesBuilder startAttributes = Attributes.builder();
Expand Down
Loading

0 comments on commit cc8160c

Please sign in to comment.