From 3c1798935780e9f0cf3d30c75b63812ac0249246 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Thu, 4 May 2023 12:58:12 +0300 Subject: [PATCH 1/2] Enable http pipelining test on Grizzly --- .../FilterChainContextInstrumentation.java | 45 +++++++++++++++++++ .../grizzly/GrizzlyInstrumentationModule.java | 3 +- .../src/test/groovy/GrizzlyAsyncTest.groovy | 5 --- .../GrizzlyFilterchainServerTest.groovy | 5 --- .../src/test/groovy/GrizzlyTest.groovy | 5 --- 5 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java diff --git a/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java new file mode 100644 index 000000000000..9c3153e15fcc --- /dev/null +++ b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.grizzly; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +import io.opentelemetry.context.Scope; +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; + +public class FilterChainContextInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.glassfish.grizzly.filterchain.FilterChainContext"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("resume"), FilterChainContextInstrumentation.class.getName() + "$ResumeAdvice"); + } + + @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(); + } + } + } +} diff --git a/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java index 540057559647..a100805c7832 100644 --- a/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java +++ b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/GrizzlyInstrumentationModule.java @@ -25,6 +25,7 @@ public List typeInstrumentations() { new FilterInstrumentation(), new HttpCodecFilterInstrumentation(), new HttpServerFilterInstrumentation(), - new HttpHandlerInstrumentation()); + new HttpHandlerInstrumentation(), + new FilterChainContextInstrumentation()); } } diff --git a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyAsyncTest.groovy b/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyAsyncTest.groovy index 1d5e396ca85f..7475f81a7882 100644 --- a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyAsyncTest.groovy +++ b/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 diff --git a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyFilterchainServerTest.groovy b/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyFilterchainServerTest.groovy index ed72ef5e566a..df603aef684f 100644 --- a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyFilterchainServerTest.groovy +++ b/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyFilterchainServerTest.groovy @@ -84,11 +84,6 @@ class GrizzlyFilterchainServerTest extends HttpServerTest implements false } - @Override - boolean testHttpPipelining() { - false - } - @Override boolean verifyServerSpanEndTime() { // server spans are ended inside of the controller spans diff --git a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyTest.groovy b/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyTest.groovy index 90a34cc33038..6b9d885f1cb7 100644 --- a/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyTest.groovy +++ b/instrumentation/grizzly-2.0/javaagent/src/test/groovy/GrizzlyTest.groovy @@ -68,11 +68,6 @@ class GrizzlyTest extends HttpServerTest implements AgentTestTrait { false } - @Override - boolean testHttpPipelining() { - false - } - static class SimpleExceptionMapper implements ExceptionMapper { @Override From 8972b50c257f1965558f5c1e6aa0212b3ba417e2 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Thu, 4 May 2023 15:26:18 +0300 Subject: [PATCH 2/2] Fix grizzly latest dep test --- .../FilterChainContextInstrumentation.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java index 9c3153e15fcc..52f56c2cf24e 100644 --- a/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java +++ b/instrumentation/grizzly-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/grizzly/FilterChainContextInstrumentation.java @@ -6,14 +6,17 @@ 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 @@ -24,7 +27,10 @@ public ElementMatcher typeMatcher() { @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - named("resume"), FilterChainContextInstrumentation.class.getName() + "$ResumeAdvice"); + named("resume").and(takesArguments(0)), + FilterChainContextInstrumentation.class.getName() + "$ResumeAdvice"); + transformer.applyAdviceToMethod( + named("write"), FilterChainContextInstrumentation.class.getName() + "$WriteAdvice"); } @SuppressWarnings("unused") @@ -42,4 +48,30 @@ public static void onExit(@Advice.Enter Scope scope) { } } } + + @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); + } + } + } }