diff --git a/build.gradle b/build.gradle index fa5a5a3cd535..06f1d4f0d89d 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,6 @@ plugins { id 'org.unbroken-dome.test-sets' apply false id 'com.github.ben-manes.versions' - id "com.github.johnrengelman.shadow" apply false - id "com.diffplug.spotless" id "net.ltgt.errorprone" apply false id "net.ltgt.nullaway" apply false diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index ce532b4e2b15..000000000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -plugins { - id 'java-gradle-plugin' - id "com.diffplug.spotless" version "5.12.4" -} - -spotless { - java { - googleJavaFormat('1.10.0') - licenseHeaderFile rootProject.file('../gradle/enforcement/spotless.license.java'), '(package|import|public)' - target 'src/**/*.java' - } -} - -gradlePlugin { - plugins { - create("muzzle-plugin") { - id = "muzzle" - implementationClass = "io.opentelemetry.instrumentation.gradle.muzzle.MuzzlePlugin" - } - } -} - -repositories { - mavenLocal() - mavenCentral() -} - -test { - useJUnitPlatform() -} - -dependencies { - implementation(gradleApi()) - implementation(localGroovy()) - - implementation "org.eclipse.aether:aether-connector-basic:1.1.0" - implementation "org.eclipse.aether:aether-transport-http:1.1.0" - implementation "org.apache.maven:maven-aether-provider:3.3.9" - - implementation "com.google.guava:guava:30.1-jre" - implementation "org.ow2.asm:asm:7.0-beta" - implementation "org.ow2.asm:asm-tree:7.0-beta" - implementation "org.apache.httpcomponents:httpclient:4.5.10" - implementation "net.bytebuddy:byte-buddy-gradle-plugin:1.10.18" - - testImplementation "org.junit.jupiter:junit-jupiter-api:5.7.1" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.7.1" - testImplementation "org.assertj:assertj-core:3.19.0" -} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000000..b81cce1c9862 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,53 @@ +plugins { + `java-gradle-plugin` + `kotlin-dsl` + id("com.diffplug.spotless") version "5.12.4" +} + +spotless { + java { + googleJavaFormat("1.10.0") + licenseHeaderFile(rootProject.file("../gradle/enforcement/spotless.license.java"), "(package|import|public)") + target("src/**/*.java") + } +} + +gradlePlugin { + plugins { + create("muzzle-plugin") { + id = "muzzle" + implementationClass = "io.opentelemetry.instrumentation.gradle.muzzle.MuzzlePlugin" + } + } +} + +repositories { + mavenCentral() + gradlePluginPortal() + mavenLocal() +} + +tasks.withType().configureEach { + useJUnitPlatform() +} + +dependencies { + implementation(gradleApi()) + implementation(localGroovy()) + + implementation("org.eclipse.aether:aether-connector-basic:1.1.0") + implementation("org.eclipse.aether:aether-transport-http:1.1.0") + implementation("org.apache.maven:maven-aether-provider:3.3.9") + + implementation("com.google.guava:guava:30.1-jre") + implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0") + implementation("org.ow2.asm:asm:7.0-beta") + implementation("org.ow2.asm:asm-tree:7.0-beta") + implementation("org.apache.httpcomponents:httpclient:4.5.10") + // When updating, also update dependencyManagement/dependencyManagement.gradle.kts + implementation("net.bytebuddy:byte-buddy-gradle-plugin:1.11.2") + + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.1") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.1") + testImplementation("org.assertj:assertj-core:3.19.0") +} diff --git a/buildSrc/src/main/kotlin/otel.shadow-conventions.gradle.kts b/buildSrc/src/main/kotlin/otel.shadow-conventions.gradle.kts new file mode 100644 index 000000000000..80935e069067 --- /dev/null +++ b/buildSrc/src/main/kotlin/otel.shadow-conventions.gradle.kts @@ -0,0 +1,33 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + id("com.github.johnrengelman.shadow") +} + +tasks.withType().configureEach { + mergeServiceFiles() + + exclude("**/module-info.class") + + // Prevents conflict with other SLF4J instances. Important for premain. + relocate("org.slf4j", "io.opentelemetry.javaagent.slf4j") + // rewrite dependencies calling Logger.getLogger + relocate("java.util.logging.Logger", "io.opentelemetry.javaagent.bootstrap.PatchLogger") + + // prevents conflict with library instrumentation + relocate("io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation") + + // relocate(OpenTelemetry API) + relocate("io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api") + relocate("io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv") + relocate("io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context") + + // relocate(the OpenTelemetry extensions that are used by instrumentation modules) + // these extensions live in the AgentClassLoader, and are injected into the user"s class loader + // by the instrumentation modules that use them + relocate("io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws") + relocate("io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin") + + // this is for instrumentation on opentelemetry-api itself + relocate("application.io.opentelemetry", "io.opentelemetry") +} diff --git a/dependencyManagement/dependencyManagement.gradle.kts b/dependencyManagement/dependencyManagement.gradle.kts index 98dc1c6e4d6e..9d80db5e0b55 100644 --- a/dependencyManagement/dependencyManagement.gradle.kts +++ b/dependencyManagement/dependencyManagement.gradle.kts @@ -53,6 +53,7 @@ val DEPENDENCY_SETS = listOf( ), DependencySet( "net.bytebuddy", + // When updating, also update buildSrc/build.gradle.kts "1.11.2", listOf("byte-buddy", "byte-buddy-agent") ), diff --git a/gradle/instrumentation.gradle b/gradle/instrumentation.gradle index bc18e2090e36..c82ef9e76bc9 100644 --- a/gradle/instrumentation.gradle +++ b/gradle/instrumentation.gradle @@ -2,7 +2,7 @@ import io.opentelemetry.instrumentation.gradle.bytebuddy.ByteBuddyPluginConfigurator apply plugin: 'net.bytebuddy.byte-buddy' -apply plugin: 'com.github.johnrengelman.shadow' +apply plugin: 'otel.shadow-conventions' ext { mavenGroupId = 'io.opentelemetry.javaagent.instrumentation' @@ -85,34 +85,8 @@ configurations { tasks.named('shadowJar').configure { configurations = [project.configurations.runtimeClasspath, project.configurations.testInstrumentation] - mergeServiceFiles() archiveFileName = 'agent-testing.jar' - - // rewrite library instrumentation dependencies - relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation" - - // Prevents conflict with other SLF4J instances. Important for premain. - relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j' - // rewrite dependencies calling Logger.getLogger - relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger' - - // prevents conflict with library instrumentation - relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api' - - // relocate OpenTelemetry API usage - relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api" - relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv" - relocate "io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context" - - // relocate the OpenTelemetry extensions that are used by instrumentation modules - // these extensions live in the AgentClassLoader, and are injected into the user's class loader - // by the instrumentation modules that use them - relocate "io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws" - relocate "io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin" - - // this is for instrumentation on opentelemetry-api itself - relocate "application.io.opentelemetry", "io.opentelemetry" } evaluationDependsOn(":testing:agent-for-testing") diff --git a/instrumentation/instrumentation.gradle b/instrumentation/instrumentation.gradle index 7a005c9f9ab7..0c0b54602325 100644 --- a/instrumentation/instrumentation.gradle +++ b/instrumentation/instrumentation.gradle @@ -1,6 +1,6 @@ // this project will run in isolation under the agent's classloader plugins { - id "com.github.johnrengelman.shadow" + id "otel.shadow-conventions" } apply from: "$rootDir/gradle/java.gradle" @@ -36,13 +36,6 @@ configurations { } shadowJar { - mergeServiceFiles() - - exclude '**/module-info.class' - - // Prevents conflict with other SLF4J instances. Important for premain. - relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j' - duplicatesStrategy = DuplicatesStrategy.FAIL dependencies { @@ -51,26 +44,6 @@ shadowJar { exclude(project(':instrumentation-api')) exclude(project(':javaagent-api')) } - - // rewrite library instrumentation dependencies - relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation" - - // rewrite dependencies calling Logger.getLogger - relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger' - - // relocate OpenTelemetry API usage - relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api" - relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv" - relocate "io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context" - - // relocate the OpenTelemetry extensions that are used by instrumentation modules - // these extensions live in the AgentClassLoader, and are injected into the user's class loader - // by the instrumentation modules that use them - relocate "io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws" - relocate "io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin" - - // this is for instrumentation on opentelemetry-api itself - relocate "application.io.opentelemetry", "io.opentelemetry" } tasks.register("listInstrumentations") { 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 850d260a9069..fb50fdda8ae9 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 @@ -14,6 +14,7 @@ import io.opentelemetry.javaagent.extension.muzzle.MethodRef; import io.opentelemetry.javaagent.extension.muzzle.Source; import io.opentelemetry.javaagent.tooling.Utils; +import java.net.URLClassLoader; import java.util.Collection; import java.util.List; import java.util.Map; @@ -158,7 +159,14 @@ private ReferenceCollector collectReferences() { typeInstrumentation.transform(adviceClassNameCollector); } - ReferenceCollector collector = new ReferenceCollector(instrumentationModule::isHelperClass); + // the classloader has a parent including the Gradle classpath, such as buildSrc dependencies. + // These may have resources take precedence over ones we define, so we need to make sure to + // not include them when loading resources. + ClassLoader resourceLoader = + new URLClassLoader( + ((URLClassLoader) MuzzleCodeGenerator.class.getClassLoader()).getURLs(), null); + ReferenceCollector collector = + new ReferenceCollector(instrumentationModule::isHelperClass, resourceLoader); for (String adviceClass : adviceClassNameCollector.getAdviceClassNames()) { collector.collectReferencesFromAdvice(adviceClass); } 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 254651286b80..bdde1db05b51 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 @@ -48,15 +48,24 @@ * plugin. */ 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; + private final ClassLoader resourceLoader; + // only used by tests public ReferenceCollector(Predicate libraryInstrumentationPredicate) { + this(libraryInstrumentationPredicate, ReferenceCollector.class.getClassLoader()); + } + + public ReferenceCollector( + Predicate libraryInstrumentationPredicate, ClassLoader resourceLoader) { this.instrumentationClassPredicate = new InstrumentationClassPredicate(libraryInstrumentationPredicate); + this.resourceLoader = resourceLoader; } /** @@ -158,16 +167,13 @@ private void visitClassesAndCollectReferences( } } - private static InputStream getClassFileStream(String className) throws IOException { + private InputStream getClassFileStream(String className) throws IOException { return getResourceStream(Utils.getResourceName(className)); } - private static InputStream getResourceStream(String resource) throws IOException { + private InputStream getResourceStream(String resource) throws IOException { URLConnection connection = - checkNotNull( - ReferenceCollector.class.getClassLoader().getResource(resource), - "Couldn't find resource %s", - resource) + checkNotNull(resourceLoader.getResource(resource), "Couldn't find resource %s", resource) .openConnection(); // Since the JarFile cache is not per class loader, but global with path as key, using cache may diff --git a/javaagent/javaagent.gradle b/javaagent/javaagent.gradle index 7a6e0e9d4b16..02de6cde89bf 100644 --- a/javaagent/javaagent.gradle +++ b/javaagent/javaagent.gradle @@ -3,7 +3,7 @@ import com.github.jk1.license.filter.LicenseBundleNormalizer import com.github.jk1.license.render.InventoryMarkdownReportRenderer plugins { - id "com.github.johnrengelman.shadow" + id "otel.shadow-conventions" id "com.github.jk1.dependency-license-report" version "1.16" } @@ -60,8 +60,6 @@ shadowJar { //Includes instrumentations, but not exporters task lightShadow(type: ShadowJar) { - from sourceSets.main.output - dependsOn ':instrumentation:shadowJar' def projectsWithShadowJar = [project(':instrumentation')] with isolateSpec(projectsWithShadowJar) @@ -77,32 +75,10 @@ publishing { tasks.withType(ShadowJar).configureEach { configurations = [project.configurations.shadowInclude] - mergeServiceFiles() manifest { inheritFrom project.tasks.jar.manifest } - - exclude '**/module-info.class' - - // Prevents conflict with other SLF4J instances. Important for premain. - relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j' - // rewrite dependencies calling Logger.getLogger - relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger' - - // prevents conflict with library instrumentation - relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api' - - // relocate OpenTelemetry API - relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api" - relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv" - relocate "io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context" - - // relocate the OpenTelemetry extensions that are used by instrumentation modules - // these extensions live in the AgentClassLoader, and are injected into the user's class loader - // by the instrumentation modules that use them - relocate "io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws" - relocate "io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin" } configurations { diff --git a/settings.gradle b/settings.gradle index 5b22a9637ca7..aa0e0af23805 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,7 +2,6 @@ pluginManagement { plugins { id "com.diffplug.spotless" version "5.12.4" id 'com.github.ben-manes.versions' version '0.27.0' - id "com.github.johnrengelman.shadow" version "6.1.0" id "io.github.gradle-nexus.publish-plugin" version "1.0.0" id "me.champeau.jmh" version "0.6.4" id "net.ltgt.errorprone" version "1.3.0" diff --git a/testing/agent-exporter/agent-exporter.gradle b/testing/agent-exporter/agent-exporter.gradle index 3bb1ed971e80..6c94a3910e8b 100644 --- a/testing/agent-exporter/agent-exporter.gradle +++ b/testing/agent-exporter/agent-exporter.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" + id "otel.shadow-conventions" } apply from: "$rootDir/gradle/java.gradle" @@ -39,31 +39,4 @@ dependencies { jar.enabled = false shadowJar { archiveFileName = 'testing-agent-classloader.jar' - - mergeServiceFiles() - - exclude '**/module-info.class' - - // Prevents conflict with other SLF4J instances. Important for premain. - relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j' - - // rewrite library instrumentation dependencies - relocate "io.opentelemetry.instrumentation", "io.opentelemetry.javaagent.shaded.instrumentation" - - // rewrite dependencies calling Logger.getLogger - relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger' - - // relocate OpenTelemetry API usage - relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api" - relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv" - relocate "io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context" - - // relocate the OpenTelemetry extensions that are used by instrumentation modules - // these extensions live in the AgentClassLoader, and are injected into the user's class loader - // by the instrumentation modules that use them - relocate "io.opentelemetry.extension.aws", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws" - relocate "io.opentelemetry.extension.kotlin", "io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.kotlin" - - // this is for instrumentation on opentelemetry-api itself - relocate "application.io.opentelemetry", "io.opentelemetry" } \ No newline at end of file diff --git a/testing/agent-for-testing/agent-for-testing.gradle b/testing/agent-for-testing/agent-for-testing.gradle index 571d99f661ad..7f6ad5817cd8 100644 --- a/testing/agent-for-testing/agent-for-testing.gradle +++ b/testing/agent-for-testing/agent-for-testing.gradle @@ -1,5 +1,5 @@ plugins { - id "com.github.johnrengelman.shadow" + id "otel.shadow-conventions" } description = 'OpenTelemetry Javaagent for testing' @@ -52,26 +52,6 @@ shadowJar { manifest { inheritFrom project.tasks.jar.manifest } - - mergeServiceFiles() - - exclude '**/module-info.class' - - // Prevents conflict with other SLF4J instances. Important for premain. - relocate 'org.slf4j', 'io.opentelemetry.javaagent.slf4j' - // rewrite dependencies calling Logger.getLogger - relocate 'java.util.logging.Logger', 'io.opentelemetry.javaagent.bootstrap.PatchLogger' - - // prevents conflict with library instrumentation - relocate 'io.opentelemetry.instrumentation.api', 'io.opentelemetry.javaagent.shaded.instrumentation.api' - - // relocate OpenTelemetry API - relocate "io.opentelemetry.api", "io.opentelemetry.javaagent.shaded.io.opentelemetry.api" - relocate "io.opentelemetry.semconv", "io.opentelemetry.javaagent.shaded.io.opentelemetry.semconv" - relocate "io.opentelemetry.context", "io.opentelemetry.javaagent.shaded.io.opentelemetry.context" - - // this is for instrumentation on opentelemetry-api itself - relocate "application.io.opentelemetry", "io.opentelemetry" } jar {