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
This commit is contained in:
Anuraag Agrawal 2021-07-05 16:18:45 +09:00 committed by GitHub
parent ac54f9d446
commit 8eb24f9886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 211 additions and 168 deletions

View File

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

View File

@ -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}"
}
}

View File

@ -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")
}

View File

@ -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")
}
}

View File

@ -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")
}

View File

@ -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")
}
}

View File

@ -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"))
}

View File

@ -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")
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")
id("otel.java-conventions")
}
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()
dependencies {
annotationProcessor("com.google.auto.service:auto-service")
compileOnly("com.google.auto.service:auto-service")
compileOnly("org.slf4j:slf4j-api")
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
}
}
testImplementation("org.testcontainers:testcontainers")
}
configurations.configureEach {
@ -103,3 +22,9 @@ configurations.configureEach {
exclude(module = "javaagent-bootstrap")
}
}
tasks {
withType<Test>().configureEach {
dependsOn(":testing:agent-for-testing:shadowJar")
}
}

View File

@ -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"))
}

View File

@ -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")
}
}
}

View File

@ -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) }
}

View File

@ -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")

View File

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

View File

@ -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)
}

View File

@ -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

View File

@ -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"

View File

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

View File

@ -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")