directives = new ArrayList<>()
+ private final ObjectFactory objectFactory
+
+ @javax.inject.Inject
+ MuzzleExtension(final ObjectFactory objectFactory) {
+ this.objectFactory = objectFactory
+ }
+
+ void pass(Action super MuzzleDirective> action) {
+ final MuzzleDirective pass = objectFactory.newInstance(MuzzleDirective)
+ action.execute(pass)
+ pass.assertPass = true
+ directives.add(pass)
+ }
+
+ void fail(Action super MuzzleDirective> action) {
+ final MuzzleDirective fail = objectFactory.newInstance(MuzzleDirective)
+ action.execute(fail)
+ fail.assertPass = false
+ directives.add(fail)
+ }
}
diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java
index 5490e6cdcd..f7a00b78db 100644
--- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java
+++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/MuzzleVersionScanPlugin.java
@@ -2,9 +2,12 @@ package datadog.trace.agent.tooling.muzzle;
import datadog.trace.agent.tooling.HelperInjector;
import datadog.trace.agent.tooling.Instrumenter;
+import datadog.trace.bootstrap.WeakMap;
import java.lang.reflect.Method;
+import java.util.Collections;
import java.util.List;
import java.util.ServiceLoader;
+import java.util.WeakHashMap;
/**
* Entry point for muzzle version scan gradle plugin.
@@ -15,7 +18,19 @@ import java.util.ServiceLoader;
* Additionally, after a successful muzzle validation run each instrumenter's helper injector.
*/
public class MuzzleVersionScanPlugin {
- public static void assertInstrumentationNotMuzzled(ClassLoader cl) throws Exception {
+ static {
+ // prevent WeakMap from logging warning while plugin is running
+ WeakMap.Provider.registerIfAbsent(
+ new WeakMap.Supplier() {
+ @Override
+ public WeakMap get() {
+ return new WeakMap.MapAdapter<>(Collections.synchronizedMap(new WeakHashMap()));
+ }
+ });
+ }
+
+ public static void assertInstrumentationMuzzled(ClassLoader cl, boolean assertPass)
+ throws Exception {
// muzzle validate all instrumenters
for (Instrumenter instrumenter :
ServiceLoader.load(Instrumenter.class, MuzzleGradlePlugin.class.getClassLoader())) {
@@ -36,7 +51,12 @@ public class MuzzleVersionScanPlugin {
m.setAccessible(true);
ReferenceMatcher muzzle = (ReferenceMatcher) m.invoke(instrumenter);
List mismatches = muzzle.getMismatchedReferenceSources(cl);
- if (mismatches.size() > 0) {
+ boolean passed = mismatches.size() == 0;
+ if (mismatches.size() > 0) {}
+ if (passed && !assertPass) {
+ System.err.println("MUZZLE PASSED BUT FAILURE WAS EXPECTED");
+ throw new RuntimeException("Instrumentation unexpectedly passed Muzzle validation");
+ } else if (!passed && assertPass) {
System.err.println(
"FAILED MUZZLE VALIDATION: " + instrumenter.getClass().getName() + " mismatches:");
for (Reference.Mismatch mismatch : mismatches) {
@@ -51,33 +71,35 @@ public class MuzzleVersionScanPlugin {
}
}
// run helper injector on all instrumenters
- for (Instrumenter instrumenter :
- ServiceLoader.load(Instrumenter.class, MuzzleGradlePlugin.class.getClassLoader())) {
- if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
- // TraceConfigInstrumentation doesn't do muzzle checks
- // check on TracerClassInstrumentation instead
- instrumenter =
- (Instrumenter)
- MuzzleGradlePlugin.class
- .getClassLoader()
- .loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation")
- .getDeclaredConstructor()
- .newInstance();
- }
- try {
- // Ratpack injects the scope manager as a helper.
- // This is likely a bug, but we'll grandfather it out of the helper checks for now.
- if (!instrumenter.getClass().getName().contains("Ratpack")) {
- // verify helper injector works
- final String[] helperClassNames = instrumenter.helperClassNames();
- if (helperClassNames.length > 0) {
- new HelperInjector(helperClassNames).transform(null, null, cl, null);
- }
+ if (assertPass) {
+ for (Instrumenter instrumenter :
+ ServiceLoader.load(Instrumenter.class, MuzzleGradlePlugin.class.getClassLoader())) {
+ if (instrumenter.getClass().getName().endsWith("TraceConfigInstrumentation")) {
+ // TraceConfigInstrumentation doesn't do muzzle checks
+ // check on TracerClassInstrumentation instead
+ instrumenter =
+ (Instrumenter)
+ MuzzleGradlePlugin.class
+ .getClassLoader()
+ .loadClass(instrumenter.getClass().getName() + "$TracerClassInstrumentation")
+ .getDeclaredConstructor()
+ .newInstance();
+ }
+ try {
+ // Ratpack injects the scope manager as a helper.
+ // This is likely a bug, but we'll grandfather it out of the helper checks for now.
+ if (!instrumenter.getClass().getName().contains("Ratpack")) {
+ // verify helper injector works
+ final String[] helperClassNames = instrumenter.helperClassNames();
+ if (helperClassNames.length > 0) {
+ new HelperInjector(helperClassNames).transform(null, null, cl, null);
+ }
+ }
+ } catch (Exception e) {
+ System.err.println(
+ "FAILED HELPER INJECTION. Are Helpers being injected in the correct order?");
+ throw e;
}
- } catch (Exception e) {
- System.err.println(
- "FAILED HELPER INJECTION. Are Helpers being injected in the correct order?");
- throw e;
}
}
}
diff --git a/dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle b/dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle
index e10a43321c..34829de3c3 100644
--- a/dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle
+++ b/dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle
@@ -16,6 +16,24 @@ compileLagomTestGroovy {
targetCompatibility = 1.8
}
+
+muzzle {
+ pass {
+ group = 'com.typesafe.akka'
+ module = 'akka-http_2.11'
+ versions = "[10.0.0,)"
+ // later versions of akka-http expect streams to be provided
+ extraDependency 'com.typesafe.akka:akka-stream_2.11:2.4.14'
+ }
+ pass {
+ group = 'com.typesafe.akka'
+ module = 'akka-http_2.12'
+ versions = "[10.0.0,)"
+ // later versions of akka-http expect streams to be provided
+ extraDependency 'com.typesafe.akka:akka-stream_2.12:2.4.14'
+ }
+}
+
dependencies {
compileOnly group: 'com.typesafe.akka', name: 'akka-http_2.11', version: '10.0.0'
diff --git a/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle b/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
index d4ed32568a..75abaff407 100644
--- a/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
+++ b/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
@@ -1,29 +1,19 @@
-apply plugin: 'version-scan'
-
-versionScan {
- group = "org.apache.httpcomponents"
- module = "httpclient"
- versions = "[4.3,)"
- legacyGroup = "commons-httpclient"
- legacyModule = "commons-httpclient"
- verifyPresent = [
- // The commented out classes are required for the instrumentation (this is checked by our bytebuddy rules).
- // Once the verifier can report on the failed versions these classes can be commented out and the pass range can be widened.
-
- // "org.apache.http.HttpException" : null,
- // "org.apache.http.HttpRequest" : null,
- // "org.apache.http.client.RedirectStrategy" : null,
- "org.apache.http.client.methods.CloseableHttpResponse": null,
- "org.apache.http.client.methods.HttpExecutionAware" : null,
- "org.apache.http.client.methods.HttpRequestWrapper" : null,
- "org.apache.http.client.protocol.HttpClientContext" : null,
- // "org.apache.http.conn.routing.HttpRoute" : null,
- "org.apache.http.impl.execchain.ClientExecChain" : null
- ]
-}
-
apply from: "${rootDir}/gradle/java.gradle"
+muzzle {
+ fail {
+ group = "commons-httpclient"
+ module = "commons-httpclient"
+ versions = "[,4.3)"
+ }
+ pass {
+ group = "org.apache.httpcomponents"
+ module = "httpclient"
+ versions = "[4.3,)"
+ assertInverse = true
+ }
+}
+
apply plugin: 'org.unbroken-dome.test-sets'
testSets {
diff --git a/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientInstrumentation.java b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientInstrumentation.java
index 1973afa5b0..2e4fde528c 100644
--- a/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientInstrumentation.java
+++ b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientInstrumentation.java
@@ -1,7 +1,6 @@
package datadog.trace.instrumentation.apachehttpclient;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
-import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@@ -36,22 +35,6 @@ public class ApacheHttpClientInstrumentation extends Instrumenter.Default {
.or(safeHasSuperType(named("org.apache.http.impl.client.CloseableHttpClient")));
}
- @Override
- public ElementMatcher classLoaderMatcher() {
- return classLoaderHasClasses(
- "org.apache.http.HttpException",
- "org.apache.http.HttpRequest",
- "org.apache.http.client.RedirectStrategy",
- "org.apache.http.client.methods.CloseableHttpResponse",
- "org.apache.http.client.methods.HttpExecutionAware",
- "org.apache.http.client.methods.HttpRequestWrapper",
- "org.apache.http.client.protocol.HttpClientContext",
- "org.apache.http.conn.routing.HttpRoute",
- "org.apache.http.impl.execchain.ClientExecChain",
- "org.apache.http.impl.client.CloseableHttpClient",
- "org.apache.http.impl.client.InternalHttpClient");
- }
-
@Override
public String[] helperClassNames() {
return new String[] {
diff --git a/dd-java-agent/instrumentation/play-2.4/play-2.4.gradle b/dd-java-agent/instrumentation/play-2.4/play-2.4.gradle
index 7173c28208..1014bab501 100644
--- a/dd-java-agent/instrumentation/play-2.4/play-2.4.gradle
+++ b/dd-java-agent/instrumentation/play-2.4/play-2.4.gradle
@@ -7,6 +7,19 @@ testSets {
latestDepTest
}
+muzzle {
+ pass {
+ group = 'com.typesafe.play'
+ module = 'play_2.11'
+ versions = '[2.4.0,2.7.0-M1)'
+ }
+ pass {
+ group = 'com.typesafe.play'
+ module = 'play_2.12'
+ versions = '[2.4.0,2.7.0-M1)'
+ }
+}
+
dependencies {
compileOnly group: 'com.typesafe.play', name: 'play_2.11', version: '2.4.0'
diff --git a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play/PlayInstrumentation.java b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play/PlayInstrumentation.java
index 15f41e3c92..0310342e70 100644
--- a/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play/PlayInstrumentation.java
+++ b/dd-java-agent/instrumentation/play-2.4/src/main/java/datadog/trace/instrumentation/play/PlayInstrumentation.java
@@ -1,8 +1,6 @@
package datadog.trace.instrumentation.play;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
-import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClassWithMethod;
-import static datadog.trace.agent.tooling.ClassLoaderMatcher.classLoaderHasClasses;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
@@ -50,18 +48,6 @@ public final class PlayInstrumentation extends Instrumenter.Default {
return safeHasSuperType(named("play.api.mvc.Action"));
}
- @Override
- public ElementMatcher classLoaderMatcher() {
- return classLoaderHasClasses(
- "akka.japi.JavaPartialFunction",
- "play.api.mvc.Action",
- "play.api.mvc.Result",
- "scala.Option",
- "scala.Tuple2",
- "scala.concurrent.Future")
- .and(classLoaderHasClassWithMethod("play.api.mvc.Request", "tags"));
- }
-
@Override
public String[] helperClassNames() {
return new String[] {