xref: /aosp_15_r20/external/opencensus-java/contrib/agent/build.gradle (revision a24ffb47c3166327784aa05b149974e82e8f71b8)
1*a24ffb47SSadaf Ebrahimiplugins {
2*a24ffb47SSadaf Ebrahimi  id 'com.github.johnrengelman.shadow' version '2.0.2'
3*a24ffb47SSadaf Ebrahimi}
4*a24ffb47SSadaf Ebrahimi
5*a24ffb47SSadaf Ebrahimidescription = 'OpenCensus Agent'
6*a24ffb47SSadaf Ebrahimi
7*a24ffb47SSadaf Ebrahimidef agentPackage = 'io.opencensus.contrib.agent'
8*a24ffb47SSadaf Ebrahimidef agentMainClass = "${agentPackage}.AgentMain"
9*a24ffb47SSadaf Ebrahimi
10*a24ffb47SSadaf Ebrahimi// The package containing the classes that need to be loaded by the bootstrap classloader because
11*a24ffb47SSadaf Ebrahimi// they are used from classes loaded by the bootstrap classloader.
12*a24ffb47SSadaf Ebrahimidef agentBootstrapPackage = "${agentPackage}.bootstrap"
13*a24ffb47SSadaf Ebrahimidef agentBootstrapPackageDir = agentBootstrapPackage.replace('.', '/') + '/'
14*a24ffb47SSadaf Ebrahimidef agentBootstrapClasses = agentBootstrapPackageDir + '**'
15*a24ffb47SSadaf Ebrahimi
16*a24ffb47SSadaf Ebrahimi// The package to which we relocate all third party packages. This avoids any conflicts of the
17*a24ffb47SSadaf Ebrahimi// agent's classes with the app's classes, which are loaded by the same classloader (the system
18*a24ffb47SSadaf Ebrahimi// classloader).
19*a24ffb47SSadaf Ebrahimidef agentRepackaged = "${agentPackage}.deps"
20*a24ffb47SSadaf Ebrahimi
21*a24ffb47SSadaf Ebrahimidependencies {
22*a24ffb47SSadaf Ebrahimi  compileOnly libraries.auto_service
23*a24ffb47SSadaf Ebrahimi  compileOnly libraries.findbugs_annotations
24*a24ffb47SSadaf Ebrahimi  compileOnly libraries.grpc_context
25*a24ffb47SSadaf Ebrahimi  compileOnly project(':opencensus-api')
26*a24ffb47SSadaf Ebrahimi  compile libraries.byte_buddy
27*a24ffb47SSadaf Ebrahimi  compile libraries.config
28*a24ffb47SSadaf Ebrahimi  compile libraries.guava
29*a24ffb47SSadaf Ebrahimi
30*a24ffb47SSadaf Ebrahimi  signature 'org.codehaus.mojo.signature:java17:1.0@signature'
31*a24ffb47SSadaf Ebrahimi}
32*a24ffb47SSadaf Ebrahimi
33*a24ffb47SSadaf Ebrahimijar {
34*a24ffb47SSadaf Ebrahimi  manifest {
35*a24ffb47SSadaf Ebrahimi    // Set the required manifest attributes for the Java agent, cf.
36*a24ffb47SSadaf Ebrahimi    // https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/package-summary.html.
37*a24ffb47SSadaf Ebrahimi    attributes 'Premain-Class': agentMainClass
38*a24ffb47SSadaf Ebrahimi    attributes 'Can-Retransform-Classes': true
39*a24ffb47SSadaf Ebrahimi  }
40*a24ffb47SSadaf Ebrahimi}
41*a24ffb47SSadaf Ebrahimi
42*a24ffb47SSadaf Ebrahimi// Create bootstrap.jar containing the classes that need to be loaded by the bootstrap
43*a24ffb47SSadaf Ebrahimi// classloader.
44*a24ffb47SSadaf Ebrahimitask bootstrapJar(type: Jar) {
45*a24ffb47SSadaf Ebrahimi  // Output to 'bootstrap.jar'.
46*a24ffb47SSadaf Ebrahimi  baseName = 'bootstrap'
47*a24ffb47SSadaf Ebrahimi  version = null
48*a24ffb47SSadaf Ebrahimi
49*a24ffb47SSadaf Ebrahimi  from sourceSets.main.output
50*a24ffb47SSadaf Ebrahimi  include agentBootstrapClasses
51*a24ffb47SSadaf Ebrahimi}
52*a24ffb47SSadaf Ebrahimi
53*a24ffb47SSadaf EbrahimishadowJar.dependsOn bootstrapJar
54*a24ffb47SSadaf Ebrahimi
55*a24ffb47SSadaf Ebrahimi// Bundle the agent's classes and dependencies into a single, self-contained JAR file.
56*a24ffb47SSadaf EbrahimishadowJar {
57*a24ffb47SSadaf Ebrahimi  // Output to opencensus-contrib-agent-VERSION.jar.
58*a24ffb47SSadaf Ebrahimi  classifier = null
59*a24ffb47SSadaf Ebrahimi
60*a24ffb47SSadaf Ebrahimi  // Include only the following dependencies (excluding transitive dependencies).
61*a24ffb47SSadaf Ebrahimi  dependencies {
62*a24ffb47SSadaf Ebrahimi    include(dependency(libraries.byte_buddy))
63*a24ffb47SSadaf Ebrahimi    include(dependency(libraries.config))
64*a24ffb47SSadaf Ebrahimi    include(dependency(libraries.guava))
65*a24ffb47SSadaf Ebrahimi  }
66*a24ffb47SSadaf Ebrahimi
67*a24ffb47SSadaf Ebrahimi  // Exclude cruft which still snuck in.
68*a24ffb47SSadaf Ebrahimi  exclude 'META-INF/maven/**'
69*a24ffb47SSadaf Ebrahimi  exclude agentBootstrapClasses
70*a24ffb47SSadaf Ebrahimi
71*a24ffb47SSadaf Ebrahimi  // Relocate third party packages to avoid any conflicts of the agent's classes with the app's
72*a24ffb47SSadaf Ebrahimi  // classes, which are loaded by the same classloader (the system classloader).
73*a24ffb47SSadaf Ebrahimi  // Byte Buddy:
74*a24ffb47SSadaf Ebrahimi  relocate 'net.bytebuddy', agentRepackaged + '.bytebuddy'
75*a24ffb47SSadaf Ebrahimi  // Config:
76*a24ffb47SSadaf Ebrahimi  relocate 'com.typesafe.config', agentRepackaged + '.config'
77*a24ffb47SSadaf Ebrahimi  // Guava:
78*a24ffb47SSadaf Ebrahimi  relocate 'com.google.common', agentRepackaged + '.guava'
79*a24ffb47SSadaf Ebrahimi  relocate 'com.google.thirdparty.publicsuffix', agentRepackaged + '.publicsuffix'
80*a24ffb47SSadaf Ebrahimi
81*a24ffb47SSadaf Ebrahimi  doLast {
82*a24ffb47SSadaf Ebrahimi    def agentPackageDir = agentPackage.replace('.', '/') + '/'
83*a24ffb47SSadaf Ebrahimi    def agentBootstrapJar = agentPackageDir + 'bootstrap.jar'
84*a24ffb47SSadaf Ebrahimi
85*a24ffb47SSadaf Ebrahimi    // Bundle bootstrap.jar.
86*a24ffb47SSadaf Ebrahimi    ant.jar(update: 'true', destfile: shadowJar.archivePath) {
87*a24ffb47SSadaf Ebrahimi      mappedresources {
88*a24ffb47SSadaf Ebrahimi        fileset(file: bootstrapJar.archivePath)
89*a24ffb47SSadaf Ebrahimi        globmapper(from: '*', to: agentBootstrapJar)
90*a24ffb47SSadaf Ebrahimi      }
91*a24ffb47SSadaf Ebrahimi    }
92*a24ffb47SSadaf Ebrahimi
93*a24ffb47SSadaf Ebrahimi    // Assert that there's nothing obviously wrong with the JAR's contents.
94*a24ffb47SSadaf Ebrahimi    new java.util.zip.ZipFile(shadowJar.archivePath).withCloseable {
95*a24ffb47SSadaf Ebrahimi      // Must have bundled the bootstrap.jar.
96*a24ffb47SSadaf Ebrahimi      assert it.entries().any { it.name == agentBootstrapJar }
97*a24ffb47SSadaf Ebrahimi
98*a24ffb47SSadaf Ebrahimi      it.entries().each { entry ->
99*a24ffb47SSadaf Ebrahimi        // Must not contain anything outside of ${agentPackage}, ...
100*a24ffb47SSadaf Ebrahimi        assert entry.name.startsWith(agentPackageDir) ||
101*a24ffb47SSadaf Ebrahimi               // ... except for the expected entries.
102*a24ffb47SSadaf Ebrahimi               [ agentPackageDir,
103*a24ffb47SSadaf Ebrahimi                 'META-INF/MANIFEST.MF',
104*a24ffb47SSadaf Ebrahimi                 'META-INF/services/io.opencensus.contrib.agent.instrumentation.Instrumenter',
105*a24ffb47SSadaf Ebrahimi                 'reference.conf',
106*a24ffb47SSadaf Ebrahimi               ].any { entry.isDirectory() ? it.startsWith(entry.name) : it == entry.name }
107*a24ffb47SSadaf Ebrahimi        // Also, should not have the bootstrap classes.
108*a24ffb47SSadaf Ebrahimi        assert !entry.name.startsWith(agentBootstrapPackageDir)
109*a24ffb47SSadaf Ebrahimi      }
110*a24ffb47SSadaf Ebrahimi    }
111*a24ffb47SSadaf Ebrahimi  }
112*a24ffb47SSadaf Ebrahimi}
113*a24ffb47SSadaf Ebrahimi
114*a24ffb47SSadaf Ebrahimijar.finalizedBy shadowJar
115*a24ffb47SSadaf Ebrahimi
116*a24ffb47SSadaf Ebrahimi// TODO(stschmidt): Proguard-shrink the agent JAR.
117*a24ffb47SSadaf Ebrahimi
118*a24ffb47SSadaf Ebrahimi// Integration tests. The setup was initially based on
119*a24ffb47SSadaf Ebrahimi// https://www.petrikainulainen.net/programming/gradle/getting-started-with-gradle-integration-testing/.
120*a24ffb47SSadaf Ebrahimi// We run the same suite of integration tests on different Java versions with the agent enabled.
121*a24ffb47SSadaf Ebrahimi// The JAVA_HOMES environment variable lists the home directories of the Java installations used
122*a24ffb47SSadaf Ebrahimi// for integration testing.
123*a24ffb47SSadaf Ebrahimi
124*a24ffb47SSadaf Ebrahimi// The default JAR has been replaced with a self-contained JAR by the shadowJar task. Therefore,
125*a24ffb47SSadaf Ebrahimi// remove all declared dependencies from the generated Maven POM for said JAR.
126*a24ffb47SSadaf EbrahimiuploadArchives {
127*a24ffb47SSadaf Ebrahimi  repositories {
128*a24ffb47SSadaf Ebrahimi    mavenDeployer {
129*a24ffb47SSadaf Ebrahimi      pom.whenConfigured {
130*a24ffb47SSadaf Ebrahimi        dependencies = []
131*a24ffb47SSadaf Ebrahimi      }
132*a24ffb47SSadaf Ebrahimi    }
133*a24ffb47SSadaf Ebrahimi  }
134*a24ffb47SSadaf Ebrahimi}
135*a24ffb47SSadaf Ebrahimi
136*a24ffb47SSadaf EbrahimisourceSets {
137*a24ffb47SSadaf Ebrahimi  integrationTest {
138*a24ffb47SSadaf Ebrahimi    java {
139*a24ffb47SSadaf Ebrahimi      compileClasspath += main.output + test.output
140*a24ffb47SSadaf Ebrahimi      runtimeClasspath += main.output + test.output
141*a24ffb47SSadaf Ebrahimi      srcDir file('src/integration-test/java')
142*a24ffb47SSadaf Ebrahimi    }
143*a24ffb47SSadaf Ebrahimi    resources.srcDir file('src/integration-test/resources')
144*a24ffb47SSadaf Ebrahimi  }
145*a24ffb47SSadaf Ebrahimi}
146*a24ffb47SSadaf Ebrahimi
147*a24ffb47SSadaf Ebrahimiconfigurations {
148*a24ffb47SSadaf Ebrahimi  integrationTestCompile.extendsFrom testCompile
149*a24ffb47SSadaf Ebrahimi  integrationTestRuntime.extendsFrom testRuntime
150*a24ffb47SSadaf Ebrahimi}
151*a24ffb47SSadaf Ebrahimi
152*a24ffb47SSadaf Ebrahimidependencies {
153*a24ffb47SSadaf Ebrahimi  integrationTestCompile project(':opencensus-api')
154*a24ffb47SSadaf Ebrahimi  integrationTestCompile project(':opencensus-testing')
155*a24ffb47SSadaf Ebrahimi  integrationTestRuntime libraries.grpc_context
156*a24ffb47SSadaf Ebrahimi  integrationTestRuntime project(':opencensus-impl-lite')
157*a24ffb47SSadaf Ebrahimi}
158*a24ffb47SSadaf Ebrahimi
159*a24ffb47SSadaf Ebrahimi// Disable findbugs for integration tests, too.
160*a24ffb47SSadaf EbrahimifindbugsIntegrationTest.enabled = false
161*a24ffb47SSadaf Ebrahimi
162*a24ffb47SSadaf Ebrahimidef javaExecutables = (System.getenv('JAVA_HOMES') ?: '')
163*a24ffb47SSadaf Ebrahimi    .tokenize(File.pathSeparator)
164*a24ffb47SSadaf Ebrahimi    .plus(System.getProperty('java.home'))
165*a24ffb47SSadaf Ebrahimi    .collect { org.apache.tools.ant.taskdefs.condition.Os.isFamily(
166*a24ffb47SSadaf Ebrahimi                   org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)
167*a24ffb47SSadaf Ebrahimi                   ? "${it}/bin/java.exe"
168*a24ffb47SSadaf Ebrahimi                   : "${it}/bin/java" }
169*a24ffb47SSadaf Ebrahimi    .collect { new File(it).getCanonicalPath() }
170*a24ffb47SSadaf Ebrahimi    .unique()
171*a24ffb47SSadaf Ebrahimi
172*a24ffb47SSadaf Ebrahimiassert javaExecutables.size > 0 :
173*a24ffb47SSadaf Ebrahimi       'No Java executables found for running integration tests'
174*a24ffb47SSadaf Ebrahimi
175*a24ffb47SSadaf Ebrahimitask integrationTest
176*a24ffb47SSadaf Ebrahimi
177*a24ffb47SSadaf EbrahimijavaExecutables.eachWithIndex { javaExecutable, index ->
178*a24ffb47SSadaf Ebrahimi  def perVersionIntegrationTest = task("integrationTest_${index}", type: Test) {
179*a24ffb47SSadaf Ebrahimi    testLogging {
180*a24ffb47SSadaf Ebrahimi      // Let Gradle output the stdout and stderr from tests, too. This is useful for investigating
181*a24ffb47SSadaf Ebrahimi      // test failures on Travis, where we can't view Gradle's test reports.
182*a24ffb47SSadaf Ebrahimi      showStandardStreams = true
183*a24ffb47SSadaf Ebrahimi
184*a24ffb47SSadaf Ebrahimi      // Include the exception message and full stacktrace for failed tests.
185*a24ffb47SSadaf Ebrahimi      exceptionFormat 'full'
186*a24ffb47SSadaf Ebrahimi    }
187*a24ffb47SSadaf Ebrahimi
188*a24ffb47SSadaf Ebrahimi    dependsOn shadowJar
189*a24ffb47SSadaf Ebrahimi
190*a24ffb47SSadaf Ebrahimi    testClassesDirs = sourceSets.integrationTest.output.classesDirs
191*a24ffb47SSadaf Ebrahimi    classpath = sourceSets.integrationTest.runtimeClasspath
192*a24ffb47SSadaf Ebrahimi
193*a24ffb47SSadaf Ebrahimi    executable = javaExecutable
194*a24ffb47SSadaf Ebrahimi
195*a24ffb47SSadaf Ebrahimi    // The JaCoCo agent must be specified first so that it can instrument our agent.
196*a24ffb47SSadaf Ebrahimi    // This is a work around for the issue that the JaCoCo agent is added last, cf.
197*a24ffb47SSadaf Ebrahimi    // https://discuss.gradle.org/t/jacoco-gradle-adds-the-agent-last-to-jvm-args/7124.
198*a24ffb47SSadaf Ebrahimi    doFirst {
199*a24ffb47SSadaf Ebrahimi      jvmArgs jacoco.asJvmArg  // JaCoCo agent first.
200*a24ffb47SSadaf Ebrahimi      jvmArgs "-javaagent:${shadowJar.archivePath}"  // Our agent second.
201*a24ffb47SSadaf Ebrahimi      jacoco.enabled = false  // Don't add the JaCoCo agent again.
202*a24ffb47SSadaf Ebrahimi    }
203*a24ffb47SSadaf Ebrahimi
204*a24ffb47SSadaf Ebrahimi    doFirst { logger.lifecycle("Running integration tests using ${javaExecutable}.") }
205*a24ffb47SSadaf Ebrahimi  }
206*a24ffb47SSadaf Ebrahimi
207*a24ffb47SSadaf Ebrahimi  integrationTest.dependsOn perVersionIntegrationTest
208*a24ffb47SSadaf Ebrahimi}
209*a24ffb47SSadaf Ebrahimi
210*a24ffb47SSadaf Ebrahimicheck.dependsOn integrationTest
211*a24ffb47SSadaf EbrahimiintegrationTest.mustRunAfter test
212*a24ffb47SSadaf Ebrahimi
213*a24ffb47SSadaf Ebrahimi// Merge JaCoCo's execution data from all tests into the main test's execution data file.
214*a24ffb47SSadaf Ebrahimitask jacocoMerge(type: JacocoMerge) {
215*a24ffb47SSadaf Ebrahimi  tasks.withType(Test).each { testTask ->
216*a24ffb47SSadaf Ebrahimi    dependsOn testTask
217*a24ffb47SSadaf Ebrahimi    executionData testTask.jacoco.destinationFile
218*a24ffb47SSadaf Ebrahimi  }
219*a24ffb47SSadaf Ebrahimi  doLast {
220*a24ffb47SSadaf Ebrahimi    destinationFile.renameTo test.jacoco.destinationFile
221*a24ffb47SSadaf Ebrahimi  }
222*a24ffb47SSadaf Ebrahimi}
223*a24ffb47SSadaf Ebrahimi
224*a24ffb47SSadaf EbrahimijacocoTestReport.dependsOn jacocoMerge
225*a24ffb47SSadaf Ebrahimi
226*a24ffb47SSadaf Ebrahimi// JMH benchmarks
227*a24ffb47SSadaf Ebrahimi
228*a24ffb47SSadaf Ebrahimidependencies {
229*a24ffb47SSadaf Ebrahimi  jmh libraries.grpc_context
230*a24ffb47SSadaf Ebrahimi}
231*a24ffb47SSadaf Ebrahimi
232*a24ffb47SSadaf Ebrahimi// Make the agent JAR available using a fixed file name so that we don't have to modify the JMH
233*a24ffb47SSadaf Ebrahimi// benchmarks whenever the version changes.
234*a24ffb47SSadaf Ebrahimitask agentJar(type: Copy) {
235*a24ffb47SSadaf Ebrahimi  dependsOn shadowJar
236*a24ffb47SSadaf Ebrahimi
237*a24ffb47SSadaf Ebrahimi  from shadowJar.archivePath
238*a24ffb47SSadaf Ebrahimi  into libsDir
239*a24ffb47SSadaf Ebrahimi  rename { 'agent.jar' }
240*a24ffb47SSadaf Ebrahimi}
241*a24ffb47SSadaf Ebrahimi
242*a24ffb47SSadaf EbrahimijmhJar.dependsOn agentJar
243*a24ffb47SSadaf EbrahimijmhJar.dependsOn integrationTest
244