From ca85a0db3d2d1717853e3e8062bf58b82958c67f Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Fri, 13 Jan 2023 06:08:15 +0100 Subject: [PATCH] Support Spring Web 6 in library instrumentation (#7551) Part of https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/7312 --- .../spring-web-3.1/library/build.gradle.kts | 10 +++- .../web/SpringWebHttpAttributesGetter.java | 56 +++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/instrumentation/spring/spring-web/spring-web-3.1/library/build.gradle.kts b/instrumentation/spring/spring-web/spring-web-3.1/library/build.gradle.kts index 8cb5fe03b2cb..f852b2dccbcc 100644 --- a/instrumentation/spring/spring-web/spring-web-3.1/library/build.gradle.kts +++ b/instrumentation/spring/spring-web/spring-web-3.1/library/build.gradle.kts @@ -6,8 +6,16 @@ dependencies { compileOnly("org.springframework:spring-web:3.1.0.RELEASE") testLibrary("org.springframework:spring-web:3.1.0.RELEASE") - latestDepTestLibrary("org.springframework:spring-web:5.+") testImplementation(project(":testing-common")) testImplementation("io.opentelemetry:opentelemetry-sdk-testing") } + +val latestDepTest = findProperty("testLatestDeps") as Boolean + +// spring 6 requires java 17 +if (latestDepTest) { + otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) + } +} diff --git a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/SpringWebHttpAttributesGetter.java b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/SpringWebHttpAttributesGetter.java index 50eaf7062f04..cb23d525d2de 100644 --- a/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/SpringWebHttpAttributesGetter.java +++ b/instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/SpringWebHttpAttributesGetter.java @@ -8,11 +8,12 @@ import static java.util.Collections.emptyList; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesGetter; -import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.List; import javax.annotation.Nullable; import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; enum SpringWebHttpAttributesGetter @@ -41,13 +42,58 @@ public String flavor(HttpRequest httpRequest, @Nullable ClientHttpResponse clien return null; } + @Nullable private static final MethodHandle GET_STATUS_CODE; + + @Nullable private static final MethodHandle STATUS_CODE_VALUE; + + static { + MethodHandle getStatusCode = null; + MethodHandle statusCodeValue = null; + Class httpStatusCodeClass = null; + + MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + + try { + httpStatusCodeClass = Class.forName("org.springframework.http.HttpStatusCode"); + } catch (ClassNotFoundException e) { + try { + httpStatusCodeClass = Class.forName("org.springframework.http.HttpStatus"); + } catch (ClassNotFoundException ignored) { + // ignored + } + } + + if (httpStatusCodeClass != null) { + try { + getStatusCode = + lookup.findVirtual( + ClientHttpResponse.class, + "getStatusCode", + MethodType.methodType(httpStatusCodeClass)); + statusCodeValue = + lookup.findVirtual(httpStatusCodeClass, "value", MethodType.methodType(int.class)); + } catch (NoSuchMethodException | IllegalAccessException ignored) { + // ignored + } + } + + GET_STATUS_CODE = getStatusCode; + STATUS_CODE_VALUE = statusCodeValue; + } + @Override public Integer statusCode( HttpRequest httpRequest, ClientHttpResponse clientHttpResponse, @Nullable Throwable error) { + + if (GET_STATUS_CODE == null || STATUS_CODE_VALUE == null) { + return null; + } + try { - return clientHttpResponse.getStatusCode().value(); - } catch (IOException e) { - return HttpStatus.INTERNAL_SERVER_ERROR.value(); + Object statusCode = GET_STATUS_CODE.invoke(clientHttpResponse); + return (int) STATUS_CODE_VALUE.invoke(statusCode); + } catch (Throwable e) { + return null; } }