From 85ede52b5cc91cabe20b3685c8ebc83720e7c3b4 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Wed, 18 Nov 2020 12:34:35 +0100 Subject: [PATCH] Use instrumentation modules (#123) * Use instrumentation module Signed-off-by: Pavol Loffay * add more Signed-off-by: Pavol Loffay * fix muzzle Signed-off-by: Pavol Loffay * revert muzzle Signed-off-by: Pavol Loffay --- .../v1_5/GrpcBodyInstrumentationModule.java | 58 ++++++++++++ .../client/GrpcClientBodyInstrumentation.java | 26 +---- .../server/GrpcServerBodyInstrumentation.java | 27 +----- ... => OkHttp3BodyInstrumentationModule.java} | 40 +++++--- .../servlet/servlet-2.3/build.gradle.kts | 2 +- ...=> Servlet2BodyInstrumentationModule.java} | 62 +++++++----- ...> Servlet30BodyInstrumentationModule.java} | 61 +++++++----- .../v3_1/Servlet31BodyInstrumentation.java | 94 ------------------- .../Servlet31BodyInstrumentationModule.java} | 86 +++++++++++------ .../SparkJavaBodyInstrumentationModule.java | 75 +++++++++++++++ 10 files changed, 292 insertions(+), 239 deletions(-) create mode 100644 instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/GrpcBodyInstrumentationModule.java rename instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/{OkHttp3BodyInstrumentation.java => OkHttp3BodyInstrumentationModule.java} (67%) rename instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/{Servlet2BodyInstrumentation.java => Servlet2BodyInstrumentationModule.java} (83%) rename instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/{Servlet30BodyInstrumentation.java => Servlet30BodyInstrumentationModule.java} (84%) delete mode 100644 instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentation.java rename instrumentation/{spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentation.java => servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentationModule.java} (52%) create mode 100644 instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentationModule.java diff --git a/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/GrpcBodyInstrumentationModule.java b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/GrpcBodyInstrumentationModule.java new file mode 100644 index 000000000..218af03e7 --- /dev/null +++ b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/GrpcBodyInstrumentationModule.java @@ -0,0 +1,58 @@ +/* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.instrumentation.hypertrace.grpc.v1_5; + +import com.google.auto.service.AutoService; +import io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.client.GrpcClientBodyInstrumentation; +import io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.server.GrpcServerBodyInstrumentation; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Arrays; +import java.util.List; + +@AutoService(InstrumentationModule.class) +public class GrpcBodyInstrumentationModule extends InstrumentationModule { + + public GrpcBodyInstrumentationModule() { + super("grpc"); + } + + @Override + public int getOrder() { + return 1; + } + + @Override + public String[] helperClassNames() { + return new String[] { + "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.GrpcSpanDecorator", + "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.InstrumentationName", + packageName + ".client.GrpcClientInterceptor", + packageName + ".client.GrpcClientInterceptor$TracingClientCall", + packageName + ".client.GrpcClientInterceptor$TracingClientCallListener", + packageName + ".server.GrpcServerInterceptor", + packageName + ".server.GrpcServerInterceptor$TracingServerCall", + packageName + ".server.GrpcServerInterceptor$TracingServerCallListener", + packageName + ".server.NoopServerCallListener" + }; + } + + @Override + public List typeInstrumentations() { + return Arrays.asList(new GrpcClientBodyInstrumentation(), new GrpcServerBodyInstrumentation()); + } +} diff --git a/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/client/GrpcClientBodyInstrumentation.java b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/client/GrpcClientBodyInstrumentation.java index cf1dabfe6..f848dcad3 100644 --- a/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/client/GrpcClientBodyInstrumentation.java +++ b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/client/GrpcClientBodyInstrumentation.java @@ -22,9 +22,8 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.grpc.ClientInterceptor; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -32,28 +31,7 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class GrpcClientBodyInstrumentation extends Instrumenter.Default { - - public GrpcClientBodyInstrumentation() { - super("grpc"); - } - - @Override - public int getOrder() { - return 1; - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.GrpcSpanDecorator", - "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.InstrumentationName", - packageName + ".GrpcClientInterceptor", - packageName + ".GrpcClientInterceptor$TracingClientCall", - packageName + ".GrpcClientInterceptor$TracingClientCallListener" - }; - } +public class GrpcClientBodyInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/server/GrpcServerBodyInstrumentation.java b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/server/GrpcServerBodyInstrumentation.java index df76bd3db..bf16ec076 100644 --- a/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/server/GrpcServerBodyInstrumentation.java +++ b/instrumentation/grpc-1.5/src/main/java/io/opentelemetry/instrumentation/hypertrace/grpc/v1_5/server/GrpcServerBodyInstrumentation.java @@ -20,9 +20,8 @@ import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; -import com.google.auto.service.AutoService; import io.grpc.ServerInterceptor; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -30,29 +29,7 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -@AutoService(Instrumenter.class) -public class GrpcServerBodyInstrumentation extends Instrumenter.Default { - - public GrpcServerBodyInstrumentation() { - super("grpc"); - } - - @Override - public int getOrder() { - return 1; - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.GrpcSpanDecorator", - "io.opentelemetry.instrumentation.hypertrace.grpc.v1_5.InstrumentationName", - packageName + ".GrpcServerInterceptor", - packageName + ".GrpcServerInterceptor$TracingServerCall", - packageName + ".GrpcServerInterceptor$TracingServerCallListener", - packageName + ".NoopServerCallListener" - }; - } +public class GrpcServerBodyInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentation.java b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentationModule.java similarity index 67% rename from instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentation.java rename to instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentationModule.java index 13f0baf37..5c7c5a512 100644 --- a/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentation.java +++ b/instrumentation/okhttp/okhttp-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/okhttp/v3_0/OkHttp3BodyInstrumentationModule.java @@ -22,7 +22,10 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.method.MethodDescription; @@ -31,10 +34,10 @@ import okhttp3.Interceptor; import okhttp3.OkHttpClient; -@AutoService(Instrumenter.class) -public class OkHttp3BodyInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class OkHttp3BodyInstrumentationModule extends InstrumentationModule { - public OkHttp3BodyInstrumentation() { + public OkHttp3BodyInstrumentationModule() { super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); } @@ -44,22 +47,29 @@ public int getOrder() { } @Override - public ElementMatcher typeMatcher() { - return named("okhttp3.OkHttpClient"); + public String[] helperClassNames() { + return new String[] { + packageName + ".InstrumentationName", packageName + ".OkHttpTracingInterceptor", + }; } @Override - public Map, String> transformers() { - return singletonMap( - isConstructor().and(takesArgument(0, named("okhttp3.OkHttpClient$Builder"))), - OkHttp3BodyInstrumentation.class.getName() + "$OkHttp3Advice"); + public List typeInstrumentations() { + return Collections.singletonList(new OkHttp3BodyInstrumentation()); } - @Override - public String[] helperClassNames() { - return new String[] { - packageName + ".InstrumentationName", packageName + ".OkHttpTracingInterceptor", - }; + private static final class OkHttp3BodyInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("okhttp3.OkHttpClient"); + } + + @Override + public Map, String> transformers() { + return singletonMap( + isConstructor().and(takesArgument(0, named("okhttp3.OkHttpClient$Builder"))), + OkHttp3BodyInstrumentationModule.class.getName() + "$OkHttp3Advice"); + } } public static class OkHttp3Advice { diff --git a/instrumentation/servlet/servlet-2.3/build.gradle.kts b/instrumentation/servlet/servlet-2.3/build.gradle.kts index f87fd416b..74988355c 100644 --- a/instrumentation/servlet/servlet-2.3/build.gradle.kts +++ b/instrumentation/servlet/servlet-2.3/build.gradle.kts @@ -14,7 +14,7 @@ muzzle { fail { group = "javax.servlet" module = "javax.servlet-api" - versions = "(,)" + versions = "(3.0.1,)" } } diff --git a/instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentation.java b/instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentationModule.java similarity index 83% rename from instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentation.java rename to instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentationModule.java index 5c001506f..94d0a8f2d 100644 --- a/instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentation.java +++ b/instrumentation/servlet/servlet-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v2_3/Servlet2BodyInstrumentationModule.java @@ -29,7 +29,9 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.hypertrace.servlet.common.ServletSpanDecorator; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; @@ -52,10 +54,10 @@ * version 2.2, however this implementation uses request and response wrappers that were introduced * in 2.3. */ -@AutoService(Instrumenter.class) -public class Servlet2BodyInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class Servlet2BodyInstrumentationModule extends InstrumentationModule { - public Servlet2BodyInstrumentation() { + public Servlet2BodyInstrumentationModule() { super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); } @@ -64,21 +66,6 @@ public int getOrder() { return 1; } - // this is required to make sure servlet 2 instrumentation won't apply to servlet 3 - @Override - public ElementMatcher classLoaderMatcher() { - // Request/response wrappers are available since servlet 2.3! - return hasClassesNamed( - "javax.servlet.http.HttpServlet", "javax.servlet.http.HttpServletRequestWrapper") - .and(not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener"))); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); - } - @Override public Map contextStore() { return singletonMap("javax.servlet.ServletResponse", Integer.class.getName()); @@ -102,13 +89,36 @@ public String[] helperClassNames() { } @Override - public Map, String> transformers() { - return singletonMap( - namedOneOf("doFilter", "service") - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - Filter2Advice.class.getName()); + public List typeInstrumentations() { + return Collections.singletonList(new Servlet2BodyInstrumentation()); + } + + public static class Servlet2BodyInstrumentation implements TypeInstrumentation { + + // this is required to make sure servlet 2 instrumentation won't apply to servlet 3 + @Override + public ElementMatcher classLoaderMatcher() { + // Request/response wrappers are available since servlet 2.3! + return hasClassesNamed( + "javax.servlet.http.HttpServlet", "javax.servlet.http.HttpServletRequestWrapper") + .and(not(hasClassesNamed("javax.servlet.AsyncEvent", "javax.servlet.AsyncListener"))); + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType( + namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + namedOneOf("doFilter", "service") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + Filter2Advice.class.getName()); + } } public static class Filter2Advice { diff --git a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentation.java b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentationModule.java similarity index 84% rename from instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentation.java rename to instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentationModule.java index 4bc8a6dae..5a03587c8 100644 --- a/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentation.java +++ b/instrumentation/servlet/servlet-3.0/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_0/Servlet30BodyInstrumentationModule.java @@ -29,9 +29,12 @@ import io.opentelemetry.api.trace.Span; import io.opentelemetry.instrumentation.hypertrace.servlet.common.ServletSpanDecorator; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.ServletRequest; @@ -47,10 +50,10 @@ import org.hypertrace.agent.filter.FilterRegistry; import org.hypertrace.agent.filter.api.FilterResult; -@AutoService(Instrumenter.class) -public class Servlet30BodyInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class Servlet30BodyInstrumentationModule extends InstrumentationModule { - public Servlet30BodyInstrumentation() { + public Servlet30BodyInstrumentationModule() { super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); } @@ -63,20 +66,6 @@ public int getOrder() { return 1; } - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - // ReadListener was added in 3.1 - return hasClassesNamed("javax.servlet.http.HttpServlet", "javax.servlet.AsyncEvent") - .and(not(hasClassesNamed("javax.servlet.ReadListener"))); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); - } - @Override public String[] helperClassNames() { return new String[] { @@ -96,13 +85,35 @@ public String[] helperClassNames() { } @Override - public Map, String> transformers() { - return singletonMap( - namedOneOf("doFilter", "service") - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - FilterAdvice.class.getName()); + public List typeInstrumentations() { + return Collections.singletonList(new Servlet30BodyInstrumentation()); + } + + private static class Servlet30BodyInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + // ReadListener was added in 3.1 + return hasClassesNamed("javax.servlet.http.HttpServlet", "javax.servlet.AsyncEvent") + .and(not(hasClassesNamed("javax.servlet.ReadListener"))); + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType( + namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + namedOneOf("doFilter", "service") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + FilterAdvice.class.getName()); + } } public static class FilterAdvice { diff --git a/instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentation.java b/instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentation.java deleted file mode 100644 index a1d44e487..000000000 --- a/instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentation.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright The Hypertrace Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.opentelemetry.instrumentation.hypertrace.servlet.v3_1; - -import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; -import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; -import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; -import static java.util.Collections.singletonMap; -import static net.bytebuddy.matcher.ElementMatchers.isPublic; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.tooling.Instrumenter; -import java.util.Map; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.description.type.TypeDescription; -import net.bytebuddy.matcher.ElementMatcher; - -/** - * TODO https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1395 is resolved - * move this to org.hypertrace package. - */ -@AutoService(Instrumenter.class) -public class Servlet31BodyInstrumentation extends Instrumenter.Default { - - public Servlet31BodyInstrumentation() { - super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); - } - - @Override - public int getOrder() { - /** - * Order 1 assures that this instrumentation runs after OTEL servlet instrumentation so we can - * access current span in our advice. - */ - return 1; - } - - @Override - public ElementMatcher classLoaderMatcher() { - // Optimization for expensive typeMatcher. - return hasClassesNamed("javax.servlet.http.HttpServlet", "javax.servlet.ReadListener"); - } - - @Override - public ElementMatcher typeMatcher() { - return safeHasSuperType( - namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); - } - - @Override - public String[] helperClassNames() { - return new String[] { - "io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge", - "io.opentelemetry.instrumentation.hypertrace.servlet.common.ByteBufferData", - "io.opentelemetry.instrumentation.hypertrace.servlet.common.CharBufferData", - "io.opentelemetry.instrumentation.hypertrace.servlet.common.BufferedWriterWrapper", - "io.opentelemetry.instrumentation.hypertrace.servlet.common.BufferedReaderWrapper", - "io.opentelemetry.instrumentation.hypertrace.servlet.common.ServletSpanDecorator", - packageName + ".InstrumentationName", - packageName + ".BufferingHttpServletResponse", - packageName + ".BufferingHttpServletResponse$BufferingServletOutputStream", - packageName + ".BufferingHttpServletRequest", - packageName + ".BufferingHttpServletRequest$ServletInputStreamWrapper", - packageName + ".BodyCaptureAsyncListener", - packageName + ".Servlet31Advice", - }; - } - - @Override - public Map, String> transformers() { - return singletonMap( - namedOneOf("doFilter", "service") - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - Servlet31Advice.class.getName()); - } -} diff --git a/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentation.java b/instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentationModule.java similarity index 52% rename from instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentation.java rename to instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentationModule.java index 6fcd929d9..bc167b1da 100644 --- a/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentation.java +++ b/instrumentation/servlet/servlet-3.1/src/main/java/io/opentelemetry/instrumentation/hypertrace/servlet/v3_1/Servlet31BodyInstrumentationModule.java @@ -14,8 +14,10 @@ * limitations under the License. */ -package io.opentelemetry.instrumentation.hypertrace.sparkjava; +package io.opentelemetry.instrumentation.hypertrace.servlet.v3_1; +import static io.opentelemetry.javaagent.tooling.ClassLoaderMatcher.hasClassesNamed; +import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.safeHasSuperType; import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -23,43 +25,38 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import com.google.auto.service.AutoService; -import io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.Servlet31Advice; -import io.opentelemetry.javaagent.tooling.Instrumenter; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; import java.util.Map; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; /** - * {@code Spark.after} is not being called if a handler throws an exception. Exception handler - * {@code Spark.exception} cannot be used because it overrides user defined exception handlers. This - * might be fine as on exception there is usually not body send to users. + * TODO https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/1395 is resolved + * move this to org.hypertrace package. */ -@AutoService(Instrumenter.class) -public class SparkJavaBodyInstrumentation extends Instrumenter.Default { +@AutoService(InstrumentationModule.class) +public class Servlet31BodyInstrumentationModule extends InstrumentationModule { - public SparkJavaBodyInstrumentation() { + public Servlet31BodyInstrumentationModule() { super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); } - @Override - public int getOrder() { - return 1; - } - - @Override - public ElementMatcher typeMatcher() { - return named("spark.webserver.MatcherFilter").or(named("spark.http.matching.MatcherFilter")); + public Servlet31BodyInstrumentationModule( + String mainInstrumentationName, String... otherInstrumentationNames) { + super(mainInstrumentationName, otherInstrumentationNames); } @Override - public Map, String> transformers() { - return singletonMap( - namedOneOf("doFilter") - .and(takesArgument(0, named("javax.servlet.ServletRequest"))) - .and(takesArgument(1, named("javax.servlet.ServletResponse"))) - .and(isPublic()), - Servlet31Advice.class.getName()); + public int getOrder() { + /** + * Order 1 assures that this instrumentation runs after OTEL servlet instrumentation so we can + * access current span in our advice. + */ + return 1; } @Override @@ -71,16 +68,47 @@ public String[] helperClassNames() { "io.opentelemetry.instrumentation.hypertrace.servlet.common.BufferedWriterWrapper", "io.opentelemetry.instrumentation.hypertrace.servlet.common.BufferedReaderWrapper", "io.opentelemetry.instrumentation.hypertrace.servlet.common.ServletSpanDecorator", + // This class is extended in spark-web. The package name would be resolved to spark web + // package + // and it would cause failure. + // packageName + ".InstrumentationName", + "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.InstrumentationName", "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.BufferingHttpServletResponse", "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.BufferingHttpServletResponse$BufferingServletOutputStream", "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.BufferingHttpServletRequest", "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.BufferingHttpServletRequest$ServletInputStreamWrapper", - "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.Servlet31Advice", - "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.InstrumentationName", "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.BodyCaptureAsyncListener", - // TODO Instrumentation name is not used in the advice method to check whether - // instrumentation is enabled or not - packageName + ".InstrumentationName", + "io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.Servlet31Advice", }; } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new Servlet31BodyInstrumentation()); + } + + private static final class Servlet31BodyInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher classLoaderMatcher() { + // Optimization for expensive typeMatcher. + return hasClassesNamed("javax.servlet.http.HttpServlet", "javax.servlet.ReadListener"); + } + + @Override + public ElementMatcher typeMatcher() { + return safeHasSuperType( + namedOneOf("javax.servlet.FilterChain", "javax.servlet.http.HttpServlet")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + namedOneOf("doFilter", "service") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + Servlet31Advice.class.getName()); + } + } } diff --git a/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentationModule.java b/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentationModule.java new file mode 100644 index 000000000..54ef1befa --- /dev/null +++ b/instrumentation/spark-web-framework-2.3/src/main/java/io/opentelemetry/instrumentation/hypertrace/sparkjava/SparkJavaBodyInstrumentationModule.java @@ -0,0 +1,75 @@ +/* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.instrumentation.hypertrace.sparkjava; + +import static io.opentelemetry.javaagent.tooling.matcher.NameMatchers.namedOneOf; +import static java.util.Collections.singletonMap; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import com.google.auto.service.AutoService; +import io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.Servlet31Advice; +import io.opentelemetry.instrumentation.hypertrace.servlet.v3_1.Servlet31BodyInstrumentationModule; +import io.opentelemetry.javaagent.tooling.InstrumentationModule; +import io.opentelemetry.javaagent.tooling.TypeInstrumentation; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +/** + * {@code Spark.after} is not being called if a handler throws an exception. Exception handler + * {@code Spark.exception} cannot be used because it overrides user defined exception handlers. This + * might be fine as on exception there is usually not body send to users. + */ +@AutoService(InstrumentationModule.class) +public class SparkJavaBodyInstrumentationModule extends Servlet31BodyInstrumentationModule { + + public SparkJavaBodyInstrumentationModule() { + super(InstrumentationName.INSTRUMENTATION_NAME[0], InstrumentationName.INSTRUMENTATION_NAME[1]); + } + + @Override + public int getOrder() { + return 1; + } + + @Override + public List typeInstrumentations() { + return Collections.singletonList(new SparkJavaBodyInstrumentation()); + } + + private static class SparkJavaBodyInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("spark.webserver.MatcherFilter").or(named("spark.http.matching.MatcherFilter")); + } + + @Override + public Map, String> transformers() { + return singletonMap( + namedOneOf("doFilter") + .and(takesArgument(0, named("javax.servlet.ServletRequest"))) + .and(takesArgument(1, named("javax.servlet.ServletResponse"))) + .and(isPublic()), + Servlet31Advice.class.getName()); + } + } +}