From 216299273ed26278cc1a29d9a40c8b38c6921e9b Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Mon, 12 Apr 2021 12:34:29 +0200 Subject: [PATCH 1/2] Generate InstrumentationModule#contextStore() with muzzle --- .../AkkaActorInstrumentationModule.java | 15 ---- .../AsyncHttpClientInstrumentationModule.java | 8 -- .../AsyncHttpClientInstrumentationModule.java | 11 --- .../v2_6/CouchbaseInstrumentationModule.java | 8 -- .../ExecutorInstrumentationModule.java | 17 ---- ...GoogleHttpClientInstrumentationModule.java | 6 -- .../guava/GuavaInstrumentationModule.java | 5 -- .../v3_3/HibernateInstrumentationModule.java | 15 ---- .../v4_0/HibernateInstrumentationModule.java | 14 --- .../v4_3/HibernateInstrumentationModule.java | 12 --- ...ttpUrlConnectionInstrumentationModule.java | 6 -- .../v2_0/JaxRsInstrumentationModule.java | 8 -- .../v8_0/Jetty8InstrumentationModule.java | 6 -- .../jms/JmsInstrumentationModule.java | 7 -- .../v1_2/Log4j1InstrumentationModule.java | 8 -- .../v1_0/LogbackInstrumentationModule.java | 8 -- .../v3_8/NettyInstrumentationModule.java | 8 -- ...ntextPropagationInstrumentationModule.java | 8 -- .../RmiClientContextInstrumentation.java | 1 + .../ScalaConcurrentInstrumentationModule.java | 15 ---- .../v2_2/Servlet2InstrumentationModule.java | 7 -- .../JakartaServletInstrumentationModule.java | 8 -- .../JavaxServletInstrumentationModule.java | 8 -- .../SpringBatchInstrumentationModule.java | 13 --- .../core/SpringCoreInstrumentationModule.java | 8 -- .../VertxClientInstrumentationModule.java | 7 -- .../tooling/InstrumentationModule.java | 26 +++--- .../muzzle/collector/FixedSizeQueue.java | 46 ++++++++++ .../muzzle/collector/MuzzleCodeGenerator.java | 61 +++++++++++++ .../ReferenceCollectingClassVisitor.java | 86 +++++++++++++++++-- .../muzzle/collector/ReferenceCollector.java | 6 ++ .../muzzle/collector/FixedSizeQueueTest.java | 59 +++++++++++++ .../ContextTestInstrumentationModule.java | 28 ------ .../context/FieldBackedProviderTest.groovy | 12 --- .../IncorrectContextClassUsageKeyClass.java | 17 ---- .../IncorrectKeyClassUsageKeyClass.java | 17 ---- .../muzzle/ReferenceCollectorTest.groovy | 30 +++++++ .../InstrumentationContextTestClasses.java | 40 +++++++++ 38 files changed, 339 insertions(+), 326 deletions(-) create mode 100644 javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java create mode 100644 javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java delete mode 100644 testing-common/library-for-integration-tests/src/main/java/library/IncorrectContextClassUsageKeyClass.java delete mode 100644 testing-common/library-for-integration-tests/src/main/java/library/IncorrectKeyClassUsageKeyClass.java create mode 100644 testing-common/src/test/java/io/opentelemetry/instrumentation/InstrumentationContextTestClasses.java diff --git a/instrumentation/akka-actor-2.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java b/instrumentation/akka-actor-2.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java index eae48f836f60..88d506a23446 100644 --- a/instrumentation/akka-actor-2.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java +++ b/instrumentation/akka-actor-2.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/akkaactor/AkkaActorInstrumentationModule.java @@ -8,14 +8,9 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; @AutoService(InstrumentationModule.class) public class AkkaActorInstrumentationModule extends InstrumentationModule { @@ -32,16 +27,6 @@ public List typeInstrumentations() { new AkkaActorCellInstrumentation()); } - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put(Runnable.class.getName(), State.class.getName()); - map.put(Callable.class.getName(), State.class.getName()); - map.put(AkkaForkJoinTaskInstrumentation.TASK_CLASS_NAME, State.class.getName()); - map.put("akka.dispatch.Envelope", State.class.getName()); - return Collections.unmodifiableMap(map); - } - @Override protected boolean defaultEnabled() { return false; diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java index cee20d454f8c..72c64a16e636 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java @@ -6,13 +6,10 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.Pair; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(io.opentelemetry.javaagent.tooling.InstrumentationModule.class) public class AsyncHttpClientInstrumentationModule @@ -25,9 +22,4 @@ public AsyncHttpClientInstrumentationModule() { public List typeInstrumentations() { return asList(new RequestInstrumentation(), new ResponseInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("com.ning.http.client.AsyncHandler", Pair.class.getName()); - } } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java index 219b1022d040..87ea25e59c3d 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/AsyncHttpClientInstrumentationModule.java @@ -8,11 +8,8 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.api.Pair; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(io.opentelemetry.javaagent.tooling.InstrumentationModule.class) public class AsyncHttpClientInstrumentationModule @@ -28,12 +25,4 @@ public List typeInstrumentations() { new ResponseInstrumentation(), new RequestSenderInstrumentation()); } - - @Override - public Map contextStore() { - Map stores = new java.util.HashMap<>(); - stores.put("org.asynchttpclient.AsyncHandler", Pair.class.getName()); - stores.put("org.asynchttpclient.Request", Context.class.getName()); - return stores; - } } diff --git a/instrumentation/couchbase/couchbase-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java b/instrumentation/couchbase/couchbase-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java index ac3cafed6704..4e8a5782fb15 100644 --- a/instrumentation/couchbase/couchbase-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java +++ b/instrumentation/couchbase/couchbase-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_6/CouchbaseInstrumentationModule.java @@ -6,14 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.couchbase.v2_6; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class CouchbaseInstrumentationModule extends InstrumentationModule { @@ -25,9 +22,4 @@ public CouchbaseInstrumentationModule() { public List typeInstrumentations() { return asList(new CouchbaseCoreInstrumentation(), new CouchbaseNetworkInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("com.couchbase.client.core.message.CouchbaseRequest", Span.class.getName()); - } } diff --git a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java index fa18c0b56021..e67558feb552 100644 --- a/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java +++ b/instrumentation/executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javaconcurrent/ExecutorInstrumentationModule.java @@ -8,16 +8,9 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; @AutoService(InstrumentationModule.class) public class ExecutorInstrumentationModule extends InstrumentationModule { @@ -34,14 +27,4 @@ public List typeInstrumentations() { new JavaForkJoinTaskInstrumentation(), new RunnableInstrumentation()); } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put(Callable.class.getName(), State.class.getName()); - map.put(ForkJoinTask.class.getName(), State.class.getName()); - map.put(Future.class.getName(), State.class.getName()); - map.put(Runnable.class.getName(), State.class.getName()); - return Collections.unmodifiableMap(map); - } } diff --git a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java index acd894d7f81d..ab8220658657 100644 --- a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java +++ b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java @@ -8,7 +8,6 @@ import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; import static io.opentelemetry.javaagent.instrumentation.googlehttpclient.GoogleHttpClientTracer.tracer; import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -38,11 +37,6 @@ public GoogleHttpClientInstrumentationModule() { super("google-http-client", "google-http-client-1.19"); } - @Override - public Map contextStore() { - return singletonMap("com.google.api.client.http.HttpRequest", Context.class.getName()); - } - @Override public List typeInstrumentations() { return singletonList(new HttpRequestInstrumentation()); diff --git a/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java b/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java index 1117562e4437..58486286f395 100644 --- a/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java +++ b/instrumentation/guava-10.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/guava/GuavaInstrumentationModule.java @@ -41,11 +41,6 @@ public List typeInstrumentations() { return singletonList(new ListenableFutureInstrumentation()); } - @Override - public Map contextStore() { - return singletonMap(Runnable.class.getName(), State.class.getName()); - } - public static class ListenableFutureInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/hibernate/hibernate-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java index e6c863da23de..44b6e28035a7 100644 --- a/instrumentation/hibernate/hibernate-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java +++ b/instrumentation/hibernate/hibernate-3.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v3_3/HibernateInstrumentationModule.java @@ -9,13 +9,9 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) @@ -43,15 +39,4 @@ public List typeInstrumentations() { new SessionInstrumentation(), new TransactionInstrumentation()); } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.Criteria", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.Session", Context.class.getName()); - map.put("org.hibernate.StatelessSession", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - return Collections.unmodifiableMap(map); - } } diff --git a/instrumentation/hibernate/hibernate-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java index e1187079ec94..1b728a705fbf 100644 --- a/instrumentation/hibernate/hibernate-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java +++ b/instrumentation/hibernate/hibernate-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_0/HibernateInstrumentationModule.java @@ -8,13 +8,9 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class HibernateInstrumentationModule extends InstrumentationModule { @@ -32,14 +28,4 @@ public List typeInstrumentations() { new SessionInstrumentation(), new TransactionInstrumentation()); } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.Criteria", Context.class.getName()); - map.put("org.hibernate.Query", Context.class.getName()); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.Transaction", Context.class.getName()); - return Collections.unmodifiableMap(map); - } } diff --git a/instrumentation/hibernate/hibernate-4.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-4.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java index b1d000352375..5cd418172fe5 100644 --- a/instrumentation/hibernate/hibernate-4.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java +++ b/instrumentation/hibernate/hibernate-4.3/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v4_3/HibernateInstrumentationModule.java @@ -8,13 +8,9 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class HibernateInstrumentationModule extends InstrumentationModule { @@ -26,12 +22,4 @@ public HibernateInstrumentationModule() { public List typeInstrumentations() { return asList(new ProcedureCallInstrumentation(), new SessionInstrumentation()); } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put("org.hibernate.SharedSessionContract", Context.class.getName()); - map.put("org.hibernate.procedure.ProcedureCall", Context.class.getName()); - return Collections.unmodifiableMap(map); - } } diff --git a/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java b/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java index b843bdfd6f59..91d93a28a6b8 100644 --- a/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java +++ b/instrumentation/http-url-connection/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionInstrumentationModule.java @@ -10,7 +10,6 @@ import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.AgentElementMatchers.extendsClass; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.NameMatchers.namedOneOf; import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; @@ -52,11 +51,6 @@ public List typeInstrumentations() { return singletonList(new HttpUrlConnectionInstrumentation()); } - @Override - public Map contextStore() { - return singletonMap("java.net.HttpURLConnection", getClass().getName() + "$HttpUrlState"); - } - public static class HttpUrlConnectionInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { diff --git a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java index 0b8d4866b042..898a6e322e06 100644 --- a/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java +++ b/instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrs/v2_0/JaxRsInstrumentationModule.java @@ -7,14 +7,11 @@ import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.context.Context; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) @@ -37,9 +34,4 @@ public List typeInstrumentations() { new JaxRsAnnotationsInstrumentation(), new JaxRsAsyncResponseInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("javax.ws.rs.container.AsyncResponse", Context.class.getName()); - } } diff --git a/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8InstrumentationModule.java b/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8InstrumentationModule.java index 5ade2c52597b..61076249d752 100644 --- a/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8InstrumentationModule.java +++ b/instrumentation/jetty/jetty-8.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/v8_0/Jetty8InstrumentationModule.java @@ -5,7 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.jetty.v8_0; -import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -45,11 +44,6 @@ public List typeInstrumentations() { new JettyQueuedThreadPoolInstrumentation()); } - @Override - public Map contextStore() { - return singletonMap(Runnable.class.getName(), State.class.getName()); - } - public static class JettyQueuedThreadPoolInstrumentation implements TypeInstrumentation { @Override diff --git a/instrumentation/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java b/instrumentation/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java index a3cfb977332b..f16ad93e6839 100644 --- a/instrumentation/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java +++ b/instrumentation/jms-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jms/JmsInstrumentationModule.java @@ -6,13 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.jms; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class JmsInstrumentationModule extends InstrumentationModule { @@ -27,9 +25,4 @@ public List typeInstrumentations() { new JmsMessageListenerInstrumentation(), new JmsMessageProducerInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("javax.jms.MessageConsumer", MessageDestination.class.getName()); - } } diff --git a/instrumentation/log4j/log4j-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java b/instrumentation/log4j/log4j-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java index 5125fdcb08ec..47e3ecbe8b81 100644 --- a/instrumentation/log4j/log4j-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java +++ b/instrumentation/log4j/log4j-1.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/log4j/v1_2/Log4j1InstrumentationModule.java @@ -6,14 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.log4j.v1_2; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class Log4j1InstrumentationModule extends InstrumentationModule { @@ -25,9 +22,4 @@ public Log4j1InstrumentationModule() { public List typeInstrumentations() { return asList(new CategoryInstrumentation(), new LoggingEventInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("org.apache.log4j.spi.LoggingEvent", Span.class.getName()); - } } diff --git a/instrumentation/logback/logback-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackInstrumentationModule.java b/instrumentation/logback/logback-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackInstrumentationModule.java index 3ec8a09b95f0..f61057f2d88c 100644 --- a/instrumentation/logback/logback-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackInstrumentationModule.java +++ b/instrumentation/logback/logback-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/logback/v1_0/LogbackInstrumentationModule.java @@ -6,14 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.logback.v1_0; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class LogbackInstrumentationModule extends InstrumentationModule { @@ -25,9 +22,4 @@ public LogbackInstrumentationModule() { public List typeInstrumentations() { return asList(new LoggerInstrumentation(), new LoggingEventInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("ch.qos.logback.classic.spi.ILoggingEvent", Span.class.getName()); - } } diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java index 2f1153e700af..861ab6030099 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyInstrumentationModule.java @@ -10,9 +10,7 @@ import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class NettyInstrumentationModule extends InstrumentationModule { @@ -28,10 +26,4 @@ public List typeInstrumentations() { new NettyChannelPipelineInstrumentation(), new DefaultChannelPipelineInstrumentation()); } - - @Override - public Map contextStore() { - return Collections.singletonMap( - "org.jboss.netty.channel.Channel", ChannelTraceContext.class.getName()); - } } diff --git a/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java b/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java index 2130065bdebc..94276b91979a 100644 --- a/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java +++ b/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/RmiContextPropagationInstrumentationModule.java @@ -6,7 +6,6 @@ package io.opentelemetry.javaagent.instrumentation.rmi.context; import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.instrumentation.rmi.context.client.RmiClientContextInstrumentation; @@ -14,7 +13,6 @@ import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class RmiContextPropagationInstrumentationModule extends InstrumentationModule { @@ -26,10 +24,4 @@ public RmiContextPropagationInstrumentationModule() { public List typeInstrumentations() { return asList(new RmiClientContextInstrumentation(), new RmiServerContextInstrumentation()); } - - @Override - public Map contextStore() { - // caching if a connection can support enhanced format - return singletonMap("sun.rmi.transport.Connection", "java.lang.Boolean"); - } } diff --git a/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java b/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java index b9c33335c75e..ee4671422644 100644 --- a/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java +++ b/instrumentation/rmi/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rmi/context/client/RmiClientContextInstrumentation.java @@ -78,6 +78,7 @@ public static void onEnter(@Advice.Argument(0) Connection c, @Advice.Argument(1) return; } + // caching if a connection can support enhanced format ContextStore knownConnections = InstrumentationContext.get(Connection.class, Boolean.class); diff --git a/instrumentation/scala-executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaexecutors/ScalaConcurrentInstrumentationModule.java b/instrumentation/scala-executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaexecutors/ScalaConcurrentInstrumentationModule.java index f1c85e510100..f5fb04b816ae 100644 --- a/instrumentation/scala-executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaexecutors/ScalaConcurrentInstrumentationModule.java +++ b/instrumentation/scala-executors/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/scalaexecutors/ScalaConcurrentInstrumentationModule.java @@ -5,18 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.scalaexecutors; -import static io.opentelemetry.javaagent.instrumentation.scalaexecutors.ScalaForkJoinTaskInstrumentation.TASK_CLASS_NAME; import static java.util.Arrays.asList; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; @AutoService(InstrumentationModule.class) public class ScalaConcurrentInstrumentationModule extends InstrumentationModule { @@ -28,13 +22,4 @@ public ScalaConcurrentInstrumentationModule() { public List typeInstrumentations() { return asList(new ScalaForkJoinPoolInstrumentation(), new ScalaForkJoinTaskInstrumentation()); } - - @Override - public Map contextStore() { - Map map = new HashMap<>(); - map.put(Runnable.class.getName(), State.class.getName()); - map.put(Callable.class.getName(), State.class.getName()); - map.put(TASK_CLASS_NAME, State.class.getName()); - return Collections.unmodifiableMap(map); - } } diff --git a/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java b/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java index c2d7ce1cbf9a..6a23d75f7eb0 100644 --- a/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java +++ b/instrumentation/servlet/servlet-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v2_2/Servlet2InstrumentationModule.java @@ -6,7 +6,6 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v2_2; import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed; -import static java.util.Collections.singletonMap; import static net.bytebuddy.matcher.ElementMatchers.not; import com.google.auto.service.AutoService; @@ -15,7 +14,6 @@ import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Arrays; import java.util.List; -import java.util.Map; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) @@ -38,9 +36,4 @@ public List typeInstrumentations() { "javax.servlet", Servlet2InstrumentationModule.class.getPackage().getName() + ".Servlet2Advice")); } - - @Override - public Map contextStore() { - return singletonMap("javax.servlet.ServletResponse", Integer.class.getName()); - } } diff --git a/instrumentation/servlet/servlet-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v5_0/JakartaServletInstrumentationModule.java b/instrumentation/servlet/servlet-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v5_0/JakartaServletInstrumentationModule.java index c1f253403e8b..b5593cb79e0e 100644 --- a/instrumentation/servlet/servlet-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v5_0/JakartaServletInstrumentationModule.java +++ b/instrumentation/servlet/servlet-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/v5_0/JakartaServletInstrumentationModule.java @@ -5,8 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.servlet.v5_0; -import static java.util.Collections.singletonMap; - import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.instrumentation.servlet.common.async.AsyncContextInstrumentation; import io.opentelemetry.javaagent.instrumentation.servlet.common.dispatcher.RequestDispatcherInstrumentation; @@ -16,7 +14,6 @@ import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Arrays; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class JakartaServletInstrumentationModule extends InstrumentationModule { @@ -39,11 +36,6 @@ BASE_PACKAGE, adviceClassName(".response.ResponseSendAdvice")), BASE_PACKAGE, adviceClassName(".dispatcher.RequestDispatcherAdvice"))); } - @Override - public Map contextStore() { - return singletonMap(BASE_PACKAGE + ".RequestDispatcher", String.class.getName()); - } - private static String adviceClassName(String suffix) { return JakartaServletInstrumentationModule.class.getPackage().getName() + suffix; } diff --git a/instrumentation/servlet/servlet-javax-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/javax/JavaxServletInstrumentationModule.java b/instrumentation/servlet/servlet-javax-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/javax/JavaxServletInstrumentationModule.java index 9f5355b689aa..c8bcd5692358 100644 --- a/instrumentation/servlet/servlet-javax-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/javax/JavaxServletInstrumentationModule.java +++ b/instrumentation/servlet/servlet-javax-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/servlet/javax/JavaxServletInstrumentationModule.java @@ -5,8 +5,6 @@ package io.opentelemetry.javaagent.instrumentation.servlet.javax; -import static java.util.Collections.singletonMap; - import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.instrumentation.servlet.common.dispatcher.RequestDispatcherInstrumentation; import io.opentelemetry.javaagent.instrumentation.servlet.common.response.HttpServletResponseInstrumentation; @@ -14,7 +12,6 @@ import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Arrays; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class JavaxServletInstrumentationModule extends InstrumentationModule { @@ -33,11 +30,6 @@ BASE_PACKAGE, adviceClassName(".response.ResponseSendAdvice")), BASE_PACKAGE, adviceClassName(".dispatcher.RequestDispatcherAdvice"))); } - @Override - protected Map contextStore() { - return singletonMap(BASE_PACKAGE + ".RequestDispatcher", String.class.getName()); - } - private static String adviceClassName(String suffix) { return JavaxServletInstrumentationModule.class.getPackage().getName() + suffix; } diff --git a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/SpringBatchInstrumentationModule.java b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/SpringBatchInstrumentationModule.java index e7f57d323608..84b86688a701 100644 --- a/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/SpringBatchInstrumentationModule.java +++ b/instrumentation/spring/spring-batch-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/batch/SpringBatchInstrumentationModule.java @@ -21,9 +21,7 @@ import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) @@ -37,17 +35,6 @@ public ElementMatcher.Junction classLoaderMatcher() { return hasClassesNamed("org.springframework.batch.core.jsr.launch.JsrJobOperator"); } - @Override - protected Map contextStore() { - Map context = new HashMap<>(); - String contextAndScope = - "io.opentelemetry.javaagent.instrumentation.spring.batch.ContextAndScope"; - context.put("org.springframework.batch.core.JobExecution", contextAndScope); - context.put("org.springframework.batch.core.StepExecution", contextAndScope); - context.put("org.springframework.batch.core.scope.context.ChunkContext", contextAndScope); - return context; - } - @Override public List typeInstrumentations() { return Arrays.asList( diff --git a/instrumentation/spring/spring-core-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/core/SpringCoreInstrumentationModule.java b/instrumentation/spring/spring-core-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/core/SpringCoreInstrumentationModule.java index 78b69d0737f6..dd87ea5d4d46 100644 --- a/instrumentation/spring/spring-core-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/core/SpringCoreInstrumentationModule.java +++ b/instrumentation/spring/spring-core-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/core/SpringCoreInstrumentationModule.java @@ -7,14 +7,11 @@ import static io.opentelemetry.javaagent.tooling.bytebuddy.matcher.ClassLoaderMatcher.hasClassesNamed; import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; -import io.opentelemetry.javaagent.instrumentation.api.concurrent.State; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) @@ -28,11 +25,6 @@ public ElementMatcher.Junction classLoaderMatcher() { return hasClassesNamed("org.springframework.core.task.SimpleAsyncTaskExecutor"); } - @Override - protected Map contextStore() { - return singletonMap(Runnable.class.getName(), State.class.getName()); - } - @Override public List typeInstrumentations() { return singletonList(new SimpleAsyncTaskExecutorInstrumentation()); diff --git a/instrumentation/vertx-web-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumentationModule.java b/instrumentation/vertx-web-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumentationModule.java index 7b9b5a72bf40..f7d053612663 100644 --- a/instrumentation/vertx-web-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumentationModule.java +++ b/instrumentation/vertx-web-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/client/VertxClientInstrumentationModule.java @@ -6,13 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.vertx.client; import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.tooling.InstrumentationModule; import io.opentelemetry.javaagent.tooling.TypeInstrumentation; import java.util.List; -import java.util.Map; @AutoService(InstrumentationModule.class) public class VertxClientInstrumentationModule extends InstrumentationModule { @@ -25,9 +23,4 @@ public VertxClientInstrumentationModule() { public List typeInstrumentations() { return singletonList(new HttpRequestInstrumentation()); } - - @Override - public Map contextStore() { - return singletonMap("io.vertx.core.http.HttpClientRequest", Contexts.class.getName()); - } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/InstrumentationModule.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/InstrumentationModule.java index 3b90b9b0283a..17b8bef6ad19 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/InstrumentationModule.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/InstrumentationModule.java @@ -192,7 +192,7 @@ private AgentBuilder.Identified.Extendable applyInstrumentationTransformers( } private InstrumentationContextProvider getContextProvider() { - Map contextStore = contextStore(); + Map contextStore = getMuzzleContextStoreClasses(); if (!contextStore.isEmpty()) { return new FieldBackedProvider(getClass(), contextStore); } else { @@ -303,6 +303,20 @@ protected String[] getMuzzleHelperClassNames() { return EMPTY; } + /** + * Returns a map of {@code class-name to context-class-name}. Keys (and their subclasses) will be + * associated with a context class stored in the value. + * + *

The actual implementation of this method is generated automatically during compilation by + * the {@link io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCodeGenerationPlugin} + * ByteBuddy plugin. + * + *

This method is generated automatically, do not override it. + */ + protected Map getMuzzleContextStoreClasses() { + return Collections.emptyMap(); + } + /** * Instrumentation modules can override this method to provide additional helper classes that are * not located in instrumentation packages described in {@link InstrumentationClassPredicate} and @@ -346,16 +360,6 @@ public ElementMatcher.Junction classLoaderMatcher() { /** Returns a list of all individual type instrumentation in this module. */ public abstract List typeInstrumentations(); - /** - * Context stores to define for this instrumentation. - * - *

A map of {@code class-name to context-class-name}. Keys (and their subclasses) will be - * associated with a context of the value. - */ - protected Map contextStore() { - return Collections.emptyMap(); - } - /** * Allows instrumentation modules to disable themselves by default, or to additionally disable * themselves on some other condition. diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java new file mode 100644 index 000000000000..29348a70e505 --- /dev/null +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java @@ -0,0 +1,46 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.muzzle.collector; + +import java.util.ArrayDeque; +import java.util.Iterator; + +final class FixedSizeQueue implements Iterable { + private final int maxSize; + private final ArrayDeque queue; + + FixedSizeQueue(int maxSize) { + this.maxSize = maxSize; + this.queue = new ArrayDeque<>(maxSize); + } + + void add(T elem) { + if (hasMaxSize()) { + queue.removeFirst(); + } + queue.addLast(elem); + } + + boolean hasMaxSize() { + return queue.size() == maxSize; + } + + T pop() { + if (!queue.isEmpty()) { + return queue.removeFirst(); + } + return null; + } + + void clear() { + queue.clear(); + } + + @Override + public Iterator iterator() { + return queue.iterator(); + } +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCodeGenerator.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCodeGenerator.java index 79c6aeb46a46..07f7abaf1f4b 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCodeGenerator.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCodeGenerator.java @@ -10,6 +10,7 @@ import io.opentelemetry.javaagent.tooling.muzzle.Reference; import io.opentelemetry.javaagent.tooling.muzzle.matcher.ReferenceMatcher; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -42,6 +43,8 @@ class MuzzleCodeGenerator implements AsmVisitorWrapper { public static final String MUZZLE_REF_MATCHER_FIELD_NAME = "muzzleReferenceMatcher"; public static final String MUZZLE_REF_MATCHER_METHOD_NAME = "getMuzzleReferenceMatcher"; public static final String MUZZLE_HELPER_CLASSES_METHOD_NAME = "getMuzzleHelperClassNames"; + public static final String MUZZLE_CONTEXT_STORE_CLASSES_METHOD_NAME = + "getMuzzleContextStoreClasses"; @Override public int mergeWriter(int flags) { @@ -138,6 +141,7 @@ public void visitEnd() { generateMuzzleHelperClassNamesMethod(collector); generateMuzzleReferenceMatcherMethod(collector); generateMuzzleReferenceMatcherField(); + generateMuzzleContextStoreClassesMethod(collector); super.visitEnd(); } @@ -518,6 +522,63 @@ private void generateMuzzleReferenceMatcherField() { null); } + private void generateMuzzleContextStoreClassesMethod(ReferenceCollector collector) { + /* + * protected Map getMuzzleContextStoreClasses() { + * Map contextStore = new HashMap(); + * contextStore.put(..., ...); + * return contextStore; + * } + */ + MethodVisitor mv = + super.visitMethod( + Opcodes.ACC_PROTECTED, + MUZZLE_CONTEXT_STORE_CLASSES_METHOD_NAME, + "()Ljava/util/Map;", + null, + null); + mv.visitCode(); + + Map contextStoreClasses = collector.getContextStoreClasses(); + + mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap"); + // stack: map + mv.visitInsn(Opcodes.DUP); + // stack: map, map + mv.visitLdcInsn(contextStoreClasses.size()); + // stack: map, map, size + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "", "(I)V", false); + // stack: map + mv.visitVarInsn(Opcodes.ASTORE, 1); + // stack: + + contextStoreClasses.forEach( + (className, contextClassName) -> { + mv.visitVarInsn(Opcodes.ALOAD, 1); + // stack: map + mv.visitLdcInsn(className); + // stack: map, className + mv.visitLdcInsn(contextClassName); + // stack: map, className, contextClassName + mv.visitMethodInsn( + Opcodes.INVOKEINTERFACE, + "java/util/Map", + "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + true); + // stack: previousValue + mv.visitInsn(Opcodes.POP); + // stack: + }); + + mv.visitVarInsn(Opcodes.ALOAD, 1); + // stack: map + mv.visitInsn(Opcodes.ARETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + private static final Pattern ANONYMOUS_ENUM_CONSTANT_CLASS = Pattern.compile("(?.*)\\$[0-9]+$"); diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java index 614c21c41578..4ab7a4a15044 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java @@ -115,6 +115,7 @@ private static Type underlyingType(Type type) { // helper super classes which are themselves also helpers // this is needed for injecting the helper classes into the class loader in the correct order private final Set helperSuperClasses = new HashSet<>(); + private final Map contextStoreClasses = new LinkedHashMap<>(); private String refSourceClassName; private Type refSourceType; @@ -137,6 +138,10 @@ Set getHelperSuperClasses() { return helperSuperClasses; } + Map getContextStoreClasses() { + return contextStoreClasses; + } + private void addExtendsReference(Reference ref) { addReference(ref); if (instrumentationClassPredicate.isInstrumentationClass(ref.getClassName())) { @@ -276,6 +281,10 @@ private static ManifestationFlag computeTypeManifestationFlag(int access) { private class AdviceReferenceMethodVisitor extends MethodVisitor { private int currentLineNumber = -1; + // this data structure will remember last two LDC instructions before + // InstrumentationContext.get() call + private final FixedSizeQueue lastTwoClassConstants = new FixedSizeQueue<>(2); + public AdviceReferenceMethodVisitor(MethodVisitor methodVisitor) { super(Opcodes.ASM7, methodVisitor); } @@ -332,6 +341,8 @@ public void visitFieldInsn(int opcode, String owner, String name, String descrip .withFlag(computeMinimumClassAccess(refSourceType, underlyingFieldType)) .build()); } + + registerOpcode(opcode, null); super.visitFieldInsn(opcode, owner, name, descriptor); } @@ -349,6 +360,28 @@ public void visitMethodInsn( // * return type Type methodType = Type.getMethodType(descriptor); + Type ownerType = + owner.startsWith("[") + ? underlyingType(Type.getType(owner)) + : Type.getType("L" + owner + ";"); + + // remember used context classes if this is an InstrumentationContext.get() call + if ("io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext" + .equals(ownerType.getClassName()) + && "get".equals(name) + && methodType.getArgumentTypes().length == 2) { + // in case of invalid scenario (not using .class ref directly) don't store anything and + // clear the last LDC stack + // note that FieldBackedProvider also check for an invalid context call in the runtime + if (lastTwoClassConstants.hasMaxSize()) { + String className = lastTwoClassConstants.pop(); + String contextClassName = lastTwoClassConstants.pop(); + contextStoreClasses.put(className, contextClassName); + } else { + lastTwoClassConstants.clear(); + } + } + { // ref for method return type Type returnType = underlyingType(methodType.getReturnType()); if (returnType.getSort() == Type.OBJECT) { @@ -371,11 +404,6 @@ public void visitMethodInsn( } } - Type ownerType = - owner.startsWith("[") - ? underlyingType(Type.getType(owner)) - : Type.getType("L" + owner + ";"); - List methodFlags = new ArrayList<>(); methodFlags.add( opcode == Opcodes.INVOKESTATIC ? OwnershipFlag.STATIC : OwnershipFlag.NON_STATIC); @@ -395,6 +423,8 @@ public void visitMethodInsn( methodType.getReturnType(), methodType.getArgumentTypes()) .build()); + + registerOpcode(opcode, null); super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); } @@ -408,6 +438,8 @@ public void visitTypeInsn(int opcode, String type) { .withFlag(computeMinimumClassAccess(refSourceType, typeObj)) .build()); } + + registerOpcode(opcode, null); super.visitTypeInsn(opcode, type); } @@ -453,7 +485,51 @@ public void visitLdcInsn(Object value) { .build()); } } + registerOpcode(Opcodes.LDC, value); super.visitLdcInsn(value); } + + @Override + public void visitInsn(int opcode) { + registerOpcode(opcode, null); + super.visitInsn(opcode); + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + registerOpcode(opcode, null); + super.visitJumpInsn(opcode, label); + } + + @Override + public void visitIntInsn(int opcode, int operand) { + registerOpcode(opcode, null); + super.visitIntInsn(opcode, operand); + } + + @Override + public void visitVarInsn(int opcode, int var) { + registerOpcode(opcode, null); + super.visitVarInsn(opcode, var); + } + + private void registerOpcode(int opcode, Object value) { + // check if this is an LDC instruction; if so, remember the class that was used + // we need to remember last two LDC instructions that were executed before + // InstrumentationContext.get() call + if (opcode == Opcodes.LDC) { + if (value instanceof Type) { + Type type = (Type) value; + if (type.getSort() == Type.OBJECT) { + lastTwoClassConstants.add(type.getClassName()); + return; + } + } + } + + // instruction other than LDC visited; pop the first element if present - this will + // prevent adding wrong context key pairs in case of an invalid scenario + lastTwoClassConstants.pop(); + } } } diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollector.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollector.java index 6875a9d1ceaa..1f0c64a9e839 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollector.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollector.java @@ -46,6 +46,7 @@ public class ReferenceCollector { private final Map references = new LinkedHashMap<>(); private final MutableGraph helperSuperClassGraph = GraphBuilder.directed().build(); + private final Map contextStoreClasses = new LinkedHashMap<>(); private final Set visitedClasses = new HashSet<>(); private final InstrumentationClassPredicate instrumentationClassPredicate; @@ -142,6 +143,7 @@ private void visitClassesAndCollectReferences( collectHelperClasses( isAdviceClass, visitedClassName, cv.getHelperClasses(), cv.getHelperSuperClasses()); + contextStoreClasses.putAll(cv.getContextStoreClasses()); } catch (IOException e) { throw new IllegalStateException("Error reading class " + visitedClassName, e); } @@ -232,4 +234,8 @@ private static Queue findAllHelperClassesWithoutDependencies( } return helpersWithNoDeps; } + + public Map getContextStoreClasses() { + return contextStoreClasses; + } } diff --git a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java new file mode 100644 index 000000000000..52df4b7f004a --- /dev/null +++ b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java @@ -0,0 +1,59 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.muzzle.collector; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class FixedSizeQueueTest { + @Test + void shouldRemoveOldestItems() { + // given + FixedSizeQueue underTest = new FixedSizeQueue<>(2); + + // when + underTest.add("class 1"); + underTest.add("class 2"); + + // then + assertThat(underTest).containsExactly("class 1", "class 2"); + assertThat(underTest.hasMaxSize()).isTrue(); + + // when + underTest.add("class 3"); + + // then + assertThat(underTest).containsExactly("class 2", "class 3"); + assertThat(underTest.hasMaxSize()).isTrue(); + } + + @Test + void shouldNotThrowOnPopIfEmpty() { + // given + FixedSizeQueue underTest = new FixedSizeQueue<>(2); + + // when + underTest.pop(); + underTest.pop(); + + // then no exception is thrown + } + + @Test + void shouldClearQueue() { + // given + FixedSizeQueue underTest = new FixedSizeQueue<>(2); + underTest.add("class 1"); + underTest.add("class 2"); + + // when + underTest.clear(); + + // then + assertThat(underTest).isEmpty(); + } +} diff --git a/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java b/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java index ee21c2d815dc..7804b9997657 100644 --- a/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java +++ b/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java @@ -47,15 +47,6 @@ public List typeInstrumentations() { return singletonList(new ContextTestInstrumentation()); } - @Override - public Map contextStore() { - Map store = new HashMap<>(3); - store.put("library.KeyClass", getClass().getName() + "$Context"); - store.put("library.UntransformableKeyClass", getClass().getName() + "$Context"); - store.put("library.DisabledKeyClass", getClass().getName() + "$Context"); - return store; - } - public static class ContextTestInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { @@ -71,11 +62,6 @@ public Map, String> transfor transformers.put(named("getContextCount"), GetApiUsageAdvice.class.getName()); transformers.put(named("putContextCount"), PutApiUsageAdvice.class.getName()); transformers.put(named("removeContextCount"), RemoveApiUsageAdvice.class.getName()); - transformers.put( - named("incorrectKeyClassUsage"), IncorrectKeyClassContextApiUsageAdvice.class.getName()); - transformers.put( - named("incorrectContextClassUsage"), - IncorrectContextClassContextApiUsageAdvice.class.getName()); transformers.put( named("incorrectCallUsage"), IncorrectCallContextApiUsageAdvice.class.getName()); return transformers; @@ -142,20 +128,6 @@ public static void methodExit(@Advice.This KeyClass thiz) { } } - public static class IncorrectKeyClassContextApiUsageAdvice { - @Advice.OnMethodExit - public static void methodExit() { - InstrumentationContext.get(Object.class, Context.class); - } - } - - public static class IncorrectContextClassContextApiUsageAdvice { - @Advice.OnMethodExit - public static void methodExit() { - InstrumentationContext.get(KeyClass.class, Object.class); - } - } - public static class IncorrectCallContextApiUsageAdvice { @Advice.OnMethodExit public static void methodExit() { diff --git a/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy b/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy index 05cab5144a34..1883eec16ae5 100644 --- a/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy +++ b/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy @@ -16,8 +16,6 @@ import java.lang.reflect.Method import java.lang.reflect.Modifier import java.util.concurrent.atomic.AtomicReference import library.IncorrectCallUsageKeyClass -import library.IncorrectContextClassUsageKeyClass -import library.IncorrectKeyClassUsageKeyClass import library.KeyClass import library.UntransformableKeyClass import net.bytebuddy.agent.ByteBuddyAgent @@ -188,16 +186,6 @@ class FieldBackedProviderTest extends AgentInstrumentationSpecification { new UntransformableKeyClass().incrementContextCount() == 1 } - def "incorrect key class usage fails at class load time"() { - expect: - !new IncorrectKeyClassUsageKeyClass().isInstrumented() - } - - def "incorrect context class usage fails at class load time"() { - expect: - !new IncorrectContextClassUsageKeyClass().isInstrumented() - } - def "incorrect call usage fails at class load time"() { expect: !new IncorrectCallUsageKeyClass().isInstrumented() diff --git a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectContextClassUsageKeyClass.java b/testing-common/library-for-integration-tests/src/main/java/library/IncorrectContextClassUsageKeyClass.java deleted file mode 100644 index af700ced9975..000000000000 --- a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectContextClassUsageKeyClass.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package library; - -public class IncorrectContextClassUsageKeyClass { - public boolean isInstrumented() { - return false; - } - - public int incorrectContextClassUsage() { - // instrumentation will not apply to this class because advice incorrectly uses context api - return -1; - } -} diff --git a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectKeyClassUsageKeyClass.java b/testing-common/library-for-integration-tests/src/main/java/library/IncorrectKeyClassUsageKeyClass.java deleted file mode 100644 index 53c2eda689c3..000000000000 --- a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectKeyClassUsageKeyClass.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package library; - -public class IncorrectKeyClassUsageKeyClass { - public boolean isInstrumented() { - return false; - } - - public int incorrectKeyClassUsage() { - // instrumentation will not apply to this class because advice incorrectly uses context api - return -1; - } -} diff --git a/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy b/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy index 99b0cccf1b9e..12cbbbfcd633 100644 --- a/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy +++ b/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy @@ -14,6 +14,8 @@ import static muzzle.TestClasses.LdcAdvice import static muzzle.TestClasses.MethodBodyAdvice import external.instrumentation.ExternalHelper +import io.opentelemetry.context.Context +import io.opentelemetry.instrumentation.InstrumentationContextTestClasses import io.opentelemetry.instrumentation.OtherTestHelperClasses import io.opentelemetry.instrumentation.TestHelperClasses import io.opentelemetry.javaagent.tooling.muzzle.Reference @@ -255,6 +257,34 @@ class ReferenceCollectorTest extends Specification { collector.sortedHelperClasses.isEmpty() } + def "should collect context store classes"() { + when: + def collector = new ReferenceCollector({ false }) + collector.collectReferencesFromAdvice(InstrumentationContextTestClasses.ValidAdvice.name) + + then: + def contextStore = collector.getContextStoreClasses() + contextStore == [ + (InstrumentationContextTestClasses.Key1.name): Context.name, + (InstrumentationContextTestClasses.Key2.name): Context.name + ] + } + + def "should not collect context store classes for invalid scenario: #desc"() { + when: + def collector = new ReferenceCollector({ false }) + collector.collectReferencesFromAdvice(adviceClassName) + + then: + def contextStore = collector.getContextStoreClasses() + contextStore.isEmpty() + + where: + desc | adviceClassName + "passing arbitrary variables or parameters to InstrumentationContext.get()" | InstrumentationContextTestClasses.NotUsingClassRefAdvice.name + "storing class ref in a local var" | InstrumentationContextTestClasses.PassingVariableAdvice.name + } + private static assertHelperSuperClassMethod(Reference reference, boolean isAbstract) { assertMethod reference, 'abstractMethod', '()I', VisibilityFlag.PROTECTED, diff --git a/testing-common/src/test/java/io/opentelemetry/instrumentation/InstrumentationContextTestClasses.java b/testing-common/src/test/java/io/opentelemetry/instrumentation/InstrumentationContextTestClasses.java new file mode 100644 index 000000000000..1c6df827bb91 --- /dev/null +++ b/testing-common/src/test/java/io/opentelemetry/instrumentation/InstrumentationContextTestClasses.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation; + +import io.opentelemetry.context.Context; +import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext; + +public class InstrumentationContextTestClasses { + public static class ValidAdvice { + public static void advice() { + Runnable.class.getName(); + InstrumentationContext.get(Key1.class, Context.class); + Key2.class.getName(); + Key1.class.getName(); + InstrumentationContext.get(Key2.class, Context.class); + } + } + + public static class NotUsingClassRefAdvice { + public static void advice(Class key, Class context) { + Key2.class.getName(); + Key1.class.getName(); + InstrumentationContext.get(key, context); + } + } + + public static class PassingVariableAdvice { + public static void advice() { + Class context = Context.class; + InstrumentationContext.get(Key1.class, context); + } + } + + public static class Key1 {} + + public static class Key2 {} +} From 61a86ad44badb290edbcb3478ff63a0f4e3c65f0 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Tue, 13 Apr 2021 08:23:00 +0200 Subject: [PATCH 2/2] Generate InstrumentationModule#contextStore() with muzzle --- .../muzzle/collector/FixedSizeQueue.java | 46 -------- .../collector/MuzzleCompilationException.java | 12 +++ .../ReferenceCollectingClassVisitor.java | 102 ++++++++++++------ .../muzzle/collector/FixedSizeQueueTest.java | 59 ---------- .../ContextTestInstrumentationModule.java | 12 --- .../context/FieldBackedProviderTest.groovy | 6 -- .../library/IncorrectCallUsageKeyClass.java | 17 --- .../muzzle/ReferenceCollectorTest.groovy | 4 +- 8 files changed, 83 insertions(+), 175 deletions(-) delete mode 100644 javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java create mode 100644 javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCompilationException.java delete mode 100644 javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java delete mode 100644 testing-common/library-for-integration-tests/src/main/java/library/IncorrectCallUsageKeyClass.java diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java deleted file mode 100644 index 29348a70e505..000000000000 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueue.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.tooling.muzzle.collector; - -import java.util.ArrayDeque; -import java.util.Iterator; - -final class FixedSizeQueue implements Iterable { - private final int maxSize; - private final ArrayDeque queue; - - FixedSizeQueue(int maxSize) { - this.maxSize = maxSize; - this.queue = new ArrayDeque<>(maxSize); - } - - void add(T elem) { - if (hasMaxSize()) { - queue.removeFirst(); - } - queue.addLast(elem); - } - - boolean hasMaxSize() { - return queue.size() == maxSize; - } - - T pop() { - if (!queue.isEmpty()) { - return queue.removeFirst(); - } - return null; - } - - void clear() { - queue.clear(); - } - - @Override - public Iterator iterator() { - return queue.iterator(); - } -} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCompilationException.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCompilationException.java new file mode 100644 index 000000000000..10f69f4be880 --- /dev/null +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/MuzzleCompilationException.java @@ -0,0 +1,12 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.tooling.muzzle.collector; + +public class MuzzleCompilationException extends RuntimeException { + public MuzzleCompilationException(String message) { + super(message); + } +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java index 4ab7a4a15044..d52e86e75ff7 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/collector/ReferenceCollectingClassVisitor.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.tooling.muzzle.collector; +import com.google.common.collect.EvictingQueue; import io.opentelemetry.javaagent.tooling.Utils; import io.opentelemetry.javaagent.tooling.muzzle.InstrumentationClassPredicate; import io.opentelemetry.javaagent.tooling.muzzle.Reference; @@ -245,7 +246,8 @@ public MethodVisitor visitMethod( // Additional references we could check // - Classes in signature (return type, params) and visible from this package return new AdviceReferenceMethodVisitor( - super.visitMethod(access, name, descriptor, signature, exceptions)); + new InstrumentationContextMethodVisitor( + super.visitMethod(access, name, descriptor, signature, exceptions))); } private static VisibilityFlag computeVisibilityFlag(int access) { @@ -281,10 +283,6 @@ private static ManifestationFlag computeTypeManifestationFlag(int access) { private class AdviceReferenceMethodVisitor extends MethodVisitor { private int currentLineNumber = -1; - // this data structure will remember last two LDC instructions before - // InstrumentationContext.get() call - private final FixedSizeQueue lastTwoClassConstants = new FixedSizeQueue<>(2); - public AdviceReferenceMethodVisitor(MethodVisitor methodVisitor) { super(Opcodes.ASM7, methodVisitor); } @@ -342,7 +340,6 @@ public void visitFieldInsn(int opcode, String owner, String name, String descrip .build()); } - registerOpcode(opcode, null); super.visitFieldInsn(opcode, owner, name, descriptor); } @@ -365,23 +362,6 @@ public void visitMethodInsn( ? underlyingType(Type.getType(owner)) : Type.getType("L" + owner + ";"); - // remember used context classes if this is an InstrumentationContext.get() call - if ("io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext" - .equals(ownerType.getClassName()) - && "get".equals(name) - && methodType.getArgumentTypes().length == 2) { - // in case of invalid scenario (not using .class ref directly) don't store anything and - // clear the last LDC stack - // note that FieldBackedProvider also check for an invalid context call in the runtime - if (lastTwoClassConstants.hasMaxSize()) { - String className = lastTwoClassConstants.pop(); - String contextClassName = lastTwoClassConstants.pop(); - contextStoreClasses.put(className, contextClassName); - } else { - lastTwoClassConstants.clear(); - } - } - { // ref for method return type Type returnType = underlyingType(methodType.getReturnType()); if (returnType.getSort() == Type.OBJECT) { @@ -424,7 +404,6 @@ public void visitMethodInsn( methodType.getArgumentTypes()) .build()); - registerOpcode(opcode, null); super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); } @@ -439,7 +418,6 @@ public void visitTypeInsn(int opcode, String type) { .build()); } - registerOpcode(opcode, null); super.visitTypeInsn(opcode, type); } @@ -485,20 +463,23 @@ public void visitLdcInsn(Object value) { .build()); } } - registerOpcode(Opcodes.LDC, value); super.visitLdcInsn(value); } + } - @Override - public void visitInsn(int opcode) { - registerOpcode(opcode, null); - super.visitInsn(opcode); + private class InstrumentationContextMethodVisitor extends MethodVisitor { + // this data structure will remember last two LDC instructions before + // InstrumentationContext.get() call + private final EvictingQueue lastTwoClassConstants = EvictingQueue.create(2); + + InstrumentationContextMethodVisitor(MethodVisitor methodVisitor) { + super(Opcodes.ASM7, methodVisitor); } @Override - public void visitJumpInsn(int opcode, Label label) { + public void visitInsn(int opcode) { registerOpcode(opcode, null); - super.visitJumpInsn(opcode, label); + super.visitInsn(opcode); } @Override @@ -513,6 +494,61 @@ public void visitVarInsn(int opcode, int var) { super.visitVarInsn(opcode, var); } + @Override + public void visitTypeInsn(int opcode, String type) { + registerOpcode(opcode, null); + super.visitTypeInsn(opcode, type); + } + + @Override + public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { + registerOpcode(opcode, null); + super.visitFieldInsn(opcode, owner, name, descriptor); + } + + @Override + public void visitMethodInsn( + int opcode, String owner, String name, String descriptor, boolean isInterface) { + + Type methodType = Type.getMethodType(descriptor); + Type ownerType = Type.getType("L" + owner + ";"); + + // remember used context classes if this is an InstrumentationContext.get() call + if ("io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext" + .equals(ownerType.getClassName()) + && "get".equals(name) + && methodType.getArgumentTypes().length == 2) { + // in case of invalid scenario (not using .class ref directly) don't store anything and + // clear the last LDC stack + // note that FieldBackedProvider also check for an invalid context call in the runtime + if (lastTwoClassConstants.remainingCapacity() == 0) { + String className = lastTwoClassConstants.poll(); + String contextClassName = lastTwoClassConstants.poll(); + contextStoreClasses.put(className, contextClassName); + } else { + throw new MuzzleCompilationException( + "Invalid InstrumentationContext#get(Class, Class) usage: you cannot pass variables," + + " method parameters, compute classes; class references need to be passed" + + " directly to the get() method"); + } + } + + registerOpcode(opcode, null); + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + } + + @Override + public void visitJumpInsn(int opcode, Label label) { + registerOpcode(opcode, null); + super.visitJumpInsn(opcode, label); + } + + @Override + public void visitLdcInsn(Object value) { + registerOpcode(Opcodes.LDC, value); + super.visitLdcInsn(value); + } + private void registerOpcode(int opcode, Object value) { // check if this is an LDC instruction; if so, remember the class that was used // we need to remember last two LDC instructions that were executed before @@ -529,7 +565,7 @@ private void registerOpcode(int opcode, Object value) { // instruction other than LDC visited; pop the first element if present - this will // prevent adding wrong context key pairs in case of an invalid scenario - lastTwoClassConstants.pop(); + lastTwoClassConstants.poll(); } } } diff --git a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java b/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java deleted file mode 100644 index 52df4b7f004a..000000000000 --- a/javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/muzzle/collector/FixedSizeQueueTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.tooling.muzzle.collector; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.Test; - -class FixedSizeQueueTest { - @Test - void shouldRemoveOldestItems() { - // given - FixedSizeQueue underTest = new FixedSizeQueue<>(2); - - // when - underTest.add("class 1"); - underTest.add("class 2"); - - // then - assertThat(underTest).containsExactly("class 1", "class 2"); - assertThat(underTest.hasMaxSize()).isTrue(); - - // when - underTest.add("class 3"); - - // then - assertThat(underTest).containsExactly("class 2", "class 3"); - assertThat(underTest.hasMaxSize()).isTrue(); - } - - @Test - void shouldNotThrowOnPopIfEmpty() { - // given - FixedSizeQueue underTest = new FixedSizeQueue<>(2); - - // when - underTest.pop(); - underTest.pop(); - - // then no exception is thrown - } - - @Test - void shouldClearQueue() { - // given - FixedSizeQueue underTest = new FixedSizeQueue<>(2); - underTest.add("class 1"); - underTest.add("class 2"); - - // when - underTest.clear(); - - // then - assertThat(underTest).isEmpty(); - } -} diff --git a/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java b/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java index 7804b9997657..9bfdbac57580 100644 --- a/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java +++ b/testing-common/integration-tests/src/main/java/context/ContextTestInstrumentationModule.java @@ -62,8 +62,6 @@ public Map, String> transfor transformers.put(named("getContextCount"), GetApiUsageAdvice.class.getName()); transformers.put(named("putContextCount"), PutApiUsageAdvice.class.getName()); transformers.put(named("removeContextCount"), RemoveApiUsageAdvice.class.getName()); - transformers.put( - named("incorrectCallUsage"), IncorrectCallContextApiUsageAdvice.class.getName()); return transformers; } } @@ -128,16 +126,6 @@ public static void methodExit(@Advice.This KeyClass thiz) { } } - public static class IncorrectCallContextApiUsageAdvice { - @Advice.OnMethodExit - public static void methodExit() { - // Our instrumentation doesn't handle variables being passed to InstrumentationContext.get, - // so we make sure that this actually fails instrumentation. - Class clazz = null; - InstrumentationContext.get(clazz, Object.class); - } - } - public static class Context { public static final ContextStore.Factory FACTORY = Context::new; diff --git a/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy b/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy index 1883eec16ae5..a8b91421384b 100644 --- a/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy +++ b/testing-common/integration-tests/src/test/groovy/context/FieldBackedProviderTest.groovy @@ -15,7 +15,6 @@ import java.lang.reflect.Field import java.lang.reflect.Method import java.lang.reflect.Modifier import java.util.concurrent.atomic.AtomicReference -import library.IncorrectCallUsageKeyClass import library.KeyClass import library.UntransformableKeyClass import net.bytebuddy.agent.ByteBuddyAgent @@ -185,11 +184,6 @@ class FieldBackedProviderTest extends AgentInstrumentationSpecification { new KeyClass().incrementContextCount() == 1 new UntransformableKeyClass().incrementContextCount() == 1 } - - def "incorrect call usage fails at class load time"() { - expect: - !new IncorrectCallUsageKeyClass().isInstrumented() - } } diff --git a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectCallUsageKeyClass.java b/testing-common/library-for-integration-tests/src/main/java/library/IncorrectCallUsageKeyClass.java deleted file mode 100644 index d37f3c38accc..000000000000 --- a/testing-common/library-for-integration-tests/src/main/java/library/IncorrectCallUsageKeyClass.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package library; - -public class IncorrectCallUsageKeyClass { - public boolean isInstrumented() { - return false; - } - - public int incorrectCallUsage() { - // instrumentation will not apply to this class because advice incorrectly uses context api - return -1; - } -} diff --git a/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy b/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy index 12cbbbfcd633..19d9dd314ac6 100644 --- a/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy +++ b/testing-common/src/test/groovy/muzzle/ReferenceCollectorTest.groovy @@ -19,6 +19,7 @@ import io.opentelemetry.instrumentation.InstrumentationContextTestClasses import io.opentelemetry.instrumentation.OtherTestHelperClasses import io.opentelemetry.instrumentation.TestHelperClasses import io.opentelemetry.javaagent.tooling.muzzle.Reference +import io.opentelemetry.javaagent.tooling.muzzle.collector.MuzzleCompilationException import io.opentelemetry.javaagent.tooling.muzzle.collector.ReferenceCollector import spock.lang.Specification import spock.lang.Unroll @@ -276,8 +277,7 @@ class ReferenceCollectorTest extends Specification { collector.collectReferencesFromAdvice(adviceClassName) then: - def contextStore = collector.getContextStoreClasses() - contextStore.isEmpty() + thrown(MuzzleCompilationException) where: desc | adviceClassName