blob: 89b46a3e6df326851b7ee015d08a3774a332c8d0 [file] [log] [blame]
plugins {
id 'com.github.johnrengelman.shadow' version '2.0.1'
id 'me.tatarka.retrolambda' version '3.6.0'
id 'me.champeau.gradle.jmh' version '0.4.4'
id 'io.morethan.jmhreport' version '0.5.0'
}
description = 'OpenCensus Agent'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
// Experimental support for legacy Java 1.6 JVMs. Animalsniffer (applied by the root project) is
// used to check for unexpected references to later APIs. Also see dependencies/signature.
// Retrolambda itself requires JDK 8, which it finds at $JAVA8_HOME.
retrolambda {
javaVersion JavaVersion.VERSION_1_6
}
def agentPackage = 'io.opencensus.contrib.agent'
def agentMainClass = "${agentPackage}.AgentMain"
// The package containing the classes that need to be loaded by the bootstrap classloader because
// they are used from classes loaded by the bootstrap classloader.
def agentBootstrapPackage = "${agentPackage}.bootstrap"
def agentBootstrapPackageDir = agentBootstrapPackage.replace('.', '/') + '/'
def agentBootstrapClasses = agentBootstrapPackageDir + '**'
// The package to which we relocate all third party packages. This avoids any conflicts of the
// agent's classes with the app's classes, which are loaded by the same classloader (the system
// classloader).
def agentRepackaged = "${agentPackage}.deps"
dependencies {
compileOnly libraries.auto_service
compileOnly libraries.grpc_context
compile libraries.findbugs_annotations
compile libraries.guava
compile libraries.byte_buddy
signature 'org.codehaus.mojo.signature:java16:+@signature'
}
jar {
manifest {
// Set the required manifest attributes for the Java agent, cf.
// https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html.
attributes 'Premain-Class': agentMainClass
attributes 'Can-Retransform-Classes': true
// Let the java plugin use the overridden values instead of the root project's values.
attributes 'Source-Compatibility': JavaVersion.VERSION_1_6
attributes 'Target-Compatibility': JavaVersion.VERSION_1_6
}
}
// Create bootstrap.jar containing the classes that need to be loaded by the bootstrap
// classloader.
task bootstrapJar(type: Jar) {
// Output to 'bootstrap.jar'.
baseName = 'bootstrap'
version = null
from sourceSets.main.output
include agentBootstrapClasses
}
shadowJar.dependsOn bootstrapJar
// Bundle the agent's classes and dependencies into a single, self-contained JAR file.
shadowJar {
// Output to opencensus-contrib-agent-VERSION.jar.
classifier = null
// Include only the following dependencies (excluding transitive dependencies).
dependencies {
include(dependency(libraries.byte_buddy))
include(dependency(libraries.guava))
}
// Exclude cruft which still snuck in.
exclude 'META-INF/maven/**'
exclude agentBootstrapClasses
// Relocate third party packages to avoid any conflicts of the agent's classes with the app's
// classes, which are loaded by the same classloader (the system classloader).
// Byte Buddy:
relocate 'net.bytebuddy', agentRepackaged + '.bytebuddy'
// Guava:
relocate 'com.google.common', agentRepackaged + '.guava'
relocate 'com.google.thirdparty.publicsuffix', agentRepackaged + '.publicsuffix'
doLast {
def agentPackageDir = agentPackage.replace('.', '/') + '/'
def agentBootstrapJar = agentPackageDir + 'bootstrap.jar'
// Bundle bootstrap.jar.
ant.jar(update: 'true', destfile: shadowJar.archivePath) {
mappedresources {
fileset(file: bootstrapJar.archivePath)
globmapper(from: '*', to: agentBootstrapJar)
}
}
// Assert that there's nothing obviously wrong with the JAR's contents.
new java.util.zip.ZipFile(shadowJar.archivePath).withCloseable {
// Must have bundled the bootstrap.jar.
assert it.entries().any { it.name == agentBootstrapJar }
it.entries().each { entry ->
// Must not contain anything outside of ${agentPackage}, ...
assert entry.name.startsWith(agentPackageDir) ||
// ... except for the expected entries.
[ agentPackageDir,
'META-INF/MANIFEST.MF',
'META-INF/services/io.opencensus.contrib.agent.instrumentation.Instrumenter'
].any { entry.isDirectory() ? it.startsWith(entry.name) : it == entry.name }
// Also, should not have the bootstrap classes.
assert !entry.name.startsWith(agentBootstrapPackageDir)
}
}
}
}
jar.finalizedBy shadowJar
// TODO(stschmidt): Proguard-shrink the agent JAR.
// Integration tests. The setup is mostly based on
// https://www.petrikainulainen.net/programming/gradle/getting-started-with-gradle-integration-testing/.
sourceSets {
integrationTest {
java {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
dependencies {
integrationTestCompile libraries.grpc_context
}
// Disable checkstyle for integration tests if not java8.
checkstyleIntegrationTest.enabled = JavaVersion.current().isJava8Compatible()
// Disable findbugs for integration tests, too.
findbugsIntegrationTest.enabled = false
// Run integration tests with the agent enabled.
task integrationTest(type: Test) {
testLogging {
// Let Gradle output the stdout and stderr from tests, too. This is useful for investigating
// test failures on Travis, where we can't view Gradle's test reports.
showStandardStreams = true
// Include the exception message and full stacktrace for failed tests.
exceptionFormat 'full'
}
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
jvmArgs "-javaagent:${shadowJar.archivePath}"
}
check.dependsOn integrationTest
integrationTest.dependsOn shadowJar
integrationTest.mustRunAfter test
// JMH benchmarks
dependencies {
jmh libraries.grpc_context
}
// Disable checkstyle for JMH benchmarks if not java8.
checkstyleJmh.enabled = JavaVersion.current().isJava8Compatible()
// Generate html report for findbugsJmh.
findbugsJmh {
reports {
xml.enabled = false
html.enabled = true
}
}
// Make the agent JAR available using a fixed file name so that we don't have to modify the JMH
// benchmarks whenever the version changes.
task agentJar(type: Copy) {
dependsOn shadowJar
from shadowJar.archivePath
into libsDir
rename { 'agent.jar' }
}
jmhJar.dependsOn agentJar
jmhJar.dependsOn integrationTest
jmh {
jmhVersion = '1.19'
warmupIterations = 10
iterations = 10
fork = 1
failOnError = true
resultFormat = 'JSON'
}
jmhReport {
jmhResultPath = project.file("${project.buildDir}/reports/jmh/results.json")
jmhReportOutput = project.file("${project.buildDir}/reports/jmh")
}
tasks.jmh.finalizedBy tasks.jmhReport