build.gradle.kts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
  2. import com.github.jk1.license.filter.LicenseBundleNormalizer
  3. import com.github.jk1.license.render.InventoryMarkdownReportRenderer
  4. plugins {
  5. id("com.github.jk1.dependency-license-report")
  6. id("otel.java-conventions")
  7. id("otel.publish-conventions")
  8. id("io.opentelemetry.instrumentation.javaagent-shadowing")
  9. }
  10. description = "OpenTelemetry Javaagent"
  11. group = "io.opentelemetry.javaagent"
  12. // this configuration collects libs that will be placed in the bootstrap classloader
  13. val bootstrapLibs by configurations.creating {
  14. isCanBeResolved = true
  15. isCanBeConsumed = false
  16. }
  17. // this configuration collects only required instrumentations and agent machinery
  18. val baseJavaagentLibs by configurations.creating {
  19. isCanBeResolved = true
  20. isCanBeConsumed = false
  21. }
  22. // this configuration collects libs that will be placed in the agent classloader, isolated from the instrumented application code
  23. val javaagentLibs by configurations.creating {
  24. isCanBeResolved = true
  25. isCanBeConsumed = false
  26. extendsFrom(baseJavaagentLibs)
  27. }
  28. // this configuration collects just exporter libs (also placed in the agent classloader & isolated from the instrumented application)
  29. val exporterLibs by configurations.creating {
  30. isCanBeResolved = true
  31. isCanBeConsumed = false
  32. }
  33. // this configuration collects just exporter libs for slim artifact (also placed in the agent classloader & isolated from the instrumented application)
  34. val exporterSlimLibs by configurations.creating {
  35. isCanBeResolved = true
  36. isCanBeConsumed = false
  37. }
  38. // exclude dependencies that are to be placed in bootstrap from agent libs - they won't be added to inst/
  39. listOf(baseJavaagentLibs, javaagentLibs, exporterLibs, exporterSlimLibs).forEach {
  40. it.run {
  41. exclude("org.slf4j")
  42. exclude("io.opentelemetry", "opentelemetry-api")
  43. exclude("io.opentelemetry", "opentelemetry-semconv")
  44. }
  45. }
  46. val licenseReportDependencies by configurations.creating {
  47. extendsFrom(bootstrapLibs)
  48. }
  49. dependencies {
  50. bootstrapLibs(project(":instrumentation-api"))
  51. bootstrapLibs(project(":instrumentation-api-annotation-support"))
  52. bootstrapLibs(project(":instrumentation-api-appender"))
  53. bootstrapLibs(project(":javaagent-bootstrap"))
  54. bootstrapLibs(project(":javaagent-instrumentation-api"))
  55. bootstrapLibs("org.slf4j:slf4j-simple")
  56. baseJavaagentLibs(project(":javaagent-extension-api"))
  57. baseJavaagentLibs(project(":javaagent-tooling"))
  58. baseJavaagentLibs(project(":muzzle"))
  59. baseJavaagentLibs(project(":instrumentation:opentelemetry-annotations-1.0:javaagent"))
  60. baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent"))
  61. baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent"))
  62. baseJavaagentLibs(project(":instrumentation:executors:javaagent"))
  63. baseJavaagentLibs(project(":instrumentation:internal:internal-class-loader:javaagent"))
  64. baseJavaagentLibs(project(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent"))
  65. baseJavaagentLibs(project(":instrumentation:internal:internal-lambda:javaagent"))
  66. baseJavaagentLibs(project(":instrumentation:internal:internal-reflection:javaagent"))
  67. baseJavaagentLibs(project(":instrumentation:internal:internal-url-class-loader:javaagent"))
  68. exporterLibs(project(":javaagent-exporters"))
  69. exporterSlimLibs("io.opentelemetry:opentelemetry-exporter-otlp")
  70. exporterSlimLibs("io.opentelemetry:opentelemetry-exporter-otlp-metrics")
  71. // concurrentlinkedhashmap-lru and weak-lock-free are copied in to the instrumentation-api module
  72. licenseReportDependencies("com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2")
  73. licenseReportDependencies("com.blogspot.mydailyjava:weak-lock-free:0.18")
  74. // TODO ideally this would be :instrumentation instead of :javaagent-tooling
  75. // in case there are dependencies (accidentally) pulled in by instrumentation modules
  76. // but I couldn't get that to work
  77. licenseReportDependencies(project(":javaagent-tooling"))
  78. licenseReportDependencies(project(":javaagent-extension-api"))
  79. testCompileOnly(project(":javaagent-bootstrap"))
  80. testCompileOnly(project(":javaagent-instrumentation-api"))
  81. testImplementation("com.google.guava:guava")
  82. testImplementation("io.opentelemetry:opentelemetry-sdk")
  83. testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
  84. testImplementation("org.assertj:assertj-core")
  85. }
  86. val javaagentDependencies = dependencies
  87. // collect all bootstrap and javaagent instrumentation dependencies
  88. project(":instrumentation").subprojects {
  89. val subProj = this
  90. plugins.withId("otel.javaagent-bootstrap") {
  91. javaagentDependencies.run {
  92. add(bootstrapLibs.name, project(subProj.path))
  93. }
  94. }
  95. plugins.withId("otel.javaagent-instrumentation") {
  96. javaagentDependencies.run {
  97. add(javaagentLibs.name, project(subProj.path))
  98. }
  99. }
  100. }
  101. tasks {
  102. processResources {
  103. from(rootProject.file("licenses")) {
  104. into("META-INF/licenses")
  105. }
  106. }
  107. val relocateBaseJavaagentLibs by registering(ShadowJar::class) {
  108. configurations = listOf(baseJavaagentLibs)
  109. duplicatesStrategy = DuplicatesStrategy.FAIL
  110. archiveFileName.set("baseJavaagentLibs-relocated.jar")
  111. excludeBootstrapJars()
  112. }
  113. val relocateJavaagentLibs by registering(ShadowJar::class) {
  114. configurations = listOf(javaagentLibs)
  115. duplicatesStrategy = DuplicatesStrategy.FAIL
  116. archiveFileName.set("javaagentLibs-relocated.jar")
  117. excludeBootstrapJars()
  118. }
  119. val relocateExporterLibs by registering(ShadowJar::class) {
  120. configurations = listOf(exporterLibs)
  121. archiveFileName.set("exporterLibs-relocated.jar")
  122. }
  123. val relocateExporterSlimLibs by registering(ShadowJar::class) {
  124. configurations = listOf(exporterSlimLibs)
  125. archiveFileName.set("exporterSlimLibs-relocated.jar")
  126. }
  127. // Includes everything needed for OOTB experience
  128. val shadowJar by existing(ShadowJar::class) {
  129. configurations = listOf(bootstrapLibs)
  130. dependsOn(relocateJavaagentLibs, relocateExporterLibs)
  131. isolateClasses(relocateJavaagentLibs.get().outputs.files)
  132. isolateClasses(relocateExporterLibs.get().outputs.files)
  133. duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  134. archiveClassifier.set("")
  135. manifest {
  136. attributes(jar.get().manifest.attributes)
  137. attributes(
  138. "Main-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
  139. "Agent-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
  140. "Premain-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
  141. "Can-Redefine-Classes" to true,
  142. "Can-Retransform-Classes" to true
  143. )
  144. }
  145. }
  146. // Includes instrumentations plus the OTLP/gRPC exporters
  147. val slimShadowJar by registering(ShadowJar::class) {
  148. configurations = listOf(bootstrapLibs)
  149. dependsOn(relocateJavaagentLibs, relocateExporterSlimLibs)
  150. isolateClasses(relocateJavaagentLibs.get().outputs.files)
  151. isolateClasses(relocateExporterSlimLibs.get().outputs.files)
  152. archiveClassifier.set("slim")
  153. manifest {
  154. attributes(shadowJar.get().manifest.attributes)
  155. }
  156. }
  157. // Includes only the agent machinery and required instrumentations
  158. val baseJavaagentJar by registering(ShadowJar::class) {
  159. configurations = listOf(bootstrapLibs)
  160. dependsOn(relocateBaseJavaagentLibs)
  161. isolateClasses(relocateBaseJavaagentLibs.get().outputs.files)
  162. duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  163. archiveClassifier.set("base")
  164. manifest {
  165. attributes(shadowJar.get().manifest.attributes)
  166. }
  167. }
  168. val baseJar by configurations.creating {
  169. isCanBeConsumed = true
  170. isCanBeResolved = false
  171. }
  172. artifacts {
  173. add("baseJar", baseJavaagentJar)
  174. }
  175. jar {
  176. enabled = false
  177. }
  178. assemble {
  179. dependsOn(shadowJar, slimShadowJar, baseJavaagentJar)
  180. }
  181. withType<Test>().configureEach {
  182. dependsOn(shadowJar)
  183. jvmArgs("-Dotel.javaagent.debug=true")
  184. jvmArgumentProviders.add(JavaagentProvider(shadowJar.flatMap { it.archiveFile }))
  185. testLogging {
  186. events("started")
  187. }
  188. }
  189. val cleanLicenses by registering(Delete::class) {
  190. delete(rootProject.file("licenses"))
  191. }
  192. named("generateLicenseReport").configure {
  193. dependsOn(cleanLicenses)
  194. }
  195. publishing {
  196. publications {
  197. named<MavenPublication>("maven") {
  198. artifact(slimShadowJar)
  199. project.shadow.component(this)
  200. }
  201. }
  202. }
  203. }
  204. licenseReport {
  205. outputDir = rootProject.file("licenses").absolutePath
  206. renderers = arrayOf(InventoryMarkdownReportRenderer())
  207. configurations = arrayOf(licenseReportDependencies.name)
  208. excludeGroups = arrayOf(
  209. "io.opentelemetry.instrumentation",
  210. "io.opentelemetry.javaagent"
  211. )
  212. filters = arrayOf(LicenseBundleNormalizer("$projectDir/license-normalizer-bundle.json", true))
  213. }
  214. fun CopySpec.isolateClasses(jars: Iterable<File>) {
  215. jars.forEach {
  216. from(zipTree(it)) {
  217. // important to keep prefix "inst" short, as it is prefixed to lots of strings in runtime mem
  218. into("inst")
  219. rename("(^.*)\\.class\$", "\$1.classdata")
  220. // Rename LICENSE file since it clashes with license dir on non-case sensitive FSs (i.e. Mac)
  221. rename("""^LICENSE$""", "LICENSE.renamed")
  222. exclude("META-INF/INDEX.LIST")
  223. exclude("META-INF/*.DSA")
  224. exclude("META-INF/*.SF")
  225. }
  226. }
  227. }
  228. // exclude bootstrap projects from javaagent libs - they won't be added to inst/
  229. fun ShadowJar.excludeBootstrapJars() {
  230. dependencies {
  231. exclude(project(":instrumentation-api"))
  232. exclude(project(":instrumentation-api-annotation-support"))
  233. exclude(project(":instrumentation-api-appender"))
  234. exclude(project(":javaagent-bootstrap"))
  235. exclude(project(":javaagent-instrumentation-api"))
  236. }
  237. }
  238. class JavaagentProvider(
  239. @InputFile
  240. @PathSensitive(PathSensitivity.RELATIVE)
  241. val agentJar: Provider<RegularFile>
  242. ) : CommandLineArgumentProvider {
  243. override fun asArguments(): Iterable<String> = listOf(
  244. "-javaagent:${file(agentJar).absolutePath}"
  245. )
  246. }