From 7c126b49abf46b5bd237798127b8bf94f01b3a6c Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Thu, 16 Jan 2025 13:03:01 +0200 Subject: [PATCH 1/2] Implement ExtendedTextMapGetter in http server instrumentations --- .../api/internal/EnumerationUtil.java | 37 +++++++++++++++++++ .../server/AkkaHttpServerHeaders.java | 20 +++++++++- .../v1_3/internal/RequestContextGetter.java | 13 ++++++- .../grizzly/HttpRequestHeadersGetter.java | 10 ++++- .../jetty/v12_0/Jetty12TextMapGetter.java | 11 +++++- .../ktor/v1_0/ApplicationRequestGetter.kt | 7 +++- .../v2_0/common/ApplicationRequestGetter.kt | 7 +++- .../LibertyDispatcherRequestGetter.java | 10 ++++- .../netty/v3_8/server/NettyHeadersGetter.java | 10 ++++- .../server/HttpRequestHeadersGetter.java | 13 ++++++- .../v1_0/server/PekkoHttpServerHeaders.java | 20 +++++++++- .../ratpack/v1_7/internal/RatpackGetter.java | 14 ++++++- .../v1_1/internal/RestletHeadersGetter.java | 23 +++++++----- .../v2_0/internal/RestletHeadersGetter.java | 14 ++++++- .../servlet/ServletRequestGetter.java | 10 ++++- .../webflux/v5_3/WebfluxTextMapGetter.java | 16 +++++++- .../v5_3/JavaxHttpServletRequestGetter.java | 21 +---------- .../webmvc/v5_3/WebMvcHttpServerTest.java | 2 - .../v6_0/JakartaHttpServletRequestGetter.java | 11 +++++- .../tomcat/common/TomcatRequestGetter.java | 11 +++++- .../undertow/UndertowExchangeGetter.java | 13 ++++++- .../server/http/RequestContextGetter.java | 13 ++++++- .../junit/http/AbstractHttpServerTest.java | 2 - .../junit/http/HttpServerTestOptions.java | 7 ---- 24 files changed, 240 insertions(+), 75 deletions(-) create mode 100644 instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/EnumerationUtil.java diff --git a/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/EnumerationUtil.java b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/EnumerationUtil.java new file mode 100644 index 000000000000..e8bf168cfdc3 --- /dev/null +++ b/instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/EnumerationUtil.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.internal; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +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 EnumerationUtil { + + public static Iterator asIterator(@Nullable Enumeration enumeration) { + if (enumeration == null) { + return Collections.emptyIterator(); + } + return new Iterator() { + @Override + public boolean hasNext() { + return enumeration.hasMoreElements(); + } + + @Override + public E next() { + return enumeration.nextElement(); + } + }; + } + + private EnumerationUtil() {} +} diff --git a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerHeaders.java b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerHeaders.java index d353b268a94b..5708957576eb 100644 --- a/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerHeaders.java +++ b/instrumentation/akka/akka-http-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkahttp/server/AkkaHttpServerHeaders.java @@ -7,12 +7,16 @@ import akka.http.javadsl.model.HttpHeader; import akka.http.scaladsl.model.HttpRequest; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -enum AkkaHttpServerHeaders implements TextMapGetter { +enum AkkaHttpServerHeaders implements ExtendedTextMapGetter { INSTANCE; @Override @@ -27,4 +31,16 @@ public String get(HttpRequest carrier, String key) { Optional header = carrier.getHeader(key); return header.map(HttpHeader::value).orElse(null); } + + @Override + public Iterator getAll(HttpRequest carrier, String key) { + String headerName = key.toLowerCase(Locale.ROOT); + List result = new ArrayList<>(); + for (HttpHeader header : carrier.getHeaders()) { + if (header.is(headerName)) { + result.add(header.value()); + } + } + return result.iterator(); + } } diff --git a/instrumentation/armeria/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/internal/RequestContextGetter.java b/instrumentation/armeria/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/internal/RequestContextGetter.java index 5cae10de6578..8afb5f5fb8d7 100644 --- a/instrumentation/armeria/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/internal/RequestContextGetter.java +++ b/instrumentation/armeria/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/internal/RequestContextGetter.java @@ -7,12 +7,13 @@ import com.linecorp.armeria.server.ServiceRequestContext; import io.netty.util.AsciiString; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import java.util.Collections; +import java.util.Iterator; import java.util.stream.Collectors; import javax.annotation.Nullable; -enum RequestContextGetter implements TextMapGetter { +enum RequestContextGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -33,4 +34,12 @@ public String get(@Nullable ServiceRequestContext carrier, String key) { } return carrier.request().headers().get(key); } + + @Override + public Iterator getAll(@Nullable ServiceRequestContext carrier, String key) { + if (carrier == null) { + return Collections.emptyIterator(); + } + return carrier.request().headers().valueIterator(key); + } } diff --git a/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpRequestHeadersGetter.java b/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpRequestHeadersGetter.java index 3623c650860c..484e1abc18be 100644 --- a/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpRequestHeadersGetter.java +++ b/instrumentation/grizzly-2.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/HttpRequestHeadersGetter.java @@ -5,10 +5,11 @@ package io.opentelemetry.javaagent.instrumentation.grizzly; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Iterator; import org.glassfish.grizzly.http.HttpRequestPacket; -enum HttpRequestHeadersGetter implements TextMapGetter { +enum HttpRequestHeadersGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -20,4 +21,9 @@ public Iterable keys(HttpRequestPacket request) { public String get(HttpRequestPacket request, String key) { return request.getHeader(key); } + + @Override + public Iterator getAll(HttpRequestPacket request, String key) { + return request.getHeaders().values(key).iterator(); + } } diff --git a/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12TextMapGetter.java b/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12TextMapGetter.java index 59e9248eb9b5..c420b3480170 100644 --- a/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12TextMapGetter.java +++ b/instrumentation/jetty/jetty-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v12_0/Jetty12TextMapGetter.java @@ -5,10 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.jetty.v12_0; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import io.opentelemetry.instrumentation.api.internal.EnumerationUtil; +import java.util.Iterator; import org.eclipse.jetty.server.Request; -enum Jetty12TextMapGetter implements TextMapGetter { +enum Jetty12TextMapGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -20,4 +22,9 @@ public Iterable keys(Request carrier) { public String get(Request carrier, String key) { return carrier.getHeaders().get(key); } + + @Override + public Iterator getAll(Request carrier, String key) { + return EnumerationUtil.asIterator(carrier.getHeaders().getValues(key)); + } } diff --git a/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/ApplicationRequestGetter.kt b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/ApplicationRequestGetter.kt index 60313cfb4b00..0a5eafdf7b88 100644 --- a/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/ApplicationRequestGetter.kt +++ b/instrumentation/ktor/ktor-1.0/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v1_0/ApplicationRequestGetter.kt @@ -6,10 +6,13 @@ package io.opentelemetry.instrumentation.ktor.v1_0 import io.ktor.request.* -import io.opentelemetry.context.propagation.TextMapGetter +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter +import java.util.Collections -internal object ApplicationRequestGetter : TextMapGetter { +internal object ApplicationRequestGetter : ExtendedTextMapGetter { override fun keys(carrier: ApplicationRequest): Iterable = carrier.headers.names() override fun get(carrier: ApplicationRequest?, name: String): String? = carrier?.headers?.get(name) + + override fun getAll(carrier: ApplicationRequest?, name: String): Iterator = carrier?.headers?.getAll(name)?.iterator() ?: Collections.emptyIterator() } diff --git a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt index f11cd9513ee7..ad03ba2b8810 100644 --- a/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt +++ b/instrumentation/ktor/ktor-2-common/library/src/main/kotlin/io/opentelemetry/instrumentation/ktor/v2_0/common/ApplicationRequestGetter.kt @@ -6,10 +6,13 @@ package io.opentelemetry.instrumentation.ktor.v2_0.common import io.ktor.server.request.* -import io.opentelemetry.context.propagation.TextMapGetter +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter +import java.util.Collections -internal object ApplicationRequestGetter : TextMapGetter { +internal object ApplicationRequestGetter : ExtendedTextMapGetter { override fun keys(carrier: ApplicationRequest): Iterable = carrier.headers.names() override fun get(carrier: ApplicationRequest?, name: String): String? = carrier?.headers?.get(name) + + override fun getAll(carrier: ApplicationRequest?, name: String): Iterator = carrier?.headers?.getAll(name)?.iterator() ?: Collections.emptyIterator() } diff --git a/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherRequestGetter.java b/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherRequestGetter.java index 18f228e2014c..20e80ecd55e6 100644 --- a/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherRequestGetter.java +++ b/instrumentation/liberty/liberty-dispatcher-20.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/liberty/dispatcher/LibertyDispatcherRequestGetter.java @@ -5,9 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.liberty.dispatcher; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Iterator; -enum LibertyDispatcherRequestGetter implements TextMapGetter { +enum LibertyDispatcherRequestGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -19,4 +20,9 @@ public Iterable keys(LibertyRequest carrier) { public String get(LibertyRequest carrier, String key) { return carrier.getHeaderValue(key); } + + @Override + public Iterator getAll(LibertyRequest carrier, String key) { + return carrier.getHeaderValues(key).iterator(); + } } diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHeadersGetter.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHeadersGetter.java index 46c1a763cb11..42406de068d7 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHeadersGetter.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/server/NettyHeadersGetter.java @@ -5,11 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import io.opentelemetry.javaagent.instrumentation.netty.v3_8.HttpRequestAndChannel; +import java.util.Iterator; import javax.annotation.Nullable; -enum NettyHeadersGetter implements TextMapGetter { +enum NettyHeadersGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -22,4 +23,9 @@ public Iterable keys(HttpRequestAndChannel requestAndChannel) { public String get(@Nullable HttpRequestAndChannel requestAndChannel, String s) { return requestAndChannel.request().headers().get(s); } + + @Override + public Iterator getAll(@Nullable HttpRequestAndChannel carrier, String key) { + return carrier.request().headers().getAll(key).iterator(); + } } diff --git a/instrumentation/netty/netty-4-common/library/src/main/java/io/opentelemetry/instrumentation/netty/v4/common/internal/server/HttpRequestHeadersGetter.java b/instrumentation/netty/netty-4-common/library/src/main/java/io/opentelemetry/instrumentation/netty/v4/common/internal/server/HttpRequestHeadersGetter.java index 5de03b96e9a4..3fa51962457f 100644 --- a/instrumentation/netty/netty-4-common/library/src/main/java/io/opentelemetry/instrumentation/netty/v4/common/internal/server/HttpRequestHeadersGetter.java +++ b/instrumentation/netty/netty-4-common/library/src/main/java/io/opentelemetry/instrumentation/netty/v4/common/internal/server/HttpRequestHeadersGetter.java @@ -5,15 +5,18 @@ package io.opentelemetry.instrumentation.netty.v4.common.internal.server; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; 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 enum HttpRequestHeadersGetter implements TextMapGetter { +public enum HttpRequestHeadersGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -26,4 +29,10 @@ public Iterable keys(HttpRequestAndChannel carrier) { public String get(@Nullable HttpRequestAndChannel carrier, String key) { return carrier.request().headers().get(key); } + + @Override + public Iterator getAll(@Nullable HttpRequestAndChannel carrier, String key) { + List list = carrier.request().headers().getAll(key); + return list != null ? list.iterator() : Collections.emptyIterator(); + } } diff --git a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerHeaders.java b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerHeaders.java index 12636cf58889..52956ef52801 100644 --- a/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerHeaders.java +++ b/instrumentation/pekko/pekko-http-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/pekkohttp/v1_0/server/PekkoHttpServerHeaders.java @@ -5,14 +5,18 @@ package io.opentelemetry.javaagent.instrumentation.pekkohttp.v1_0.server; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import org.apache.pekko.http.javadsl.model.HttpHeader; import org.apache.pekko.http.scaladsl.model.HttpRequest; -enum PekkoHttpServerHeaders implements TextMapGetter { +enum PekkoHttpServerHeaders implements ExtendedTextMapGetter { INSTANCE; @Override @@ -27,4 +31,16 @@ public String get(HttpRequest carrier, String key) { Optional header = carrier.getHeader(key); return header.map(HttpHeader::value).orElse(null); } + + @Override + public Iterator getAll(HttpRequest carrier, String key) { + String headerName = key.toLowerCase(Locale.ROOT); + List result = new ArrayList<>(); + for (HttpHeader header : carrier.getHeaders()) { + if (header.is(headerName)) { + result.add(header.value()); + } + } + return result.iterator(); + } } diff --git a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java index b50e28244418..4d1c50a69299 100644 --- a/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java +++ b/instrumentation/ratpack/ratpack-1.7/library/src/main/java/io/opentelemetry/instrumentation/ratpack/v1_7/internal/RatpackGetter.java @@ -5,7 +5,9 @@ package io.opentelemetry.instrumentation.ratpack.v1_7.internal; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Collections; +import java.util.Iterator; import javax.annotation.Nullable; import ratpack.http.Request; @@ -13,7 +15,7 @@ * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -enum RatpackGetter implements TextMapGetter { +enum RatpackGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -29,4 +31,12 @@ public String get(@Nullable Request request, String key) { } return request.getHeaders().get(key); } + + @Override + public Iterator getAll(@Nullable Request request, String key) { + if (request == null) { + return Collections.emptyIterator(); + } + return request.getHeaders().getAll(key).iterator(); + } } diff --git a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/internal/RestletHeadersGetter.java b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/internal/RestletHeadersGetter.java index 7f137049d502..fe42c4c9e3d9 100644 --- a/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/internal/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-1.1/library/src/main/java/io/opentelemetry/instrumentation/restlet/v1_1/internal/RestletHeadersGetter.java @@ -5,13 +5,15 @@ package io.opentelemetry.instrumentation.restlet.v1_1.internal; -import io.opentelemetry.context.propagation.TextMapGetter; -import java.util.Locale; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Iterator; +import java.util.stream.Collectors; import org.restlet.data.Form; import org.restlet.data.Message; +import org.restlet.data.Parameter; import org.restlet.data.Request; -enum RestletHeadersGetter implements TextMapGetter { +enum RestletHeadersGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -21,14 +23,17 @@ public Iterable keys(Request carrier) { @Override public String get(Request carrier, String key) { - Form headers = getHeaders(carrier); + return headers.getFirstValue(key, true); + } - String value = headers.getFirstValue(key); - if (value != null) { - return value; - } - return headers.getFirstValue(key.toLowerCase(Locale.ROOT)); + @Override + public Iterator getAll(Request carrier, String key) { + Form headers = getHeaders(carrier); + return headers.subList(key, true).stream() + .map(Parameter::getValue) + .collect(Collectors.toList()) + .iterator(); } static Form getHeaders(Message carrier) { diff --git a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java index 50afe5a8406a..aa23f0e2b2ac 100644 --- a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java @@ -7,10 +7,12 @@ import static java.util.Collections.emptySet; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.Arrays; +import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentMap; import javax.annotation.Nullable; @@ -18,7 +20,7 @@ import org.restlet.Request; import org.restlet.util.Series; -final class RestletHeadersGetter implements TextMapGetter { +final class RestletHeadersGetter implements ExtendedTextMapGetter { private static final MethodHandle GET_ATTRIBUTES; @@ -55,6 +57,14 @@ public String get(Request carrier, String key) { return headers == null ? null : headers.getFirstValue(key, /* ignoreCase= */ true); } + @Override + public Iterator getAll(Request carrier, String key) { + Series headers = getHeaders(carrier); + return headers == null + ? null + : Arrays.asList(headers.getValuesArray(key, /* ignoreCase= */ true)).iterator(); + } + @SuppressWarnings("unchecked") @Nullable static Series getHeaders(Message carrier) { diff --git a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestGetter.java b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestGetter.java index 676d98bc4b83..6292c85636cf 100644 --- a/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestGetter.java +++ b/instrumentation/servlet/servlet-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/ServletRequestGetter.java @@ -5,10 +5,11 @@ package io.opentelemetry.javaagent.instrumentation.servlet; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Iterator; public class ServletRequestGetter - implements TextMapGetter> { + implements ExtendedTextMapGetter> { protected final ServletAccessor accessor; public ServletRequestGetter(ServletAccessor accessor) { @@ -24,4 +25,9 @@ public Iterable keys(ServletRequestContext carrier) { public String get(ServletRequestContext carrier, String key) { return accessor.getRequestHeader(carrier.request(), key); } + + @Override + public Iterator getAll(ServletRequestContext carrier, String key) { + return accessor.getRequestHeaderValues(carrier.request(), key).iterator(); + } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java index 8d80e96ee56f..282de66ee23c 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java @@ -5,11 +5,14 @@ package io.opentelemetry.instrumentation.spring.webflux.v5_3; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; import javax.annotation.Nullable; import org.springframework.web.server.ServerWebExchange; -enum WebfluxTextMapGetter implements TextMapGetter { +enum WebfluxTextMapGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -25,4 +28,13 @@ public String get(@Nullable ServerWebExchange exchange, String key) { } return exchange.getRequest().getHeaders().getFirst(key); } + + @Override + public Iterator getAll(@Nullable ServerWebExchange exchange, String key) { + if (exchange == null) { + return Collections.emptyIterator(); + } + List list = exchange.getRequest().getHeaders().get(key); + return list != null ? list.iterator() : Collections.emptyIterator(); + } } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/JavaxHttpServletRequestGetter.java b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/JavaxHttpServletRequestGetter.java index 955c074a1b58..85486e50ba53 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/JavaxHttpServletRequestGetter.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/JavaxHttpServletRequestGetter.java @@ -5,11 +5,9 @@ package io.opentelemetry.instrumentation.spring.webmvc.v5_3; -import static java.util.Collections.emptyIterator; - import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import io.opentelemetry.instrumentation.api.internal.EnumerationUtil; import java.util.Collections; -import java.util.Enumeration; import java.util.Iterator; import javax.servlet.http.HttpServletRequest; @@ -28,21 +26,6 @@ public String get(HttpServletRequest carrier, String key) { @Override public Iterator getAll(HttpServletRequest carrier, String key) { - Enumeration values = carrier.getHeaders(key); - if (values == null) { - return emptyIterator(); - } - - return new Iterator() { - @Override - public boolean hasNext() { - return values.hasMoreElements(); - } - - @Override - public String next() { - return values.nextElement(); - } - }; + return EnumerationUtil.asIterator(carrier.getHeaders(key)); } } diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/WebMvcHttpServerTest.java b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/WebMvcHttpServerTest.java index f13b1f1a98f4..d0a69337c7de 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/WebMvcHttpServerTest.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/src/test/java/io/opentelemetry/instrumentation/spring/webmvc/v5_3/WebMvcHttpServerTest.java @@ -53,8 +53,6 @@ protected void configure(HttpServerTestOptions options) { } return expectedHttpRoute(endpoint, method); }); - - options.setTestExtractMultiBaggage(true); } @Test diff --git a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/JakartaHttpServletRequestGetter.java b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/JakartaHttpServletRequestGetter.java index 2955fb5d7b25..7541bd981ad1 100644 --- a/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/JakartaHttpServletRequestGetter.java +++ b/instrumentation/spring/spring-webmvc/spring-webmvc-6.0/library/src/main/java/io/opentelemetry/instrumentation/spring/webmvc/v6_0/JakartaHttpServletRequestGetter.java @@ -5,11 +5,13 @@ package io.opentelemetry.instrumentation.spring.webmvc.v6_0; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import io.opentelemetry.instrumentation.api.internal.EnumerationUtil; import jakarta.servlet.http.HttpServletRequest; import java.util.Collections; +import java.util.Iterator; -enum JakartaHttpServletRequestGetter implements TextMapGetter { +enum JakartaHttpServletRequestGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -21,4 +23,9 @@ public Iterable keys(HttpServletRequest carrier) { public String get(HttpServletRequest carrier, String key) { return carrier.getHeader(key); } + + @Override + public Iterator getAll(HttpServletRequest carrier, String key) { + return EnumerationUtil.asIterator(carrier.getHeaders(key)); + } } diff --git a/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatRequestGetter.java b/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatRequestGetter.java index 5f7d2becd7a9..84736121bbd6 100644 --- a/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatRequestGetter.java +++ b/instrumentation/tomcat/tomcat-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/tomcat/common/TomcatRequestGetter.java @@ -5,11 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.tomcat.common; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; +import io.opentelemetry.instrumentation.api.internal.EnumerationUtil; import java.util.Collections; +import java.util.Iterator; import org.apache.coyote.Request; -enum TomcatRequestGetter implements TextMapGetter { +enum TomcatRequestGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -21,4 +23,9 @@ public Iterable keys(Request carrier) { public String get(Request carrier, String key) { return carrier.getHeader(key); } + + @Override + public Iterator getAll(Request carrier, String key) { + return EnumerationUtil.asIterator(carrier.getMimeHeaders().values(key)); + } } diff --git a/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowExchangeGetter.java b/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowExchangeGetter.java index 24869e7fc3a2..0c8b1fa7d899 100644 --- a/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowExchangeGetter.java +++ b/instrumentation/undertow-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/undertow/UndertowExchangeGetter.java @@ -5,12 +5,15 @@ package io.opentelemetry.javaagent.instrumentation.undertow; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import io.undertow.server.HttpServerExchange; +import io.undertow.util.HeaderValues; import io.undertow.util.HttpString; +import java.util.Collections; +import java.util.Iterator; import java.util.stream.Collectors; -enum UndertowExchangeGetter implements TextMapGetter { +enum UndertowExchangeGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -24,4 +27,10 @@ public Iterable keys(HttpServerExchange carrier) { public String get(HttpServerExchange carrier, String key) { return carrier.getRequestHeaders().getFirst(key); } + + @Override + public Iterator getAll(HttpServerExchange carrier, String key) { + HeaderValues headerValues = carrier.getRequestHeaders().get(key); + return headerValues != null ? headerValues.iterator() : Collections.emptyIterator(); + } } diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/test/server/http/RequestContextGetter.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/test/server/http/RequestContextGetter.java index dcb296380773..9d964f428862 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/test/server/http/RequestContextGetter.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/test/server/http/RequestContextGetter.java @@ -5,14 +5,15 @@ package io.opentelemetry.instrumentation.test.server.http; -import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; import io.opentelemetry.testing.internal.armeria.server.ServiceRequestContext; import io.opentelemetry.testing.internal.io.netty.util.AsciiString; import java.util.Collections; +import java.util.Iterator; import java.util.stream.Collectors; import javax.annotation.Nullable; -public enum RequestContextGetter implements TextMapGetter { +public enum RequestContextGetter implements ExtendedTextMapGetter { INSTANCE; @Override @@ -33,4 +34,12 @@ public String get(@Nullable ServiceRequestContext carrier, String key) { } return carrier.request().headers().get(key); } + + @Override + public Iterator getAll(@Nullable ServiceRequestContext carrier, String key) { + if (carrier == null) { + return Collections.emptyIterator(); + } + return carrier.request().headers().valueIterator(key); + } } diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java index 93940b0551bb..8fa507bd7980 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/AbstractHttpServerTest.java @@ -568,8 +568,6 @@ void extractSingleBaggage() { @Test void extractMultiBaggage() { - assumeTrue(options.testExtractMultiBaggage); - String method = "GET"; AggregatedHttpRequest request = AggregatedHttpRequest.of( diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java index 8023050f57d3..13e79b8f31b7 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/junit/http/HttpServerTestOptions.java @@ -64,7 +64,6 @@ public final class HttpServerTestOptions { boolean testNonStandardHttpMethod = true; boolean verifyServerSpanEndTime = true; boolean useHttp2 = false; - boolean testExtractMultiBaggage = false; HttpServerTestOptions() {} @@ -231,12 +230,6 @@ public HttpServerTestOptions useHttp2() { return setUseHttp2(true); } - @CanIgnoreReturnValue - public HttpServerTestOptions setTestExtractMultiBaggage(boolean testExtractMultiBaggage) { - this.testExtractMultiBaggage = testExtractMultiBaggage; - return this; - } - @FunctionalInterface public interface SpanNameMapper { From 22f7d258c96e05c210242765adbee13f278a23ac Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 20 Jan 2025 10:04:55 +0200 Subject: [PATCH 2/2] addess review comments --- .../restlet/v2_0/internal/RestletHeadersGetter.java | 3 ++- .../spring/webflux/v5_3/WebfluxTextMapGetter.java | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java index aa23f0e2b2ac..28485e3c8702 100644 --- a/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java +++ b/instrumentation/restlet/restlet-2.0/library/src/main/java/io/opentelemetry/instrumentation/restlet/v2_0/internal/RestletHeadersGetter.java @@ -12,6 +12,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentMap; @@ -61,7 +62,7 @@ public String get(Request carrier, String key) { public Iterator getAll(Request carrier, String key) { Series headers = getHeaders(carrier); return headers == null - ? null + ? Collections.emptyIterator() : Arrays.asList(headers.getValuesArray(key, /* ignoreCase= */ true)).iterator(); } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java index 282de66ee23c..b5fef66ce494 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/WebfluxTextMapGetter.java @@ -5,8 +5,9 @@ package io.opentelemetry.instrumentation.spring.webflux.v5_3; +import static java.util.Collections.emptyIterator; + import io.opentelemetry.context.propagation.internal.ExtendedTextMapGetter; -import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.annotation.Nullable; @@ -32,9 +33,9 @@ public String get(@Nullable ServerWebExchange exchange, String key) { @Override public Iterator getAll(@Nullable ServerWebExchange exchange, String key) { if (exchange == null) { - return Collections.emptyIterator(); + return emptyIterator(); } List list = exchange.getRequest().getHeaders().get(key); - return list != null ? list.iterator() : Collections.emptyIterator(); + return list != null ? list.iterator() : emptyIterator(); } }