Skip to content

Commit cc8160c

Browse files
author
Mateusz Rzeszutek
authored
Support the http.request.method_original attribute (open-telemetry#8779)
1 parent 3650f16 commit cc8160c

File tree

72 files changed

+833
-73
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+833
-73
lines changed

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpAttributes.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ final class HttpAttributes {
1717

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

20+
static final AttributeKey<String> HTTP_REQUEST_METHOD_ORIGINAL =
21+
stringKey("http.request.method_original");
22+
2023
static final AttributeKey<Long> HTTP_REQUEST_BODY_SIZE = longKey("http.request.body.size");
2124

2225
static final AttributeKey<Long> HTTP_RESPONSE_BODY_SIZE = longKey("http.response.body.size");

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
2121
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2222
import java.util.List;
23+
import java.util.Set;
2324
import java.util.function.ToIntFunction;
2425
import javax.annotation.Nullable;
2526

@@ -63,12 +64,14 @@ public static <REQUEST, RESPONSE> HttpClientAttributesExtractorBuilder<REQUEST,
6364
HttpClientAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
6465
NetClientAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
6566
List<String> capturedRequestHeaders,
66-
List<String> capturedResponseHeaders) {
67+
List<String> capturedResponseHeaders,
68+
Set<String> knownMethods) {
6769
this(
6870
httpAttributesGetter,
6971
netAttributesGetter,
7072
capturedRequestHeaders,
7173
capturedResponseHeaders,
74+
knownMethods,
7275
HttpClientResend::getAndIncrement);
7376
}
7477

@@ -78,8 +81,9 @@ public static <REQUEST, RESPONSE> HttpClientAttributesExtractorBuilder<REQUEST,
7881
NetClientAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
7982
List<String> capturedRequestHeaders,
8083
List<String> capturedResponseHeaders,
84+
Set<String> knownMethods,
8185
ToIntFunction<Context> resendCountIncrementer) {
82-
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
86+
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders, knownMethods);
8387
HttpNetAddressPortExtractor<REQUEST> addressPortExtractor =
8488
new HttpNetAddressPortExtractor<>(httpAttributesGetter);
8589
internalNetExtractor =

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBuilder.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import com.google.errorprone.annotations.CanIgnoreReturnValue;
1111
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1212
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesGetter;
13+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
1314
import java.util.List;
15+
import java.util.Set;
1416

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

2326
HttpClientAttributesExtractorBuilder(
2427
HttpClientAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
@@ -64,12 +67,38 @@ public HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> setCapturedRespon
6467
return this;
6568
}
6669

70+
/**
71+
* Configures the extractor to recognize an alternative set of HTTP request methods.
72+
*
73+
* <p>By default, this extractor defines "known" methods as the ones listed in <a
74+
* href="https://www.rfc-editor.org/rfc/rfc9110.html#name-methods">RFC9110</a> and the PATCH
75+
* method defined in <a href="https://www.rfc-editor.org/rfc/rfc5789.html">RFC5789</a>. If an
76+
* unknown method is encountered, the extractor will use the value {@value HttpConstants#_OTHER}
77+
* instead of it and put the original value in an extra {@code http.request.method_original}
78+
* attribute.
79+
*
80+
* <p>Note: calling this method <b>overrides</b> the default known method sets completely; it does
81+
* not supplement it.
82+
*
83+
* @param knownMethods A set of recognized HTTP request methods.
84+
*/
85+
@CanIgnoreReturnValue
86+
public HttpClientAttributesExtractorBuilder<REQUEST, RESPONSE> setKnownMethods(
87+
Set<String> knownMethods) {
88+
this.knownMethods = knownMethods;
89+
return this;
90+
}
91+
6792
/**
6893
* Returns a new {@link HttpClientAttributesExtractor} with the settings of this {@link
6994
* HttpClientAttributesExtractorBuilder}.
7095
*/
7196
public AttributesExtractor<REQUEST, RESPONSE> build() {
7297
return new HttpClientAttributesExtractor<>(
73-
httpAttributesGetter, netAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
98+
httpAttributesGetter,
99+
netAttributesGetter,
100+
capturedRequestHeaders,
101+
capturedResponseHeaders,
102+
knownMethods);
74103
}
75104
}

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpCommonAttributesExtractor.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeadersUtil.requestAttributeKey;
1010
import static io.opentelemetry.instrumentation.api.instrumenter.http.CapturedHttpHeadersUtil.responseAttributeKey;
1111
import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;
12+
import static io.opentelemetry.instrumentation.api.internal.HttpConstants._OTHER;
1213
import static java.util.logging.Level.FINE;
1314

1415
import io.opentelemetry.api.common.AttributesBuilder;
@@ -17,7 +18,9 @@
1718
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.FallbackAddressPortExtractor;
1819
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
1920
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
21+
import java.util.HashSet;
2022
import java.util.List;
23+
import java.util.Set;
2124
import java.util.logging.Logger;
2225
import javax.annotation.Nullable;
2326

@@ -35,19 +38,29 @@ abstract class HttpCommonAttributesExtractor<
3538
final GETTER getter;
3639
private final List<String> capturedRequestHeaders;
3740
private final List<String> capturedResponseHeaders;
41+
private final Set<String> knownMethods;
3842

3943
HttpCommonAttributesExtractor(
40-
GETTER getter, List<String> capturedRequestHeaders, List<String> capturedResponseHeaders) {
44+
GETTER getter,
45+
List<String> capturedRequestHeaders,
46+
List<String> capturedResponseHeaders,
47+
Set<String> knownMethods) {
4148
this.getter = getter;
4249
this.capturedRequestHeaders = lowercase(capturedRequestHeaders);
4350
this.capturedResponseHeaders = lowercase(capturedResponseHeaders);
51+
this.knownMethods = new HashSet<>(knownMethods);
4452
}
4553

4654
@Override
4755
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
4856
String method = getter.getHttpRequestMethod(request);
4957
if (SemconvStability.emitStableHttpSemconv()) {
50-
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, method);
58+
if (knownMethods.contains(method)) {
59+
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, method);
60+
} else {
61+
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD, _OTHER);
62+
internalSet(attributes, HttpAttributes.HTTP_REQUEST_METHOD_ORIGINAL, method);
63+
}
5164
}
5265
if (SemconvStability.emitOldHttpSemconv()) {
5366
internalSet(attributes, SemanticAttributes.HTTP_METHOD, method);

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractor.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
2828
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2929
import java.util.List;
30+
import java.util.Set;
3031
import java.util.function.Function;
3132
import javax.annotation.Nullable;
3233

@@ -78,12 +79,14 @@ public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST,
7879
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
7980
NetServerAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
8081
List<String> capturedRequestHeaders,
81-
List<String> capturedResponseHeaders) {
82+
List<String> capturedResponseHeaders,
83+
Set<String> knownMethods) {
8284
this(
8385
httpAttributesGetter,
8486
netAttributesGetter,
8587
capturedRequestHeaders,
8688
capturedResponseHeaders,
89+
knownMethods,
8790
HttpRouteHolder::getRoute);
8891
}
8992

@@ -93,8 +96,9 @@ public static <REQUEST, RESPONSE> HttpServerAttributesExtractorBuilder<REQUEST,
9396
NetServerAttributesGetter<REQUEST, RESPONSE> netAttributesGetter,
9497
List<String> capturedRequestHeaders,
9598
List<String> capturedResponseHeaders,
99+
Set<String> knownMethods,
96100
Function<Context, String> httpRouteHolderGetter) {
97-
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
101+
super(httpAttributesGetter, capturedRequestHeaders, capturedResponseHeaders, knownMethods);
98102
HttpNetAddressPortExtractor<REQUEST> addressPortExtractor =
99103
new HttpNetAddressPortExtractor<>(httpAttributesGetter);
100104
internalUrlExtractor =

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBuilder.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import com.google.errorprone.annotations.CanIgnoreReturnValue;
1111
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1212
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
13+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
1314
import java.util.List;
15+
import java.util.Set;
1416

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

2326
HttpServerAttributesExtractorBuilder(
2427
HttpServerAttributesGetter<REQUEST, RESPONSE> httpAttributesGetter,
@@ -64,12 +67,38 @@ public HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> setCapturedRespon
6467
return this;
6568
}
6669

70+
/**
71+
* Configures the extractor to recognize an alternative set of HTTP request methods.
72+
*
73+
* <p>By default, this extractor defines "known" methods as the ones listed in <a
74+
* href="https://www.rfc-editor.org/rfc/rfc9110.html#name-methods">RFC9110</a> and the PATCH
75+
* method defined in <a href="https://www.rfc-editor.org/rfc/rfc5789.html">RFC5789</a>. If an
76+
* unknown method is encountered, the extractor will use the value {@value HttpConstants#_OTHER}
77+
* instead of it and put the original value in an extra {@code http.request.method_original}
78+
* attribute.
79+
*
80+
* <p>Note: calling this method <b>overrides</b> the default known method sets completely; it does
81+
* not supplement it.
82+
*
83+
* @param knownMethods A set of recognized HTTP request methods.
84+
*/
85+
@CanIgnoreReturnValue
86+
public HttpServerAttributesExtractorBuilder<REQUEST, RESPONSE> setKnownMethods(
87+
Set<String> knownMethods) {
88+
this.knownMethods = knownMethods;
89+
return this;
90+
}
91+
6792
/**
6893
* Returns a new {@link HttpServerAttributesExtractor} with the settings of this {@link
6994
* HttpServerAttributesExtractorBuilder}.
7095
*/
7196
public AttributesExtractor<REQUEST, RESPONSE> build() {
7297
return new HttpServerAttributesExtractor<>(
73-
httpAttributesGetter, netAttributesGetter, capturedRequestHeaders, capturedResponseHeaders);
98+
httpAttributesGetter,
99+
netAttributesGetter,
100+
capturedRequestHeaders,
101+
capturedResponseHeaders,
102+
knownMethods);
74103
}
75104
}

instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
2020
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesGetter;
2121
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
22+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
2223
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2324
import java.util.HashMap;
2425
import java.util.List;
@@ -141,6 +142,7 @@ void normal() {
141142
new TestNetClientAttributesGetter(),
142143
singletonList("Custom-Request-Header"),
143144
singletonList("Custom-Response-Header"),
145+
HttpConstants.KNOWN_METHODS,
144146
resendCountFromContext);
145147

146148
AttributesBuilder startAttributes = Attributes.builder();
@@ -311,6 +313,7 @@ void zeroResends() {
311313
new TestNetClientAttributesGetter(),
312314
emptyList(),
313315
emptyList(),
316+
HttpConstants.KNOWN_METHODS,
314317
resendCountFromContext);
315318

316319
AttributesBuilder attributes = Attributes.builder();

instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
2020
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesGetter;
2121
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
22+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
2223
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2324
import java.util.HashMap;
2425
import java.util.List;
@@ -162,6 +163,7 @@ void normal() {
162163
new TestNetServerAttributesGetter(),
163164
singletonList("Custom-Request-Header"),
164165
singletonList("Custom-Response-Header"),
166+
HttpConstants.KNOWN_METHODS,
165167
routeFromContext);
166168

167169
AttributesBuilder startAttributes = Attributes.builder();

instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientAttributesExtractorBothSemconvTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
2121
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
2222
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
23+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
2324
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2425
import java.util.HashMap;
2526
import java.util.List;
@@ -136,6 +137,7 @@ void normal() {
136137
new TestNetClientAttributesGetter(),
137138
singletonList("Custom-Request-Header"),
138139
singletonList("Custom-Response-Header"),
140+
HttpConstants.KNOWN_METHODS,
139141
resendCountFromContext);
140142

141143
AttributesBuilder startAttributes = Attributes.builder();

instrumentation-api-semconv/src/testBothHttpSemconv/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerAttributesExtractorBothSemconvTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.instrumentation.api.instrumenter.net.internal.NetAttributes;
2020
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
2121
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
22+
import io.opentelemetry.instrumentation.api.internal.HttpConstants;
2223
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
2324
import java.util.HashMap;
2425
import java.util.List;
@@ -156,6 +157,7 @@ void normal() {
156157
new TestNetServerAttributesGetter(),
157158
singletonList("Custom-Request-Header"),
158159
singletonList("Custom-Response-Header"),
160+
HttpConstants.KNOWN_METHODS,
159161
routeFromContext);
160162

161163
AttributesBuilder startAttributes = Attributes.builder();

0 commit comments

Comments
 (0)