Browse Source

Enable http pipelining test on Grizzly (#8411)

Lauri Tulmin 1 year ago
parent
commit
60aa4215f6

+ 77 - 0
instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java

@@ -0,0 +1,77 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.grizzly;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+
+import io.opentelemetry.context.Scope;
+import io.opentelemetry.javaagent.bootstrap.CallDepth;
+import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
+import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
+import net.bytebuddy.asm.Advice;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.glassfish.grizzly.filterchain.FilterChainContext;
+
+public class FilterChainContextInstrumentation implements TypeInstrumentation {
+  @Override
+  public ElementMatcher<TypeDescription> typeMatcher() {
+    return named("org.glassfish.grizzly.filterchain.FilterChainContext");
+  }
+
+  @Override
+  public void transform(TypeTransformer transformer) {
+    transformer.applyAdviceToMethod(
+        named("resume").and(takesArguments(0)),
+        FilterChainContextInstrumentation.class.getName() + "$ResumeAdvice");
+    transformer.applyAdviceToMethod(
+        named("write"), FilterChainContextInstrumentation.class.getName() + "$WriteAdvice");
+  }
+
+  @SuppressWarnings("unused")
+  public static class ResumeAdvice {
+
+    @Advice.OnMethodEnter(suppress = Throwable.class)
+    public static Scope onEnter() {
+      return Java8BytecodeBridge.rootContext().makeCurrent();
+    }
+
+    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
+    public static void onExit(@Advice.Enter Scope scope) {
+      if (scope != null) {
+        scope.close();
+      }
+    }
+  }
+
+  @SuppressWarnings("unused")
+  public static class WriteAdvice {
+
+    @Advice.OnMethodEnter(suppress = Throwable.class)
+    public static void onEnter(@Advice.Local("otelCallDepth") CallDepth callDepth) {
+      callDepth = CallDepth.forClass(FilterChainContext.class);
+      callDepth.getAndIncrement();
+    }
+
+    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
+    public static void onExit(
+        @Advice.This FilterChainContext filterChainContext,
+        @Advice.Local("otelCallDepth") CallDepth callDepth) {
+      // When exiting the outermost call to write clear context & request from filter chain context.
+      // Write makes a copy of the current filter chain context and passes it on. In older versions
+      // new and old filter chain context share the attributes, but in newer versions the attributes
+      // are also copied. We need to remove the attributes here to ensure that the next request
+      // starts with clean state, failing to do so causes http pipelining test to fail with the
+      // latest deps.
+      if (callDepth.decrementAndGet() == 0) {
+        GrizzlyStateStorage.removeContext(filterChainContext);
+        GrizzlyStateStorage.removeRequest(filterChainContext);
+      }
+    }
+  }
+}

+ 2 - 1
instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java

@@ -25,6 +25,7 @@ public class GrizzlyInstrumentationModule extends InstrumentationModule {
         new FilterInstrumentation(),
         new HttpCodecFilterInstrumentation(),
         new HttpServerFilterInstrumentation(),
-        new HttpHandlerInstrumentation());
+        new HttpHandlerInstrumentation(),
+        new FilterChainContextInstrumentation());
   }
 }

+ 0 - 5
instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyAsyncTest.groovy

@@ -39,11 +39,6 @@ class GrizzlyAsyncTest extends GrizzlyTest {
     false
   }
 
-  @Override
-  boolean testHttpPipelining() {
-    false
-  }
-
   @Override
   boolean verifyServerSpanEndTime() {
     // server spans are ended inside of the JAX-RS controller spans

+ 0 - 5
instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyFilterchainServerTest.groovy

@@ -84,11 +84,6 @@ class GrizzlyFilterchainServerTest extends HttpServerTest<HttpServer> implements
     false
   }
 
-  @Override
-  boolean testHttpPipelining() {
-    false
-  }
-
   @Override
   boolean verifyServerSpanEndTime() {
     // server spans are ended inside of the controller spans

+ 0 - 5
instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyTest.groovy

@@ -68,11 +68,6 @@ class GrizzlyTest extends HttpServerTest<HttpServer> implements AgentTestTrait {
     false
   }
 
-  @Override
-  boolean testHttpPipelining() {
-    false
-  }
-
   static class SimpleExceptionMapper implements ExceptionMapper<Throwable> {
 
     @Override