Skip to content

Commit e4c42f6

Browse files
authored
Merge pull request DataDog#2388 from DataDog/mcculls/detectLibrariesOnBoot
Initial support for detecting certain libraries at boot to help tune agent behaviour
2 parents 6c76747 + 13e6602 commit e4c42f6

2 files changed

Lines changed: 55 additions & 22 deletions

File tree

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package datadog.trace.bootstrap;
22

33
import static datadog.trace.api.Platform.isJavaVersionAtLeast;
4+
import static datadog.trace.bootstrap.Library.WILDFLY;
5+
import static datadog.trace.bootstrap.Library.detectLibraries;
46
import static datadog.trace.util.AgentThreadFactory.AgentThread.JMX_STARTUP;
57
import static datadog.trace.util.AgentThreadFactory.AgentThread.PROFILER_STARTUP;
68
import static datadog.trace.util.AgentThreadFactory.AgentThread.TRACE_STARTUP;
@@ -13,6 +15,7 @@
1315
import java.lang.reflect.InvocationTargetException;
1416
import java.lang.reflect.Method;
1517
import java.net.URL;
18+
import java.util.EnumSet;
1619
import org.slf4j.Logger;
1720
import org.slf4j.LoggerFactory;
1821

@@ -63,9 +66,10 @@ public static void start(final Instrumentation inst, final URL bootstrapURL) {
6366

6467
startDatadogAgent(inst, bootstrapURL);
6568

66-
final boolean appUsingCustomLogManager = isAppUsingCustomLogManager();
69+
final EnumSet<Library> libraries = detectLibraries(log);
6770

68-
final boolean appUsingCustomJMXBuilder = isAppUsingCustomJMXBuilder();
71+
final boolean appUsingCustomLogManager = isAppUsingCustomLogManager(libraries);
72+
final boolean appUsingCustomJMXBuilder = isAppUsingCustomJMXBuilder(libraries);
6973

7074
/*
7175
* java.util.logging.LogManager maintains a final static LogManager, which is created during class initialization.
@@ -464,8 +468,7 @@ private static boolean isDebugMode() {
464468
return Boolean.parseBoolean(tracerDebugLevelProp);
465469
}
466470

467-
final String tracerDebugLevelEnv =
468-
System.getenv(tracerDebugLevelSysprop.replace('.', '_').toUpperCase());
471+
final String tracerDebugLevelEnv = ddGetEnv(tracerDebugLevelSysprop);
469472

470473
if (tracerDebugLevelEnv != null) {
471474
return Boolean.parseBoolean(tracerDebugLevelEnv);
@@ -482,7 +485,7 @@ private static boolean isStartupLogsEnabled() {
482485
final String startupLogsSysprop = "dd.trace.startup.logs";
483486
String startupLogsEnabled = System.getProperty(startupLogsSysprop);
484487
if (startupLogsEnabled == null) {
485-
startupLogsEnabled = System.getenv(startupLogsSysprop.replace('.', '_').toUpperCase());
488+
startupLogsEnabled = ddGetEnv(startupLogsSysprop);
486489
}
487490
// assume true unless it's explicitly set to "false"
488491
return !"false".equalsIgnoreCase(startupLogsEnabled);
@@ -494,11 +497,10 @@ private static boolean isStartupLogsEnabled() {
494497
*
495498
* @return true if we detect a custom log manager being used.
496499
*/
497-
private static boolean isAppUsingCustomLogManager() {
500+
private static boolean isAppUsingCustomLogManager(final EnumSet<Library> libraries) {
498501
final String tracerCustomLogManSysprop = "dd.app.customlogmanager";
499502
final String customLogManagerProp = System.getProperty(tracerCustomLogManSysprop);
500-
final String customLogManagerEnv =
501-
System.getenv(tracerCustomLogManSysprop.replace('.', '_').toUpperCase());
503+
final String customLogManagerEnv = ddGetEnv(tracerCustomLogManSysprop);
502504

503505
if (customLogManagerProp != null || customLogManagerEnv != null) {
504506
log.debug("Prop - customlogmanager: " + customLogManagerProp);
@@ -508,21 +510,14 @@ private static boolean isAppUsingCustomLogManager() {
508510
|| Boolean.parseBoolean(customLogManagerEnv);
509511
}
510512

511-
final String jbossHome = System.getenv("JBOSS_HOME");
512-
if (jbossHome != null) {
513-
log.debug("Env - jboss: " + jbossHome);
514-
// JBoss/Wildfly is known to set a custom log manager after startup.
515-
// Originally we were checking for the presence of a jboss class,
516-
// but it seems some non-jboss applications have jboss classes on the classpath.
517-
// This would cause jmxfetch initialization to be delayed indefinitely.
518-
// Checking for an environment variable required by jboss instead.
519-
return true;
513+
if (libraries.contains(WILDFLY)) {
514+
return true; // Wildfly is known to set a custom log manager after startup.
520515
}
521516

522517
final String logManagerProp = System.getProperty("java.util.logging.manager");
523518
if (logManagerProp != null) {
524519
final boolean onSysClasspath =
525-
ClassLoader.getSystemResource(logManagerProp.replaceAll("\\.", "/") + ".class") != null;
520+
ClassLoader.getSystemResource(logManagerProp.replace('.', '/') + ".class") != null;
526521
log.debug("Prop - logging.manager: " + logManagerProp);
527522
log.debug("logging.manager on system classpath: " + onSysClasspath);
528523
// Some applications set java.util.logging.manager but never actually initialize the logger.
@@ -540,11 +535,10 @@ private static boolean isAppUsingCustomLogManager() {
540535
*
541536
* @return true if we detect a custom JMX builder being used.
542537
*/
543-
private static boolean isAppUsingCustomJMXBuilder() {
538+
private static boolean isAppUsingCustomJMXBuilder(final EnumSet<Library> libraries) {
544539
final String tracerCustomJMXBuilderSysprop = "dd.app.customjmxbuilder";
545540
final String customJMXBuilderProp = System.getProperty(tracerCustomJMXBuilderSysprop);
546-
final String customJMXBuilderEnv =
547-
System.getenv(tracerCustomJMXBuilderSysprop.replace('.', '_').toUpperCase());
541+
final String customJMXBuilderEnv = ddGetEnv(tracerCustomJMXBuilderSysprop);
548542

549543
if (customJMXBuilderProp != null || customJMXBuilderEnv != null) {
550544
log.debug("Prop - customjmxbuilder: " + customJMXBuilderProp);
@@ -554,10 +548,15 @@ private static boolean isAppUsingCustomJMXBuilder() {
554548
|| Boolean.parseBoolean(customJMXBuilderEnv);
555549
}
556550

551+
// FIXME: uncomment this when we add delayed JMX startup
552+
// if (libraries.contains(WILDFLY)) {
553+
// return true; // Wildfly is known to set a custom JMX builder after startup.
554+
// }
555+
557556
final String jmxBuilderProp = System.getProperty("javax.management.builder.initial");
558557
if (jmxBuilderProp != null) {
559558
final boolean onSysClasspath =
560-
ClassLoader.getSystemResource(jmxBuilderProp.replaceAll("\\.", "/") + ".class") != null;
559+
ClassLoader.getSystemResource(jmxBuilderProp.replace('.', '/') + ".class") != null;
561560
log.debug("Prop - javax.management.builder.initial: " + jmxBuilderProp);
562561
log.debug("javax.management.builder.initial on system classpath: " + onSysClasspath);
563562
// Some applications set javax.management.builder.initial but never actually initialize JMX.
@@ -569,6 +568,11 @@ private static boolean isAppUsingCustomJMXBuilder() {
569568
return false;
570569
}
571570

571+
/** Looks for the "DD_" environment variable equivalent of the given "dd." system property. */
572+
private static String ddGetEnv(final String sysProp) {
573+
return System.getenv(sysProp.replace('.', '_').toUpperCase());
574+
}
575+
572576
private static boolean isJavaBefore9WithJFR() {
573577
if (isJavaVersionAtLeast(9)) {
574578
return false;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package datadog.trace.bootstrap;
2+
3+
import java.util.EnumSet;
4+
import org.slf4j.Logger;
5+
6+
/** Tracks third-party libraries that may need special handling during agent startup. */
7+
public enum Library {
8+
WILDFLY;
9+
10+
/**
11+
* Best-effort detection of libraries potentially used by the application. This is called at boot
12+
* so we need to be very careful how many checks happen here. Some library use may not be visible
13+
* to the agent at this point.
14+
*/
15+
public static EnumSet<Library> detectLibraries(final Logger log) {
16+
final EnumSet<Library> libraries = EnumSet.noneOf(Library.class);
17+
18+
final String jbossHome = System.getenv("JBOSS_HOME");
19+
if (jbossHome != null) {
20+
log.debug("Env - jboss: {}", jbossHome);
21+
libraries.add(WILDFLY);
22+
}
23+
24+
if (!libraries.isEmpty()) {
25+
log.debug("Detected {}", libraries);
26+
}
27+
return libraries;
28+
}
29+
}

0 commit comments

Comments
 (0)