445 lines
16 KiB
Plaintext
445 lines
16 KiB
Plaintext
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
import com.github.jk1.license.filter.LicenseBundleNormalizer
|
|
import com.github.jk1.license.render.InventoryMarkdownReportRenderer
|
|
import org.spdx.sbom.gradle.SpdxSbomTask
|
|
import java.nio.file.Files
|
|
import java.util.UUID
|
|
import java.util.regex.Pattern
|
|
|
|
plugins {
|
|
id("com.github.jk1.dependency-license-report")
|
|
|
|
id("otel.java-conventions")
|
|
id("otel.publish-conventions")
|
|
id("io.opentelemetry.instrumentation.javaagent-shadowing")
|
|
id("org.spdx.sbom")
|
|
}
|
|
|
|
description = "OpenTelemetry Javaagent"
|
|
group = "io.opentelemetry.javaagent"
|
|
|
|
// this configuration collects libs that will be placed in the bootstrap classloader
|
|
val bootstrapLibs by configurations.creating {
|
|
isCanBeResolved = true
|
|
isCanBeConsumed = false
|
|
}
|
|
// this configuration collects only required instrumentations and agent machinery
|
|
val baseJavaagentLibs by configurations.creating {
|
|
isCanBeResolved = true
|
|
isCanBeConsumed = false
|
|
}
|
|
// this configuration collects libs that will be placed in the agent classloader, isolated from the instrumented application code
|
|
val javaagentLibs by configurations.creating {
|
|
isCanBeResolved = true
|
|
isCanBeConsumed = false
|
|
extendsFrom(baseJavaagentLibs)
|
|
}
|
|
|
|
// exclude dependencies that are to be placed in bootstrap from agent libs - they won't be added to inst/
|
|
listOf(baseJavaagentLibs, javaagentLibs).forEach {
|
|
it.run {
|
|
exclude("io.opentelemetry", "opentelemetry-api")
|
|
exclude("io.opentelemetry.semconv", "opentelemetry-semconv")
|
|
exclude("io.opentelemetry.semconv", "opentelemetry-semconv-incubating")
|
|
// events API and metrics advice API
|
|
exclude("io.opentelemetry", "opentelemetry-api-incubator")
|
|
}
|
|
}
|
|
|
|
val licenseReportDependencies by configurations.creating {
|
|
extendsFrom(bootstrapLibs)
|
|
extendsFrom(baseJavaagentLibs)
|
|
}
|
|
|
|
dependencies {
|
|
bootstrapLibs(project(":instrumentation-api"))
|
|
// opentelemetry-api is an api dependency of :instrumentation-api, but opentelemetry-api-incubator is not
|
|
bootstrapLibs("io.opentelemetry:opentelemetry-api-incubator")
|
|
bootstrapLibs(project(":instrumentation-api-incubator"))
|
|
bootstrapLibs(project(":instrumentation-annotations-support"))
|
|
bootstrapLibs(project(":javaagent-bootstrap"))
|
|
|
|
// extension-api contains both bootstrap packages and agent packages
|
|
bootstrapLibs(project(":javaagent-extension-api")) {
|
|
// exclude javaagent dependencies from the bootstrap classpath
|
|
exclude("net.bytebuddy")
|
|
exclude("org.ow2.asm")
|
|
exclude("io.opentelemetry", "opentelemetry-sdk")
|
|
exclude("io.opentelemetry", "opentelemetry-sdk-extension-autoconfigure")
|
|
exclude("io.opentelemetry", "opentelemetry-sdk-extension-autoconfigure-spi")
|
|
}
|
|
baseJavaagentLibs(project(":javaagent-extension-api"))
|
|
|
|
baseJavaagentLibs(project(":javaagent-tooling"))
|
|
baseJavaagentLibs(project(":javaagent-internal-logging-application"))
|
|
baseJavaagentLibs(project(":javaagent-internal-logging-simple", configuration = "shadow"))
|
|
baseJavaagentLibs(project(":muzzle"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.15:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.27:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.31:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.32:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.37:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.38:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.40:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.42:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-api:opentelemetry-api-1.47:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-instrumentation-api:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:opentelemetry-instrumentation-annotations-1.16:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:executors:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-application-logger:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-class-loader:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-lambda:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-reflection:javaagent"))
|
|
baseJavaagentLibs(project(":instrumentation:internal:internal-url-class-loader:javaagent"))
|
|
|
|
// concurrentlinkedhashmap-lru and weak-lock-free are copied in to the instrumentation-api module
|
|
licenseReportDependencies("com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2")
|
|
licenseReportDependencies("com.blogspot.mydailyjava:weak-lock-free:0.18")
|
|
licenseReportDependencies(project(":javaagent-internal-logging-simple")) // need the non-shadow versions
|
|
|
|
testCompileOnly(project(":javaagent-bootstrap"))
|
|
testCompileOnly(project(":javaagent-extension-api"))
|
|
|
|
testImplementation(project(":testing-common"))
|
|
testImplementation("io.opentracing.contrib.dropwizard:dropwizard-opentracing:0.2.2")
|
|
}
|
|
|
|
val javaagentDependencies = dependencies
|
|
|
|
// collect all bootstrap and javaagent instrumentation dependencies
|
|
project(":instrumentation").subprojects {
|
|
val subProj = this
|
|
|
|
plugins.withId("otel.javaagent-bootstrap") {
|
|
javaagentDependencies.run {
|
|
add(bootstrapLibs.name, project(subProj.path))
|
|
}
|
|
}
|
|
|
|
plugins.withId("otel.javaagent-instrumentation") {
|
|
javaagentDependencies.run {
|
|
add(javaagentLibs.name, project(subProj.path))
|
|
}
|
|
}
|
|
|
|
plugins.withId("otel.sdk-extension") {
|
|
javaagentDependencies.run {
|
|
add(javaagentLibs.name, project(subProj.path))
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks {
|
|
processResources {
|
|
from(rootProject.file("licenses")) {
|
|
into("META-INF/licenses")
|
|
}
|
|
}
|
|
|
|
val buildBootstrapLibs by registering(ShadowJar::class) {
|
|
configurations = listOf(bootstrapLibs)
|
|
|
|
// exclude the agent part of the javaagent-extension-api; these classes will be added in relocate tasks
|
|
exclude("io/opentelemetry/javaagent/extension/**")
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
|
|
archiveFileName.set("bootstrapLibs.jar")
|
|
}
|
|
|
|
val relocateBaseJavaagentLibsTmp by registering(ShadowJar::class) {
|
|
configurations = listOf(baseJavaagentLibs)
|
|
|
|
excludeBootstrapClasses()
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveFileName.set("baseJavaagentLibs-relocated-tmp.jar")
|
|
}
|
|
|
|
val relocateBaseJavaagentLibs by registering(Jar::class) {
|
|
dependsOn(relocateBaseJavaagentLibsTmp)
|
|
|
|
copyByteBuddy(relocateBaseJavaagentLibsTmp.get().archiveFile)
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveFileName.set("baseJavaagentLibs-relocated.jar")
|
|
}
|
|
|
|
val relocateJavaagentLibsTmp by registering(ShadowJar::class) {
|
|
configurations = listOf(javaagentLibs)
|
|
|
|
excludeBootstrapClasses()
|
|
// remove MPL licensed content
|
|
exclude("okhttp3/internal/publicsuffix/NOTICE")
|
|
exclude("okhttp3/internal/publicsuffix/publicsuffixes.gz")
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveFileName.set("javaagentLibs-relocated-tmp.jar")
|
|
}
|
|
|
|
val relocateJavaagentLibs by registering(Jar::class) {
|
|
dependsOn(relocateJavaagentLibsTmp)
|
|
|
|
copyByteBuddy(relocateJavaagentLibsTmp.get().archiveFile)
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveFileName.set("javaagentLibs-relocated.jar")
|
|
}
|
|
|
|
// Includes everything needed for OOTB experience
|
|
val shadowJar by existing(ShadowJar::class) {
|
|
dependsOn(buildBootstrapLibs)
|
|
from(zipTree(buildBootstrapLibs.get().archiveFile))
|
|
|
|
dependsOn(relocateJavaagentLibs)
|
|
isolateClasses(relocateJavaagentLibs.get().archiveFile)
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveClassifier.set("")
|
|
|
|
manifest {
|
|
attributes(jar.get().manifest.attributes)
|
|
attributes(
|
|
"Main-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
|
|
"Agent-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
|
|
"Premain-Class" to "io.opentelemetry.javaagent.OpenTelemetryAgent",
|
|
"Can-Redefine-Classes" to true,
|
|
"Can-Retransform-Classes" to true,
|
|
)
|
|
}
|
|
}
|
|
|
|
// Includes only the agent machinery and required instrumentations
|
|
val baseJavaagentJar by registering(ShadowJar::class) {
|
|
dependsOn(buildBootstrapLibs)
|
|
from(zipTree(buildBootstrapLibs.get().archiveFile))
|
|
|
|
dependsOn(relocateBaseJavaagentLibs)
|
|
isolateClasses(relocateBaseJavaagentLibs.get().archiveFile)
|
|
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
archiveClassifier.set("base")
|
|
|
|
manifest {
|
|
attributes(shadowJar.get().manifest.attributes)
|
|
}
|
|
}
|
|
|
|
jar {
|
|
// Empty jar that cannot be used for anything and isn't published.
|
|
archiveClassifier.set("dontuse")
|
|
}
|
|
|
|
val baseJar by configurations.creating {
|
|
isCanBeConsumed = true
|
|
isCanBeResolved = false
|
|
}
|
|
|
|
artifacts {
|
|
add("baseJar", baseJavaagentJar)
|
|
}
|
|
|
|
assemble {
|
|
dependsOn(shadowJar, baseJavaagentJar)
|
|
}
|
|
|
|
if (findProperty("removeJarVersionNumbers") == "true") {
|
|
withType<AbstractArchiveTask>().configureEach {
|
|
archiveVersion.set("")
|
|
}
|
|
}
|
|
|
|
withType<Test>().configureEach {
|
|
dependsOn(shadowJar)
|
|
|
|
jvmArgs("-Dotel.javaagent.debug=true")
|
|
jvmArgs("-Dotel.traces.exporter=none")
|
|
jvmArgs("-Dotel.metrics.exporter=none")
|
|
jvmArgs("-Dotel.logs.exporter=none")
|
|
|
|
jvmArgumentProviders.add(JavaagentProvider(shadowJar.flatMap { it.archiveFile }))
|
|
|
|
testLogging {
|
|
events("started")
|
|
}
|
|
}
|
|
|
|
val cleanLicenses by registering(Delete::class) {
|
|
delete(rootProject.file("licenses"))
|
|
}
|
|
|
|
val removeLicenseDate by registering {
|
|
// removing the license report date makes it idempotent
|
|
doLast {
|
|
val filePath = rootDir.toPath().resolve("licenses").resolve("licenses.md")
|
|
if (Files.exists(filePath)) {
|
|
val datePattern = Pattern.compile("^_[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} .*_$")
|
|
val lines = Files.readAllLines(filePath)
|
|
// 4th line contains the timestamp of when the license report was generated, replace it with
|
|
// an empty line
|
|
if (lines.size > 3 && datePattern.matcher(lines[3]).matches()) {
|
|
lines[3] = ""
|
|
Files.write(filePath, lines)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
val generateLicenseReportEnabled =
|
|
gradle.startParameter.taskNames.any { it.equals("generateLicenseReport") }
|
|
named("generateLicenseReport").configure {
|
|
dependsOn(cleanLicenses)
|
|
finalizedBy(":spotlessApply")
|
|
finalizedBy(removeLicenseDate)
|
|
// disable licence report generation unless this task is explicitly run
|
|
// the files produced by this task are used by other tasks without declaring them as dependency
|
|
// which gradle considers an error
|
|
enabled = enabled && generateLicenseReportEnabled
|
|
}
|
|
if (generateLicenseReportEnabled) {
|
|
project.parent?.tasks?.getByName("spotlessMisc")?.dependsOn(named("generateLicenseReport"))
|
|
}
|
|
|
|
// Because we reconfigure publishing to only include the shadow jar, the Gradle metadata is not correct.
|
|
// Since we are fully bundled and have no dependencies, Gradle metadata wouldn't provide any advantage over
|
|
// the POM anyways so in practice we shouldn't be losing anything.
|
|
withType<GenerateModuleMetadata>().configureEach {
|
|
enabled = false
|
|
}
|
|
}
|
|
|
|
// Don't publish non-shadowed jar (shadowJar is in shadowRuntimeElements)
|
|
with(components["java"] as AdhocComponentWithVariants) {
|
|
configurations.forEach {
|
|
withVariantsFromConfiguration(configurations["apiElements"]) {
|
|
skip()
|
|
}
|
|
withVariantsFromConfiguration(configurations["runtimeElements"]) {
|
|
skip()
|
|
}
|
|
}
|
|
}
|
|
|
|
spdxSbom {
|
|
targets {
|
|
// Create a target to match the published jar name.
|
|
// This is used for the task name (spdxSbomFor<SbomName>)
|
|
// and output file (<sbomName>.spdx.json).
|
|
create("opentelemetry-javaagent") {
|
|
configurations.set(listOf("baseJavaagentLibs"))
|
|
scm {
|
|
uri.set("https://github.com/" + System.getenv("GITHUB_REPOSITORY"))
|
|
revision.set(System.getenv("GITHUB_SHA"))
|
|
}
|
|
document {
|
|
name.set("opentelemetry-javaagent")
|
|
namespace.set("https://opentelemetry.io/spdx/" + UUID.randomUUID())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
tasks.withType<AbstractPublishToMaven> {
|
|
dependsOn("spdxSbom")
|
|
}
|
|
project.afterEvaluate {
|
|
tasks.withType<Sign>().configureEach {
|
|
mustRunAfter(tasks.withType<SpdxSbomTask>())
|
|
}
|
|
tasks.withType<PublishToMavenLocal>().configureEach {
|
|
this.publication.artifact("${layout.buildDirectory.get()}/spdx/opentelemetry-javaagent.spdx.json") {
|
|
classifier = "spdx"
|
|
extension = "json"
|
|
}
|
|
}
|
|
}
|
|
|
|
licenseReport {
|
|
outputDir = rootProject.file("licenses").absolutePath
|
|
|
|
renderers = arrayOf(InventoryMarkdownReportRenderer())
|
|
|
|
configurations = arrayOf(licenseReportDependencies.name)
|
|
|
|
excludeBoms = true
|
|
|
|
excludeGroups = arrayOf(
|
|
"io\\.opentelemetry\\.instrumentation",
|
|
"io\\.opentelemetry\\.javaagent",
|
|
"io\\.opentelemetry\\.dummy\\..*",
|
|
)
|
|
|
|
excludes = arrayOf(
|
|
"io.opentelemetry:opentelemetry-bom-alpha",
|
|
"opentelemetry-java-instrumentation:dependencyManagement",
|
|
)
|
|
|
|
filters = arrayOf(LicenseBundleNormalizer("$projectDir/license-normalizer-bundle.json", true))
|
|
}
|
|
|
|
fun CopySpec.isolateClasses(jar: Provider<RegularFile>) {
|
|
from(zipTree(jar)) {
|
|
// important to keep prefix "inst" short, as it is prefixed to lots of strings in runtime mem
|
|
into("inst")
|
|
rename("(^.*)\\.class\$", "\$1.classdata")
|
|
// Rename LICENSE file since it clashes with license dir on non-case sensitive FSs (i.e. Mac)
|
|
rename("""^LICENSE$""", "LICENSE.renamed")
|
|
exclude("META-INF/INDEX.LIST")
|
|
exclude("META-INF/*.DSA")
|
|
exclude("META-INF/*.SF")
|
|
exclude("META-INF/maven/**")
|
|
exclude("META-INF/MANIFEST.MF")
|
|
}
|
|
}
|
|
|
|
fun CopySpec.copyByteBuddy(jar: Provider<RegularFile>) {
|
|
// Byte buddy jar includes classes compiled for java 5 at the root of the jar and the same classes
|
|
// compiled for java 8 under META-INF/versions/9. Here we move the classes from
|
|
// META-INF/versions/9/net/bytebuddy to net/bytebuddy to get rid of the duplicate classes.
|
|
from(zipTree(jar)) {
|
|
eachFile {
|
|
if (path.startsWith("net/bytebuddy/") &&
|
|
// this is our class that we have placed in the byte buddy package, need to preserve it
|
|
!path.startsWith("net/bytebuddy/agent/builder/AgentBuilderUtil")) {
|
|
exclude()
|
|
} else if (path.startsWith("META-INF/versions/9/net/bytebuddy/")) {
|
|
path = path.removePrefix("META-INF/versions/9/")
|
|
}
|
|
}
|
|
includeEmptyDirs = false
|
|
}
|
|
}
|
|
|
|
// exclude bootstrap projects from javaagent libs - they won't be added to inst/
|
|
fun ShadowJar.excludeBootstrapClasses() {
|
|
dependencies {
|
|
exclude(project(":instrumentation-api"))
|
|
exclude(project(":instrumentation-api-incubator"))
|
|
exclude(project(":instrumentation-annotations-support"))
|
|
exclude(project(":javaagent-bootstrap"))
|
|
}
|
|
|
|
// exclude the bootstrap part of the javaagent-extension-api
|
|
exclude("io/opentelemetry/javaagent/bootstrap/**")
|
|
}
|
|
|
|
class JavaagentProvider(
|
|
@InputFile
|
|
@PathSensitive(PathSensitivity.RELATIVE)
|
|
val agentJar: Provider<RegularFile>,
|
|
) : CommandLineArgumentProvider {
|
|
override fun asArguments(): Iterable<String> = listOf(
|
|
"-javaagent:${file(agentJar).absolutePath}",
|
|
"-Dotel.javaagent.testing.transform-safe-logging.enabled=true"
|
|
)
|
|
}
|