Browse Source

Split up build logic to plugins that can eventually be published and … (#3474)

* Split up build logic to plugins that can eventually be published and this-repo-specific stuff.

* Muzzle

* compileOnly

* Typo
Anuraag Agrawal 3 years ago
parent
commit
8eb24f9886

+ 0 - 9
buildSrc/build.gradle.kts

@@ -13,15 +13,6 @@ spotless {
   }
 }
 
-gradlePlugin {
-  plugins {
-    create("muzzle-plugin") {
-      id = "muzzle"
-      implementationClass = "io.opentelemetry.instrumentation.gradle.muzzle.MuzzlePlugin"
-    }
-  }
-}
-
 repositories {
   mavenCentral()
   gradlePluginPortal()

+ 10 - 12
buildSrc/src/main/kotlin/otel.instrumentation-conventions.gradle.kts → buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.base.gradle.kts

@@ -1,7 +1,16 @@
 /** Common setup for manual instrumentation of libraries and javaagent instrumentation. */
 
 plugins {
-  id("otel.java-conventions")
+  `java-library`
+}
+
+afterEvaluate {
+  configurations.configureEach {
+    if (isCanBeResolved && !isCanBeConsumed) {
+      // TODO(anuraaga): Read version from properties file embedded by build.
+      project.dependencies.add(name, project.dependencies.platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.3.1-alpha"))
+    }
+  }
 }
 
 /**
@@ -86,14 +95,3 @@ if (testLatestDeps) {
     }
   }
 }
-
-when (projectDir.name) {
-  "javaagent", "library", "testing" -> {
-    // We don't use this group anywhere in our config, but we need to make sure it is unique per
-    // instrumentation so Gradle doesn't merge projects with same name due to a bug in Gradle.
-    // https://github.com/gradle/gradle/issues/847
-    // In otel.publish-conventions, we set the maven group, which is what matters, to the correct
-    // value.
-    group = "io.opentelemetry.${projectDir.parentFile.name}"
-  }
-}

+ 0 - 0
buildSrc/src/main/kotlin/otel.javaagent-codegen.gradle.kts → buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-codegen.gradle.kts


+ 10 - 0
buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-instrumentation.gradle.kts

@@ -0,0 +1,10 @@
+plugins {
+  id("io.opentelemetry.instrumentation.javaagent-testing")
+  id("io.opentelemetry.instrumentation.muzzle-check")
+}
+
+dependencies {
+  add("muzzleBootstrap", "io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap")
+  add("muzzleTooling", "io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")
+  add("muzzleTooling", "io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api")
+}

+ 0 - 0
buildSrc/src/main/kotlin/otel.shadow-conventions.gradle.kts → buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-shadowing.gradle.kts


+ 116 - 0
buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.javaagent-testing.gradle.kts

@@ -0,0 +1,116 @@
+import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+
+plugins {
+  `java-library`
+
+  id("net.bytebuddy.byte-buddy")
+
+  id("io.opentelemetry.instrumentation.base")
+  id("io.opentelemetry.instrumentation.javaagent-codegen")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
+}
+
+dependencies {
+  // Integration tests may need to define custom instrumentation modules so we include the standard
+  // instrumentation infrastructure for testing too.
+  compileOnly("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")
+  compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-api")
+  compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap")
+  // Apply common dependencies for instrumentation.
+  compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api") {
+    // OpenTelemetry SDK is not needed for compilation
+    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk")
+    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-metrics")
+  }
+  compileOnly("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling") {
+    // OpenTelemetry SDK is not needed for compilation
+    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk")
+    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-metrics")
+  }
+
+  testImplementation("io.opentelemetry.javaagent:opentelemetry-testing-common")
+
+  add("codegen", "io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap")
+  add("codegen", "io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")
+  add("codegen", "io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api")
+}
+
+val testInstrumentation by configurations.creating {
+  isCanBeConsumed = false
+  isCanBeResolved = true
+}
+
+tasks.named<ShadowJar>("shadowJar").configure {
+  configurations = listOf(project.configurations.runtimeClasspath.get(), testInstrumentation)
+
+  archiveFileName.set("agent-testing.jar")
+}
+
+val agentForTesting by configurations.creating {
+  isCanBeConsumed = false
+  isCanBeResolved = true
+}
+
+dependencies {
+  agentForTesting("io.opentelemetry.javaagent:opentelemetry-agent-for-testing")
+}
+
+// need to run this after evaluate because testSets plugin adds new test tasks
+afterEvaluate {
+  tasks.withType<Test>().configureEach {
+    val shadowJar = tasks.shadowJar.get()
+    val agentShadowJar = agentForTesting.resolve().first()
+
+    inputs.files(agentForTesting)
+    inputs.file(shadowJar.archiveFile)
+
+    dependsOn(shadowJar)
+    // TODO(anuraaga): Figure out why dependsOn override is still needed in otel.javaagent-testing
+    // despite this dependency.
+    dependsOn(agentForTesting.buildDependencies)
+
+    jvmArgs("-Dotel.javaagent.debug=true")
+    jvmArgs("-javaagent:${agentShadowJar.absolutePath}")
+    jvmArgs("-Dotel.javaagent.experimental.initializer.jar=${shadowJar.archiveFile.get().asFile.absolutePath}")
+    jvmArgs("-Dotel.javaagent.testing.additional-library-ignores.enabled=false")
+    val failOnContextLeak = findProperty("failOnContextLeak")
+    jvmArgs("-Dotel.javaagent.testing.fail-on-context-leak=${failOnContextLeak != false}")
+    // prevent sporadic gradle deadlocks, see SafeLogger for more details
+    jvmArgs("-Dotel.javaagent.testing.transform-safe-logging.enabled=true")
+
+    // Reduce noise in assertion messages since we don't need to verify this in most tests. We check
+    // in smoke tests instead.
+    jvmArgs("-Dotel.javaagent.add-thread-details=false")
+
+    // We do fine-grained filtering of the classpath of this codebase's sources since Gradle's
+    // configurations will include transitive dependencies as well, which tests do often need.
+    classpath = classpath.filter {
+      // The sources are packaged into the testing jar so we need to make sure to exclude from the test
+      // classpath, which automatically inherits them, to ensure our shaded versions are used.
+      if (file("${buildDir}/resources/main").equals(it) || file("${buildDir}/classes/java/main").equals(it)) {
+        return@filter false
+      }
+
+      // TODO(anuraaga): Better not to have this folder structure constraints, we can likely use
+      // plugin identification instead.
+
+      // If agent depends on some shared instrumentation module that is not a testing module, it will
+      // be packaged into the testing jar so we need to make sure to exclude from the test classpath.
+      val libPath = it.absolutePath
+      val instrumentationPath = file("${rootDir}/instrumentation/").absolutePath
+      if (libPath.startsWith(instrumentationPath) &&
+        libPath.endsWith(".jar") &&
+        !libPath.substring(instrumentationPath.length).contains("testing")) {
+        return@filter false
+      }
+      return@filter true
+    }
+  }
+}
+
+configurations.configureEach {
+  if (name.toLowerCase().endsWith("testruntimeclasspath")) {
+    // Added by agent, don't let Gradle bring it in when running tests.
+    exclude("io.opentelemetry.javaagent", "opentelemetry-javaagent-bootstrap")
+  }
+}

+ 11 - 0
buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.library-instrumentation.gradle.kts

@@ -0,0 +1,11 @@
+plugins {
+  id("io.opentelemetry.instrumentation.base")
+}
+
+dependencies {
+  api("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")
+
+  api("io.opentelemetry:opentelemetry-api")
+
+  testImplementation("io.opentelemetry.javaagent:opentelemetry-testing-common")
+}

+ 0 - 0
buildSrc/src/main/kotlin/otel.muzzle-check.gradle.kts → buildSrc/src/main/kotlin/io.opentelemetry.instrumentation.muzzle-check.gradle.kts


+ 33 - 0
buildSrc/src/main/kotlin/otel.java-conventions.gradle.kts

@@ -259,3 +259,36 @@ idea {
     setDownloadSources(false)
   }
 }
+
+when (projectDir.name) {
+  "javaagent", "library", "testing" -> {
+    // We don't use this group anywhere in our config, but we need to make sure it is unique per
+    // instrumentation so Gradle doesn't merge projects with same name due to a bug in Gradle.
+    // https://github.com/gradle/gradle/issues/847
+    // In otel.publish-conventions, we set the maven group, which is what matters, to the correct
+    // value.
+    group = "io.opentelemetry.${projectDir.parentFile.name}"
+  }
+}
+
+configurations.configureEach {
+  resolutionStrategy {
+    // While you might think preferProjectModules would do this, it doesn't. If this gets hard to
+    // manage, we could consider having the io.opentelemetry.instrumentation add information about
+    // what modules they add to reference generically.
+    dependencySubstitution {
+      substitute(module("io.opentelemetry.instrumentation:opentelemetry-instrumentation-api")).using(project(":instrumentation-api"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-javaagent-api")).using(project(":javaagent-api"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-javaagent-bootstrap")).using(project(":javaagent-bootstrap"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api")).using(project(":javaagent-extension-api"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-javaagent-tooling")).using(project(":javaagent-tooling"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-agent-for-testing")).using(project(":testing:agent-for-testing"))
+      substitute(module("io.opentelemetry.javaagent:opentelemetry-testing-common")).using(project(":testing-common"))
+    }
+
+    // The above substitutions ensure dependencies managed by this BOM for external projects refer to this repo's projects here.
+    // Excluding the bom as well helps ensure if we miss a substitution, we get a resolution failure instead of using the
+    // wrong version.
+    exclude("io.opentelemetry.instrumentation", "opentelemetry-instrumentation-bom-alpha")
+  }
+}

+ 2 - 8
buildSrc/src/main/kotlin/otel.javaagent-instrumentation.gradle.kts

@@ -1,16 +1,10 @@
 plugins {
   id("otel.javaagent-testing")
   id("otel.publish-conventions")
-  id("otel.muzzle-check")
+
+  id("io.opentelemetry.instrumentation.javaagent-instrumentation")
 }
 
 extra["mavenGroupId"] = "io.opentelemetry.javaagent.instrumentation"
 
 base.archivesName.set(projectDir.parentFile.name)
-
-dependencies {
-  add("muzzleBootstrap", project(path = ":javaagent-bootstrap", configuration = "instrumentationMuzzle"))
-
-  add("muzzleTooling", project(path = ":javaagent-tooling", configuration = "instrumentationMuzzle"))
-  add("muzzleTooling", project(path = ":javaagent-extension-api", configuration = "instrumentationMuzzle"))
-}

+ 11 - 86
buildSrc/src/main/kotlin/otel.javaagent-testing.gradle.kts

@@ -1,100 +1,19 @@
-import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
-
 plugins {
   id("net.bytebuddy.byte-buddy")
 
-  id("otel.instrumentation-conventions")
-  id("otel.javaagent-codegen")
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-testing")
+
+  id("otel.java-conventions")
 }
 
+evaluationDependsOn(":testing:agent-for-testing")
+
 dependencies {
-  // Integration tests may need to define custom instrumentation modules so we include the standard
-  // instrumentation infrastructure for testing too.
-  compileOnly(project(":instrumentation-api"))
-  compileOnly(project(":javaagent-api"))
-  compileOnly(project(":javaagent-bootstrap"))
-  // Apply common dependencies for instrumentation.
-  compileOnly(project(":javaagent-extension-api")) {
-    // OpenTelemetry SDK is not needed for compilation
-    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk")
-    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-metrics")
-  }
-  compileOnly(project(":javaagent-tooling")) {
-    // OpenTelemetry SDK is not needed for compilation
-    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk")
-    exclude(group = "io.opentelemetry", module = "opentelemetry-sdk-metrics")
-  }
-  compileOnly("net.bytebuddy:byte-buddy")
   annotationProcessor("com.google.auto.service:auto-service")
   compileOnly("com.google.auto.service:auto-service")
   compileOnly("org.slf4j:slf4j-api")
 
-  testImplementation(project(":testing-common"))
-
   testImplementation("org.testcontainers:testcontainers")
-
-  add("codegen", project(path = ":javaagent-tooling", configuration = "instrumentationMuzzle"))
-  add("codegen", project(path = ":javaagent-extension-api", configuration = "instrumentationMuzzle"))
-}
-
-val testInstrumentation by configurations.creating {
-  isCanBeConsumed = false
-  isCanBeResolved = true
-}
-
-tasks.named<ShadowJar>("shadowJar").configure {
-  configurations = listOf(project.configurations.runtimeClasspath.get(), testInstrumentation)
-
-  archiveFileName.set("agent-testing.jar")
-}
-
-evaluationDependsOn(":testing:agent-for-testing")
-
-// need to run this after evaluate because testSets plugin adds new test tasks
-afterEvaluate {
-  tasks.withType<Test>().configureEach {
-    val shadowJar = tasks.shadowJar.get()
-    val agentShadowJar = project(":testing:agent-for-testing").tasks.shadowJar.get()
-
-    inputs.file(shadowJar.archiveFile)
-
-    dependsOn(shadowJar)
-    dependsOn(agentShadowJar)
-
-    jvmArgs("-Dotel.javaagent.debug=true")
-    jvmArgs("-javaagent:${agentShadowJar.archiveFile.get().asFile.absolutePath}")
-    jvmArgs("-Dotel.javaagent.experimental.initializer.jar=${shadowJar.archiveFile.get().asFile.absolutePath}")
-    jvmArgs("-Dotel.javaagent.testing.additional-library-ignores.enabled=false")
-    val failOnContextLeak = findProperty("failOnContextLeak")
-    jvmArgs("-Dotel.javaagent.testing.fail-on-context-leak=${failOnContextLeak != false}")
-    // prevent sporadic gradle deadlocks, see SafeLogger for more details
-    jvmArgs("-Dotel.javaagent.testing.transform-safe-logging.enabled=true")
-
-    // Reduce noise in assertion messages since we don't need to verify this in most tests. We check
-    // in smoke tests instead.
-    jvmArgs("-Dotel.javaagent.add-thread-details=false")
-
-    // We do fine-grained filtering of the classpath of this codebase's sources since Gradle's
-    // configurations will include transitive dependencies as well, which tests do often need.
-    classpath = classpath.filter {
-      // The sources are packaged into the testing jar so we need to make sure to exclude from the test
-      // classpath, which automatically inherits them, to ensure our shaded versions are used.
-      if (file("${buildDir}/resources/main").equals(it) || file("${buildDir}/classes/java/main").equals(it)) {
-        return@filter false
-      }
-      // If agent depends on some shared instrumentation module that is not a testing module, it will
-      // be packaged into the testing jar so we need to make sure to exclude from the test classpath.
-      val libPath = it.absolutePath
-      val instrumentationPath = file("${rootDir}/instrumentation/").absolutePath
-      if (libPath.startsWith(instrumentationPath) &&
-        libPath.endsWith(".jar") &&
-        !libPath.substring(instrumentationPath.length).contains("testing")) {
-        return@filter false
-      }
-      return@filter true
-    }
-  }
 }
 
 configurations.configureEach {
@@ -103,3 +22,9 @@ configurations.configureEach {
     exclude(module = "javaagent-bootstrap")
   }
 }
+
+tasks {
+  withType<Test>().configureEach {
+    dependsOn(":testing:agent-for-testing:shadowJar")
+  }
+}

+ 3 - 9
buildSrc/src/main/kotlin/otel.library-instrumentation.gradle.kts

@@ -1,17 +1,11 @@
 plugins {
-  id("otel.instrumentation-conventions")
+  id("io.opentelemetry.instrumentation.library-instrumentation")
+
   id("otel.jacoco-conventions")
+  id("otel.java-conventions")
   id("otel.publish-conventions")
 }
 
 extra["mavenGroupId"] = "io.opentelemetry.instrumentation"
 
 base.archivesName.set(projectDir.parentFile.name)
-
-dependencies {
-  api(project(":instrumentation-api"))
-
-  api("io.opentelemetry:opentelemetry-api")
-
-  testImplementation(project(":testing-common"))
-}

+ 7 - 12
instrumentation/apache-camel-2.20/javaagent/build.gradle.kts

@@ -17,6 +17,13 @@ dependencies {
   library("org.apache.camel:camel-core:$camelversion")
   implementation("io.opentelemetry:opentelemetry-extension-aws")
 
+  // without adding this dependency, javadoc fails:
+  //   warning: unknown enum constant XmlAccessType.PROPERTY
+  //   reason: class file for javax.xml.bind.annotation.XmlAccessType not found
+  // due to usage of org.apache.camel.model.RouteDefinition in CamelTracingService
+  // which has jaxb class-level annotations
+  compileOnly("javax.xml.bind:jaxb-api:2.3.1")
+
   testInstrumentation(project(":instrumentation:apache-httpclient:apache-httpclient-2.0:javaagent"))
   testInstrumentation(project(":instrumentation:servlet:servlet-3.0:javaagent"))
   testInstrumentation(project(":instrumentation:aws-sdk:aws-sdk-1.11:javaagent"))
@@ -47,21 +54,9 @@ dependencies {
 }
 
 tasks {
-
   withType<Test>().configureEach {
     // TODO run tests both with and without experimental span attributes
     jvmArgs("-Dotel.instrumentation.apache-camel.experimental-span-attributes=true")
     jvmArgs("-Dotel.instrumentation.aws-sdk.experimental-span-attributes=true")
   }
-
-  named<Javadoc>("javadoc") {
-    dependencies {
-      // without adding this dependency, javadoc fails:
-      //   warning: unknown enum constant XmlAccessType.PROPERTY
-      //   reason: class file for javax.xml.bind.annotation.XmlAccessType not found
-      // due to usage of org.apache.camel.model.RouteDefinition in CamelTracingService
-      // which has jaxb class-level annotations
-      compileOnly("javax.xml.bind:jaxb-api:2.3.1")
-    }
-  }
 }

+ 2 - 2
instrumentation/build.gradle.kts

@@ -2,7 +2,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
 
 // this project will run in isolation under the agent's classloader
 plugins {
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
   id("otel.java-conventions")
 }
 
@@ -58,7 +58,7 @@ tasks {
     description = "List all available instrumentation modules"
     doFirst {
       subprojects
-        .filter { it.plugins.hasPlugin("otel.muzzle-check") }
+        .filter { it.plugins.hasPlugin("io.opentelemetry.instrumentation.muzzle-check") }
         .map { it.path }
         .forEach { println(it) }
     }

+ 0 - 6
javaagent-bootstrap/build.gradle.kts

@@ -17,12 +17,6 @@ tasks {
   }
 }
 
-val instrumentationMuzzle by configurations.creating {
-  isCanBeConsumed = true
-  isCanBeResolved = false
-  extendsFrom(configurations.implementation.get())
-}
-
 dependencies {
   api("io.opentelemetry:opentelemetry-api")
   api("io.opentelemetry:opentelemetry-api-metrics")

+ 1 - 1
javaagent-exporters/build.gradle.kts

@@ -2,7 +2,7 @@
 
 plugins {
   id("otel.java-conventions")
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
 }
 
 dependencies {

+ 0 - 10
javaagent-extension-api/build.gradle.kts

@@ -5,14 +5,6 @@ plugins {
 
 group = "io.opentelemetry.javaagent"
 
-val instrumentationMuzzle by configurations.creating {
-  isCanBeConsumed = true
-  isCanBeResolved = false
-  // TODO(anuraaga): Should be compileClasspath?
-  extendsFrom(configurations.api.get())
-  extendsFrom(configurations.implementation.get())
-}
-
 dependencies {
   api("io.opentelemetry:opentelemetry-sdk")
 
@@ -24,6 +16,4 @@ dependencies {
 
   // metrics are unstable, do not expose as api
   implementation("io.opentelemetry:opentelemetry-sdk-metrics")
-
-  instrumentationMuzzle(sourceSets.main.get().output)
 }

+ 0 - 8
javaagent-tooling/build.gradle.kts

@@ -5,12 +5,6 @@ plugins {
 
 group = "io.opentelemetry.javaagent"
 
-val instrumentationMuzzle by configurations.creating {
-  isCanBeConsumed = true
-  isCanBeResolved = false
-  extendsFrom(configurations.implementation.get())
-}
-
 dependencies {
   // Only used during compilation by bytebuddy plugin
   compileOnly("com.google.guava:guava")
@@ -45,8 +39,6 @@ dependencies {
   testImplementation("org.assertj:assertj-core")
   testImplementation("org.mockito:mockito-core")
   testImplementation("org.mockito:mockito-junit-jupiter")
-
-  instrumentationMuzzle(sourceSets.main.get().output)
 }
 
 // Here we only include autoconfigure but don"t include OTLP exporters to ensure they are only in

+ 1 - 1
javaagent/build.gradle.kts

@@ -7,7 +7,7 @@ plugins {
 
   id("otel.java-conventions")
   id("otel.publish-conventions")
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
 }
 
 description = "OpenTelemetry Javaagent"

+ 1 - 1
testing/agent-exporter/build.gradle.kts

@@ -1,5 +1,5 @@
 plugins {
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
 
   id("otel.java-conventions")
 }

+ 1 - 1
testing/agent-for-testing/build.gradle.kts

@@ -1,7 +1,7 @@
 import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
 
 plugins {
-  id("otel.shadow-conventions")
+  id("io.opentelemetry.instrumentation.javaagent-shadowing")
 
   id("otel.java-conventions")
   id("otel.publish-conventions")