55import java .io .File ;
66import java .lang .instrument .Instrumentation ;
77import java .net .URL ;
8+ import java .net .URLClassLoader ;
89import java .util .jar .JarFile ;
910
1011/**
@@ -44,15 +45,12 @@ private static synchronized void install(String agentArgs, Instrumentation inst)
4445
4546 if (jvmRunningWithOtelAgent ()) {
4647 log (
47- "ERROR: Braintrust agent is not yet compatible with the OTel javaagent - "
48- + " skipping install." );
48+ "ERROR: Braintrust agent is not yet compatible with the OTel -javaagent. "
49+ + " aborting install." );
4950 return ;
5051 }
51-
52- if (jvmRunningWithDatadogOtel ()) {
53- log (
54- "ERROR: Braintrust agent is not yet compatible with datadog javaagent otel -"
55- + " skipping install." );
52+ if (jvmRunningWithDatadogOtel () && (!isRunningAfterDatadogAgent ())) {
53+ log ("ERROR: Braintrust agent must run _after_ datadog -javaagent. aborting install." );
5654 return ;
5755 }
5856
@@ -67,16 +65,28 @@ private static synchronized void install(String agentArgs, Instrumentation inst)
6765 // are set before anything can trigger GlobalOpenTelemetry.get().
6866 enableOtelSDKAutoconfiguration ();
6967
70- inst .appendToBootstrapClassLoaderSearch (new JarFile (agentJarFile , false ));
71- log ("Added agent JAR to bootstrap classpath." );
68+ if (!jvmRunningWithDatadogOtel ()) {
69+ inst .appendToBootstrapClassLoaderSearch (new JarFile (agentJarFile , false ));
70+ log ("Added agent JAR to bootstrap classpath." );
71+ } else {
72+ log ("datadog detected, skipping bootstrap classpath setup" );
73+ }
7274
7375 // Create the isolated braintrust classloader.
7476 // Parent is the platform classloader so agent internals can see:
7577 // - Bootstrap classes (OTel API/SDK added via appendToBootstrapClassLoaderSearch)
7678 // - JDK platform modules (java.net.http, java.sql, etc.)
7779 // but NOT application classes (those are on the system/app classloader).
80+ ClassLoader otherCL =
81+ new URLClassLoader (
82+ new URL [] {agentJarFile .toURI ().toURL ()},
83+ ClassLoader .getPlatformClassLoader ());
7884 BraintrustClassLoader btClassLoader =
79- new BraintrustClassLoader (agentJarURL , ClassLoader .getPlatformClassLoader ());
85+ new BraintrustClassLoader (
86+ agentJarURL ,
87+ jvmRunningWithDatadogOtel ()
88+ ? otherCL
89+ : ClassLoader .getPlatformClassLoader ());
8090 BraintrustBridge .setAgentClassLoaderIfAbsent (btClassLoader );
8191
8292 // Load and invoke the real agent installer through the isolated classloader.
@@ -109,16 +119,8 @@ private static boolean jvmRunningWithOtelAgent() {
109119 }
110120 }
111121
112- /**
113- * Checks whether the Datadog agent is present and configured for OTel integration. Must be
114- * callable from the system classloader (no DD compile deps).
115- */
122+ /** Checks whether the Datadog agent is present and configured for OTel integration */
116123 private static boolean jvmRunningWithDatadogOtel () {
117- try {
118- Class .forName ("datadog.trace.bootstrap.Agent" , false , null );
119- } catch (ClassNotFoundException e ) {
120- return false ;
121- }
122124 String sysProp = System .getProperty ("dd.trace.otel.enabled" );
123125 if (sysProp != null ) {
124126 return Boolean .parseBoolean (sysProp );
@@ -131,7 +133,7 @@ private static boolean jvmRunningWithDatadogOtel() {
131133 * Returns true if the Datadog agent's premain has already executed, meaning it was listed
132134 * before the Braintrust agent in the {@code -javaagent} flags.
133135 */
134- static boolean isRunningAfterDatadogAgent () {
136+ private static boolean isRunningAfterDatadogAgent () {
135137 // DD's premain appends its jars to the bootstrap classpath, making
136138 // {@code datadog.trace.bootstrap.Agent} loadable from the bootstrap (null)
137139 // classloader. If that class is not found on bootstrap, DD either isn't
0 commit comments