Better muzzle instrumentation exclusion (#6044)

* Better muzzle instrumentation exclusion

* set
This commit is contained in:
Trask Stalnaker 2022-05-18 11:15:57 -07:00 committed by GitHub
parent beb00cd03e
commit d3be07eb1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 23 additions and 20 deletions

View File

@ -287,7 +287,7 @@ fun addMuzzleTask(muzzleDirective: MuzzleDirective, versionArtifact: Artifact?,
val userCL = createClassLoaderForTask(config) val userCL = createClassLoaderForTask(config)
withContextClassLoader(instrumentationCL) { withContextClassLoader(instrumentationCL) {
MuzzleGradlePluginUtil.assertInstrumentationMuzzled(instrumentationCL, userCL, MuzzleGradlePluginUtil.assertInstrumentationMuzzled(instrumentationCL, userCL,
muzzleDirective.excludedInstrumentationModules.get(), muzzleDirective.assertPass.get()) muzzleDirective.excludedInstrumentationNames.get(), muzzleDirective.assertPass.get())
} }
for (thread in Thread.getAllStackTraces().keys) { for (thread in Thread.getAllStackTraces().keys) {
@ -351,7 +351,7 @@ fun inverseOf(muzzleDirective: MuzzleDirective, system: RepositorySystem, sessio
assertPass.set(!muzzleDirective.assertPass.get()) assertPass.set(!muzzleDirective.assertPass.get())
additionalDependencies.set(muzzleDirective.additionalDependencies) additionalDependencies.set(muzzleDirective.additionalDependencies)
excludedDependencies.set(muzzleDirective.excludedDependencies) excludedDependencies.set(muzzleDirective.excludedDependencies)
excludedInstrumentationModules.set(muzzleDirective.excludedInstrumentationModules) excludedInstrumentationNames.set(muzzleDirective.excludedInstrumentationNames)
} }
inverseDirectives.add(inverseDirective) inverseDirectives.add(inverseDirective)
} }

View File

@ -20,7 +20,7 @@ abstract class MuzzleDirective {
abstract val skipVersions: SetProperty<String> abstract val skipVersions: SetProperty<String>
abstract val additionalDependencies: ListProperty<Any> abstract val additionalDependencies: ListProperty<Any>
abstract val excludedDependencies: ListProperty<String> abstract val excludedDependencies: ListProperty<String>
abstract val excludedInstrumentationModules: ListProperty<String> abstract val excludedInstrumentationNames: SetProperty<String>
abstract val assertPass: Property<Boolean> abstract val assertPass: Property<Boolean>
abstract val assertInverse: Property<Boolean> abstract val assertInverse: Property<Boolean>
internal abstract val coreJdk: Property<Boolean> // use coreJdk() function below to enable internal abstract val coreJdk: Property<Boolean> // use coreJdk() function below to enable
@ -31,7 +31,7 @@ abstract class MuzzleDirective {
skipVersions.convention(emptySet()) skipVersions.convention(emptySet())
additionalDependencies.convention(listOf()) additionalDependencies.convention(listOf())
excludedDependencies.convention(listOf()) excludedDependencies.convention(listOf())
excludedInstrumentationModules.convention(listOf()) excludedInstrumentationNames.convention(listOf())
assertPass.convention(false) assertPass.convention(false)
assertInverse.convention(false) assertInverse.convention(false)
coreJdk.convention(false) coreJdk.convention(false)
@ -65,8 +65,8 @@ abstract class MuzzleDirective {
* *
* @param excludeString An instrumentation module class name to exclude * @param excludeString An instrumentation module class name to exclude
*/ */
fun excludeInstrumentationModule(excludeString: String) { fun excludeInstrumentationName(excludeString: String) {
excludedInstrumentationModules.add(excludeString) excludedInstrumentationNames.add(excludeString)
} }
fun skip(vararg version: String?) { fun skip(vararg version: String?) {

View File

@ -53,7 +53,7 @@ class MuzzleGradlePluginUtil {
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun assertInstrumentationMuzzled(agentClassLoader: ClassLoader, userClassLoader: ClassLoader, fun assertInstrumentationMuzzled(agentClassLoader: ClassLoader, userClassLoader: ClassLoader,
excludedInstrumentationModules: List<String>, assertPass: Boolean) { excludedInstrumentationNames: Set<String>, assertPass: Boolean) {
val matcherClass = agentClassLoader.loadClass("io.opentelemetry.javaagent.tooling.muzzle.ClassLoaderMatcher") val matcherClass = agentClassLoader.loadClass("io.opentelemetry.javaagent.tooling.muzzle.ClassLoaderMatcher")
@ -63,13 +63,11 @@ class MuzzleGradlePluginUtil {
// We cannot reference Mismatch class directly here, because we are loaded from a different // We cannot reference Mismatch class directly here, because we are loaded from a different
// classloader. // classloader.
val allMismatches = matcherClass val allMismatches = matcherClass
.getMethod("matchesAll", ClassLoader::class.java, Boolean::class.javaPrimitiveType) .getMethod("matchesAll", ClassLoader::class.java, Boolean::class.javaPrimitiveType, Set::class.java)
.invoke(null, userClassLoader, assertPass) .invoke(null, userClassLoader, assertPass, excludedInstrumentationNames)
as Map<String, List<Any>> as Map<String, List<Any>>
allMismatches.filterKeys { allMismatches.forEach { moduleName, mismatches ->
!excludedInstrumentationModules.contains(it)
}.forEach { (moduleName, mismatches) ->
val passed = mismatches.isEmpty() val passed = mismatches.isEmpty()
if (passed && !assertPass) { if (passed && !assertPass) {
System.err.println("MUZZLE PASSED $moduleName BUT FAILURE WAS EXPECTED") System.err.println("MUZZLE PASSED $moduleName BUT FAILURE WAS EXPECTED")

View File

@ -14,7 +14,7 @@ muzzle {
// if you want to test them anyways, comment out "alpha" from the exclusions in AcceptableVersions.kt // if you want to test them anyways, comment out "alpha" from the exclusions in AcceptableVersions.kt
versions.set("[1.14.0-alpha,)") versions.set("[1.14.0-alpha,)")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.opentelemetryapi.OpenTelemetryApiInstrumentationModule") excludeInstrumentationName("opentelemetry-api")
} }
} }

View File

@ -9,7 +9,7 @@ muzzle {
versions.set("[3.1.0.RELEASE,)") versions.set("[3.1.0.RELEASE,)")
extraDependency("io.opentelemetry:opentelemetry-api:1.0.0") extraDependency("io.opentelemetry:opentelemetry-api:1.0.0")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.opentelemetryapi.OpenTelemetryApiInstrumentationModule") excludeInstrumentationName("opentelemetry-api")
} }
} }

View File

@ -8,14 +8,14 @@ muzzle {
module.set("reactor-netty") module.set("reactor-netty")
versions.set("[0.8.2.RELEASE,1.0.0)") versions.set("[0.8.2.RELEASE,1.0.0)")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyInstrumentationModule") excludeInstrumentationName("netty")
} }
fail { fail {
group.set("io.projectreactor.netty") group.set("io.projectreactor.netty")
module.set("reactor-netty-http") module.set("reactor-netty-http")
versions.set("[1.0.0,)") versions.set("[1.0.0,)")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyInstrumentationModule") excludeInstrumentationName("netty")
} }
} }

View File

@ -8,14 +8,14 @@ muzzle {
module.set("reactor-netty") module.set("reactor-netty")
versions.set("[,1.0.0)") versions.set("[,1.0.0)")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyInstrumentationModule") excludeInstrumentationName("netty")
} }
pass { pass {
group.set("io.projectreactor.netty") group.set("io.projectreactor.netty")
module.set("reactor-netty-http") module.set("reactor-netty-http")
versions.set("[1.0.0,)") versions.set("[1.0.0,)")
assertInverse.set(true) assertInverse.set(true)
excludeInstrumentationModule("io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyInstrumentationModule") excludeInstrumentationName("netty")
} }
} }

View File

@ -11,6 +11,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set;
/** /**
* This class verifies that a given {@link ClassLoader} satisfies all expectations of a given {@link * This class verifies that a given {@link ClassLoader} satisfies all expectations of a given {@link
@ -30,12 +31,16 @@ public class ClassLoaderMatcher {
* <p>The returned map will be empty if and only if no instrumentation modules were found. * <p>The returned map will be empty if and only if no instrumentation modules were found.
*/ */
public static Map<String, List<Mismatch>> matchesAll( public static Map<String, List<Mismatch>> matchesAll(
ClassLoader classLoader, boolean injectHelpers) { ClassLoader classLoader, boolean injectHelpers, Set<String> excludedInstrumentationNames) {
Map<String, List<Mismatch>> result = new HashMap<>(); Map<String, List<Mismatch>> result = new HashMap<>();
ServiceLoader.load(InstrumentationModule.class) ServiceLoader.load(InstrumentationModule.class)
.forEach( .forEach(
module -> { module -> {
result.put(module.getClass().getName(), matches(module, classLoader, injectHelpers)); if (module.instrumentationNames().stream()
.noneMatch(excludedInstrumentationNames::contains)) {
result.put(
module.getClass().getName(), matches(module, classLoader, injectHelpers));
}
}); });
return result; return result;
} }