diff --git a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebHttpAttributesGetter.java b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebHttpAttributesGetter.java index b61433ddaa44..4660f06a9be7 100644 --- a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebHttpAttributesGetter.java +++ b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/v3_1/SpringWebHttpAttributesGetter.java @@ -7,17 +7,18 @@ import static java.util.Collections.emptyList; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalAttributesGetter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.List; +import java.util.Map; import javax.annotation.Nullable; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpResponse; enum SpringWebHttpAttributesGetter - implements HttpClientAttributesGetter { + implements HttpClientExperimentalAttributesGetter { INSTANCE; @Override @@ -107,4 +108,55 @@ public String getServerAddress(HttpRequest httpRequest) { public Integer getServerPort(HttpRequest httpRequest) { return httpRequest.getURI().getPort(); } + + private static final String URI_TEMPLATE_ATTRIBUTE = + "org.springframework.web.client.RestClient.uriTemplate"; + @Nullable private static final MethodHandle GET_ATTRIBUTES; + + static { + MethodHandle getAttributes = null; + Class httpRequestClass = null; + + try { + httpRequestClass = Class.forName("org.springframework.http.HttpRequest"); + } catch (ClassNotFoundException e) { + // ignored + } + + if (httpRequestClass != null) { + MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + try { + getAttributes = + lookup.findVirtual( + httpRequestClass, "getAttributes", MethodType.methodType(java.util.Map.class)); + } catch (NoSuchMethodException | IllegalAccessException ignored) { + // ignored + } + } + + GET_ATTRIBUTES = getAttributes; + } + + @Nullable + @Override + public String getUrlTemplate(HttpRequest httpRequest) { + if (GET_ATTRIBUTES == null) { + return null; + } + + try { + Object attributes = GET_ATTRIBUTES.invoke(httpRequest); + if (attributes instanceof java.util.Map) { + Map map = (Map) attributes; + Object value = map.get(URI_TEMPLATE_ATTRIBUTE); + if (value instanceof String) { + return (String) value; + } + } + } catch (Throwable e) { + // ignore + } + + return null; + } } diff --git a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/WebClientHttpAttributesGetter.java b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/WebClientHttpAttributesGetter.java index 80c75f68a61d..226c759373b4 100644 --- a/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/WebClientHttpAttributesGetter.java +++ b/instrumentation/spring/spring-webflux/spring-webflux-5.3/library/src/main/java/io/opentelemetry/instrumentation/spring/webflux/v5_3/internal/WebClientHttpAttributesGetter.java @@ -7,20 +7,39 @@ import static java.util.Collections.emptyList; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalAttributesGetter; import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; import javax.annotation.Nullable; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.WebClient; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ public enum WebClientHttpAttributesGetter - implements HttpClientAttributesGetter { + implements HttpClientExperimentalAttributesGetter { INSTANCE; + private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate"; + private static final Pattern PATTERN_BEFORE_PATH = Pattern.compile("^https?://[^/]+/"); + + @Nullable + @Override + public String getUrlTemplate(ClientRequest clientRequest) { + Map attributes = clientRequest.attributes(); + Object value = attributes.get(URI_TEMPLATE_ATTRIBUTE); + if (value instanceof String) { + String uriTemplate = (String) value; + String path = PATTERN_BEFORE_PATH.matcher(uriTemplate).replaceFirst(""); + return path.startsWith("/") ? path : "/" + path; + } + return null; + } + @Override public String getUrlFull(ClientRequest request) { return request.url().toString();