11package datadog .trace .bootstrap ;
22
33import static datadog .trace .api .ConfigDefaults .DEFAULT_STARTUP_LOGS_ENABLED ;
4- import static datadog .trace .api .Platform .getRuntimeVendor ;
54import static datadog .trace .api .Platform .isJavaVersionAtLeast ;
65import static datadog .trace .api .Platform .isOracleJDK8 ;
76import static datadog .trace .bootstrap .Library .WILDFLY ;
@@ -329,7 +328,7 @@ public void run() {
329328 if (appUsingCustomJMXBuilder ) {
330329 log .debug ("Custom JMX builder detected. Delaying JMXFetch initialization." );
331330 registerMBeanServerBuilderCallback (new StartJmxCallback (jmxStartDelay ));
332- // one minute fail-safe in case nothing touches JMX and and callback isn't triggered
331+ // one minute fail-safe in case nothing touches JMX and callback isn't triggered
333332 scheduleJmxStart (60 + jmxStartDelay );
334333 } else if (appUsingCustomLogManager ) {
335334 log .debug ("Custom logger detected. Delaying JMXFetch initialization." );
@@ -339,20 +338,31 @@ public void run() {
339338 }
340339 }
341340
342- boolean delayOkHttp = appUsingCustomLogManager && okHttpMayIndirectlyLoadJUL ();
343-
344341 /*
345342 * Similar thing happens with DatadogTracer on (at least) zulu-8 because it uses OkHttp which indirectly loads JFR
346343 * events which in turn loads LogManager. This is not a problem on newer JDKs because there JFR uses different
347344 * logging facility. Likewise on IBM JDKs OkHttp may indirectly load 'IBMSASL' which in turn loads LogManager.
348345 */
346+ boolean delayOkHttp = !ciVisibilityEnabled && okHttpMayIndirectlyLoadJUL ();
347+ boolean waitForJUL = appUsingCustomLogManager && delayOkHttp ;
348+ int okHttpDelayMillis ;
349+ if (waitForJUL ) {
350+ okHttpDelayMillis = 1_000 ;
351+ } else if (delayOkHttp ) {
352+ okHttpDelayMillis = 100 ;
353+ } else {
354+ okHttpDelayMillis = 0 ;
355+ }
356+
349357 InstallDatadogTracerCallback installDatadogTracerCallback =
350- new InstallDatadogTracerCallback (initTelemetry , inst , delayOkHttp );
351- if (delayOkHttp ) {
358+ new InstallDatadogTracerCallback (initTelemetry , inst , okHttpDelayMillis );
359+ if (waitForJUL ) {
352360 log .debug ("Custom logger detected. Delaying Datadog Tracer initialization." );
353361 registerLogManagerCallback (installDatadogTracerCallback );
362+ } else if (okHttpDelayMillis > 0 ) {
363+ installDatadogTracerCallback .run (); // complete on different thread (after premain)
354364 } else {
355- installDatadogTracerCallback .execute ();
365+ installDatadogTracerCallback .execute (); // complete on primordial thread in premain
356366 }
357367
358368 /*
@@ -362,7 +372,7 @@ public void run() {
362372 if (profilingEnabled && !isOracleJDK8 ()) {
363373 StaticEventLogger .begin ("Profiling" );
364374
365- if (delayOkHttp ) {
375+ if (waitForJUL ) {
366376 log .debug ("Custom logger detected. Delaying Profiling initialization." );
367377 registerLogManagerCallback (new StartProfilingAgentCallback (inst ));
368378 } else {
@@ -499,18 +509,18 @@ protected static class InstallDatadogTracerCallback extends ClassLoadCallBack {
499509 private final Instrumentation instrumentation ;
500510 private final Object sco ;
501511 private final Class <?> scoClass ;
502- private final boolean delayOkHttp ;
512+ private final int okHttpDelayMillis ;
503513
504514 public InstallDatadogTracerCallback (
505515 InitializationTelemetry initTelemetry ,
506516 Instrumentation instrumentation ,
507- boolean delayOkHttp ) {
508- this .delayOkHttp = delayOkHttp ;
517+ int okHttpDelayMillis ) {
518+ this .okHttpDelayMillis = okHttpDelayMillis ;
509519 this .instrumentation = instrumentation ;
510520 try {
511521 scoClass =
512522 AGENT_CLASSLOADER .loadClass ("datadog.communication.ddagent.SharedCommunicationObjects" );
513- sco = scoClass .getConstructor (boolean .class ).newInstance (delayOkHttp );
523+ sco = scoClass .getConstructor (boolean .class ).newInstance (okHttpDelayMillis > 0 );
514524 } catch (ClassNotFoundException
515525 | NoSuchMethodException
516526 | InstantiationException
@@ -530,7 +540,7 @@ public AgentThread agentThread() {
530540
531541 @ Override
532542 public void execute () {
533- if (delayOkHttp ) {
543+ if (okHttpDelayMillis > 0 ) {
534544 resumeRemoteComponents ();
535545 }
536546
@@ -550,7 +560,7 @@ private void resumeRemoteComponents() {
550560 try {
551561 // remote components were paused for custom log-manager/jmx-builder
552562 // add small delay before resuming remote I/O to help stabilization
553- Thread .sleep (1_000 );
563+ Thread .sleep (okHttpDelayMillis );
554564 scoClass .getMethod ("resume" ).invoke (sco );
555565 } catch (InterruptedException ignore ) {
556566 } catch (Throwable e ) {
@@ -1339,15 +1349,25 @@ private static String ddGetEnv(final String sysProp) {
13391349 }
13401350
13411351 private static boolean okHttpMayIndirectlyLoadJUL () {
1342- if ("IBM Corporation" . equals ( getRuntimeVendor () )) {
1343- return true ; // IBM JDKs ship with 'IBMSASL' which will load JUL when OkHttp accesses TLS
1352+ if (isIBMSASLInstalled () || isACCPInstalled ( )) {
1353+ return true ; // 'IBMSASL' and 'ACCP' crypto providers can load JUL when OkHttp accesses TLS
13441354 }
13451355 if (isJavaVersionAtLeast (9 )) {
13461356 return false ; // JDKs since 9 have reworked JFR to use a different logging facility, not JUL
13471357 }
13481358 return isJFRSupported (); // assume OkHttp will indirectly load JUL via its JFR events
13491359 }
13501360
1361+ private static boolean isIBMSASLInstalled () {
1362+ return ClassLoader .getSystemResource ("com/ibm/security/sasl/IBMSASL.class" ) != null ;
1363+ }
1364+
1365+ private static boolean isACCPInstalled () {
1366+ return ClassLoader .getSystemResource (
1367+ "com/amazon/corretto/crypto/provider/AmazonCorrettoCryptoProvider.class" )
1368+ != null ;
1369+ }
1370+
13511371 private static boolean isJFRSupported () {
13521372 // FIXME: this is quite a hack because there maybe jfr classes on classpath somehow that have
13531373 // nothing to do with JDK - but this should be safe because only thing this does is to delay
0 commit comments