Create shared internal jar
MODIFY
dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java
dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java
@@ -166,18 +166,21 @@ public class Agent {
private static synchronized void createParentClassloader(final URL bootstrapURL) {
if (PARENT_CLASSLOADER == null) {
try {
+ final Class<?> bootstrapProxyClass =
+ ClassLoader.getSystemClassLoader()
+ .loadClass("datadog.trace.bootstrap.DatadogClassLoader$BootstrapClassLoaderProxy");
+ final Constructor constructor = bootstrapProxyClass.getDeclaredConstructor(URL.class);
+ BOOTSTRAP_PROXY = (ClassLoader) constructor.newInstance(bootstrapURL);
+
+ final ClassLoader grandParent;
if (isJavaBefore9()) {
- PARENT_CLASSLOADER = null; // bootstrap
+ grandParent = null; // bootstrap
} else {
// platform classloader is parent of system in java 9+
- PARENT_CLASSLOADER = getPlatformClassLoader();
+ grandParent = getPlatformClassLoader();
}
- final Class<?> loaderClass =
- ClassLoader.getSystemClassLoader()
- .loadClass("datadog.trace.bootstrap.DatadogClassLoader$BootstrapClassLoaderProxy");
- final Constructor constructor = loaderClass.getDeclaredConstructor(URL.class);
- BOOTSTRAP_PROXY = (ClassLoader) constructor.newInstance(bootstrapURL);
+ PARENT_CLASSLOADER = createDatadogClassLoader("shared.isolated", bootstrapURL, grandParent);
} catch (final Throwable ex) {
log.error("Throwable thrown creating parent classloader", ex);
}
@@ -189,7 +192,9 @@ public class Agent {
if (AGENT_CLASSLOADER == null) {
try {
final ClassLoader agentClassLoader =
- createDatadogClassLoader("agent-tooling-and-instrumentation.isolated", bootstrapURL);
+ createDatadogClassLoader(
+ "agent-tooling-and-instrumentation.isolated", bootstrapURL, PARENT_CLASSLOADER);
+
final Class<?> agentInstallerClass =
agentClassLoader.loadClass("datadog.trace.agent.tooling.AgentInstaller");
final Method agentInstallerMethod =
@@ -226,7 +231,7 @@ public class Agent {
final ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
try {
final ClassLoader jmxFetchClassLoader =
- createDatadogClassLoader("agent-jmxfetch.isolated", bootstrapURL);
+ createDatadogClassLoader("agent-jmxfetch.isolated", bootstrapURL, PARENT_CLASSLOADER);
Thread.currentThread().setContextClassLoader(jmxFetchClassLoader);
final Class<?> jmxFetchAgentClass =
jmxFetchClassLoader.loadClass("datadog.trace.agent.jmxfetch.JMXFetch");
@@ -267,7 +272,8 @@ public class Agent {
* @return Datadog Classloader
*/
private static ClassLoader createDatadogClassLoader(
- final String innerJarFilename, final URL bootstrapURL) throws Exception {
+ final String innerJarFilename, final URL bootstrapURL, final ClassLoader parent)
+ throws Exception {
final Class<?> loaderClass =
ClassLoader.getSystemClassLoader().loadClass("datadog.trace.bootstrap.DatadogClassLoader");
@@ -275,8 +281,7 @@ public class Agent {
loaderClass.getDeclaredConstructor(
URL.class, String.class, ClassLoader.class, ClassLoader.class);
return (ClassLoader)
- constructor.newInstance(
- bootstrapURL, innerJarFilename, BOOTSTRAP_PROXY, PARENT_CLASSLOADER);
+ constructor.newInstance(bootstrapURL, innerJarFilename, BOOTSTRAP_PROXY, parent);
}
private static ClassLoader getPlatformClassLoader()

MODIFY
dd-java-agent/agent-jmxfetch/agent-jmxfetch.gradle
dd-java-agent/agent-jmxfetch/agent-jmxfetch.gradle
@@ -13,18 +13,11 @@ dependencies {
compile project(':dd-trace-api')
}
-configurations {
- // exclude bootstrap dependencies from shadowJar
- runtime.exclude module: deps.opentracing
- runtime.exclude module: deps.slf4j
- runtime.exclude group: 'org.slf4j'
- runtime.exclude group: 'io.opentracing'
-}
-
shadowJar {
dependencies {
exclude(project(':dd-java-agent:agent-bootstrap'))
exclude(project(':dd-trace-api'))
+ exclude(dependency('org.slf4j::'))
}
}

MODIFY
dd-java-agent/dd-java-agent.gradle
dd-java-agent/dd-java-agent.gradle
@@ -9,14 +9,45 @@ apply from: "${rootDir}/gradle/publish.gradle"
configurations {
shadowInclude
+ sharedShadowInclude
}
+
+/*
+ * 4 shadow jars are created
+ * - The main "dd-java-agent" jar
+ * - 2 jars based on projects (jmxfetch, agent tooling)
+ * - 1 based on the shared dependencies
+ * This general config is shared by all of them
+ */
+
+def generalShadowJarConfig = {
+ mergeServiceFiles()
+
+ exclude '**/module-info.class'
+
+ dependencies {
+ exclude(dependency("org.projectlombok:lombok:$versions.lombok"))
+ }
+
+ // Prevents conflict with other SLF4J instances. Important for premain.
+ relocate 'org.slf4j', 'datadog.slf4j'
+ // rewrite dependencies calling Logger.getLogger
+ relocate 'java.util.logging.Logger', 'datadog.trace.bootstrap.PatchLogger'
+
+ if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) {
+ // shadow OT impl to prevent casts to implementation
+ relocate 'datadog.trace.common', 'datadog.trace.agent.common'
+ relocate 'datadog.opentracing', 'datadog.trace.agent.ot'
+ }
+}
+
/*
* Include subproject's shadowJar in the dd-java-agent jar.
* Note jarname must not end with '.jar', or its classes will be on the classpath of
* the dd-java-agent jar.
*/
-def includeShadowJar(subproject, jarname) {
+def includeShadowJar(subproject, jarname, generalShadowJarConfig) {
def agent_project = project
subproject.afterEvaluate {
agent_project.processResources {
@@ -29,34 +60,37 @@ def includeShadowJar(subproject, jarname) {
}
agent_project.processResources.dependsOn subproject.tasks.shadowJar
- subproject.shadowJar {
- mergeServiceFiles()
-
- exclude '**/module-info.class'
- dependencies {
- exclude(dependency("org.projectlombok:lombok:$versions.lombok"))
+ // subproject.shadowJar generalShadowJarConfig
+ subproject.shadowJar generalShadowJarConfig >> {
+ dependencies deps.sharedInverse
+ }
+ }
}
- // Prevents conflict with other SLF4J instances. Important for premain.
- relocate 'org.slf4j', 'datadog.slf4j'
- // rewrite dependencies calling Logger.getLogger
- relocate 'java.util.logging.Logger', 'datadog.trace.bootstrap.PatchLogger'
+includeShadowJar(project(':dd-java-agent:instrumentation'), 'agent-tooling-and-instrumentation.isolated', generalShadowJarConfig)
+includeShadowJar(project(':dd-java-agent:agent-jmxfetch'), 'agent-jmxfetch.isolated', generalShadowJarConfig)
- if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) {
- // shadow OT impl to prevent casts to implementation
- relocate 'datadog.trace.common', 'datadog.trace.agent.common'
- relocate 'datadog.opentracing', 'datadog.trace.agent.ot'
- }
+task includedSharedShadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {}
+
+includedSharedShadowJar generalShadowJarConfig >> {
+ configurations = [project.configurations.sharedShadowInclude]
}
+
+project.processResources.dependsOn includedSharedShadowJar
+project.processResources {
+ from(zipTree(includedSharedShadowJar.archiveFile)) {
+ into 'shared.isolated'
+ 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'
}
}
-includeShadowJar(project(':dd-java-agent:instrumentation'), 'agent-tooling-and-instrumentation.isolated')
-includeShadowJar(project(':dd-java-agent:agent-jmxfetch'), 'agent-jmxfetch.isolated')
+shadowJar generalShadowJarConfig >> {
+ configurations = [project.configurations.shadowInclude]
-jar {
- archiveClassifier = 'unbundled'
+ archiveClassifier = ''
manifest {
attributes(
@@ -69,31 +103,6 @@ jar {
}
}
-shadowJar {
- configurations = [project.configurations.shadowInclude]
-
- archiveClassifier = ''
-
- mergeServiceFiles()
-
- exclude '**/module-info.class'
-
- dependencies {
- exclude(dependency("org.projectlombok:lombok:$versions.lombok"))
- }
-
- // Prevents conflict with other SLF4J instances. Important for premain.
- relocate 'org.slf4j', 'datadog.slf4j'
- // rewrite dependencies calling Logger.getLogger
- relocate 'java.util.logging.Logger', 'datadog.trace.bootstrap.PatchLogger'
-
- if (!project.hasProperty("disableShadowRelocate") || !disableShadowRelocate) {
- // shadow OT impl to prevent casts to implementation
- relocate 'datadog.trace.common', 'datadog.trace.agent.common'
- relocate 'datadog.opentracing', 'datadog.trace.agent.ot'
- }
-}
-
// We don't want bundled dependencies to show up in the pom.
modifyPom {
dependencies.removeAll { true }
@@ -109,7 +118,11 @@ dependencies {
testCompile deps.testLogging
testCompile deps.guava
+ // Includes for the top level shadow jar
shadowInclude project(path: ':dd-java-agent:agent-bootstrap')
+
+ // Includes for the shared internal shadow jar
+ sharedShadowInclude deps.shared
}
tasks.withType(Test).configureEach {

MODIFY
dd-java-agent/instrumentation/instrumentation.gradle
dd-java-agent/instrumentation/instrumentation.gradle
@@ -76,16 +76,11 @@ dependencies {
}
}
-configurations {
- // exclude bootstrap dependencies from shadowJar
- runtime.exclude module: deps.slf4j
- runtime.exclude group: 'org.slf4j'
-}
-
shadowJar {
dependencies {
exclude(project(':dd-java-agent:agent-bootstrap'))
exclude(project(':dd-trace-api'))
+ exclude(dependency('org.slf4j::'))
}
}

MODIFY
gradle/dependencies.gradle
gradle/dependencies.gradle
@@ -62,5 +62,31 @@ ext {
scala : dependencies.create(group: 'org.scala-lang', name: 'scala-library', version: "${versions.scala}"),
kotlin : dependencies.create(group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: "${versions.kotlin}"),
coroutines : dependencies.create(group: 'org.jetbrains.kotlinx', name: 'kotlinx-coroutines-core', version: "${versions.coroutines}"),
+
+ // Shared between agent tooling and instrumentation and JMXFetch
+ shared : [
+ dependencies.create(group: 'com.datadoghq', name: 'java-dogstatsd-client', version: '2.8'),
+ // "Explicit override jnr version because .22 caused issues" - mar-kolya
+ dependencies.create(group: 'com.github.jnr', name: 'jnr-unixsocket', version: '0.23'),
+ dependencies.create(group: 'com.google.guava', name: 'guava', version: "${versions.guava}")
+ ],
+
+ // Inverse of "shared". These exclude directives are part of shadowJar's DSL
+ // which is similar but not exactly the same as the regular gradle dependency{} block
+ // Also, transitive dependencies have to be explicitly listed
+ sharedInverse : (Closure) {
+ // dogstatsd and its transitives
+ exclude(dependency('com.datadoghq:java-dogstatsd-client'))
+ exclude(dependency('com.github.jnr::'))
+ exclude(dependency('org.ow2.asm::'))
+
+ // Guava and its transitives
+ exclude(dependency('com.google.guava::'))
+ exclude(dependency('com.google.code.findbugs::'))
+ exclude(dependency('com.google.errorprone::'))
+ exclude(dependency('com.google.j2objc::'))
+ exclude(dependency('org.codehaus.mojo::'))
+ exclude(dependency('org.checkerframework::'))
+ }
]
}

Create shared internal jar