Bläddra i källkod

Support Spring Web 6 in library instrumentation (#7551)

Part of
https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/7312
Mateusz Rzeszutek 2 år sedan
förälder
incheckning
ca85a0db3d

+ 9 - 1
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)
+  }
+}

+ 51 - 5
instrumentation/spring/spring-web/spring-web-3.1/library/src/main/java/io/opentelemetry/instrumentation/spring/web/SpringWebHttpAttributesGetter.java

@@ -8,11 +8,12 @@ package io.opentelemetry.instrumentation.spring.web;
 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 @@ enum SpringWebHttpAttributesGetter
     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;
     }
   }