@@ -68,29 +68,38 @@ public class Agent {
6868 private static ClassLoader AGENT_CLASSLOADER = null ;
6969 private static ClassLoader JMXFETCH_CLASSLOADER = null ;
7070 private static ClassLoader PROFILING_CLASSLOADER = null ;
71+
7172 private static volatile AgentTaskScheduler .Task <URL > PROFILER_INIT_AFTER_JMX = null ;
7273
74+ private static boolean jmxFetchEnabled = true ;
75+ private static boolean profilingEnabled = false ;
76+
7377 public static void start (final Instrumentation inst , final URL bootstrapURL ) {
7478 createParentClassloader (bootstrapURL );
7579
76- if (!isOracleJDK8 ()) {
77- // Profiling agent startup code is written in a way to allow `startProfilingAgent` be called
78- // multiple times
79- // If early profiling is enabled then this call will start profiling.
80- // If early profiling is disabled then later call will do this.
81- startProfilingAgent (bootstrapURL , true );
82- } else {
83- log .debug ("Oracle JDK 8 detected. Delaying profiler initialization." );
84- // Profiling can not run early on Oracle JDK 8 because it will cause JFR initialization
85- // deadlock.
86- // Oracle JDK 8 JFR controller requires JMX so register an 'after-jmx-initialized' callback.
87- PROFILER_INIT_AFTER_JMX =
88- new AgentTaskScheduler .Task <URL >() {
89- @ Override
90- public void run (URL target ) {
91- startProfilingAgent (target , false );
92- }
93- };
80+ jmxFetchEnabled = isJmxFetchEnabled ();
81+ profilingEnabled = isProfilingEnabled ();
82+
83+ if (profilingEnabled ) {
84+ if (!isOracleJDK8 ()) {
85+ // Profiling agent startup code is written in a way to allow `startProfilingAgent` be called
86+ // multiple times
87+ // If early profiling is enabled then this call will start profiling.
88+ // If early profiling is disabled then later call will do this.
89+ startProfilingAgent (bootstrapURL , true );
90+ } else {
91+ log .debug ("Oracle JDK 8 detected. Delaying profiler initialization." );
92+ // Profiling can not run early on Oracle JDK 8 because it will cause JFR initialization
93+ // deadlock.
94+ // Oracle JDK 8 JFR controller requires JMX so register an 'after-jmx-initialized' callback.
95+ PROFILER_INIT_AFTER_JMX =
96+ new AgentTaskScheduler .Task <URL >() {
97+ @ Override
98+ public void run (URL target ) {
99+ startProfilingAgent (target , false );
100+ }
101+ };
102+ }
94103 }
95104
96105 /*
@@ -122,17 +131,19 @@ public void run(URL target) {
122131 * JMXFetch until we detect the custom MBeanServerBuilder is being used. This takes precedence over the custom
123132 * log manager check because any custom log manager will be installed before any custom MBeanServerBuilder.
124133 */
125- int jmxStartDelay = getJmxStartDelay ();
126- if (appUsingCustomJMXBuilder ) {
127- log .debug ("Custom JMX builder detected. Delaying JMXFetch initialization." );
128- registerMBeanServerBuilderCallback (new StartJmxCallback (bootstrapURL , jmxStartDelay ));
129- // one minute fail-safe in case nothing touches JMX and and callback isn't triggered
130- scheduleJmxStart (bootstrapURL , 60 + jmxStartDelay );
131- } else if (appUsingCustomLogManager ) {
132- log .debug ("Custom logger detected. Delaying JMXFetch initialization." );
133- registerLogManagerCallback (new StartJmxCallback (bootstrapURL , jmxStartDelay ));
134- } else {
135- scheduleJmxStart (bootstrapURL , jmxStartDelay );
134+ if (jmxFetchEnabled || profilingEnabled ) { // both features use JMX
135+ int jmxStartDelay = getJmxStartDelay ();
136+ if (appUsingCustomJMXBuilder ) {
137+ log .debug ("Custom JMX builder detected. Delaying JMXFetch initialization." );
138+ registerMBeanServerBuilderCallback (new StartJmxCallback (bootstrapURL , jmxStartDelay , true ));
139+ // one minute fail-safe in case nothing touches JMX and and callback isn't triggered
140+ scheduleJmxStart (bootstrapURL , 60 + jmxStartDelay );
141+ } else if (appUsingCustomLogManager ) {
142+ log .debug ("Custom logger detected. Delaying JMXFetch initialization." );
143+ registerLogManagerCallback (new StartJmxCallback (bootstrapURL , jmxStartDelay , false ));
144+ } else {
145+ scheduleJmxStart (bootstrapURL , jmxStartDelay );
146+ }
136147 }
137148
138149 /*
@@ -150,7 +161,7 @@ public void run(URL target) {
150161 /*
151162 * Similar thing happens with Profiler on zulu-8 because it is using OkHttp which indirectly loads JFR events which in turn loads LogManager. This is not a problem on newer JDKs because there JFR uses different logging facility.
152163 */
153- if (!isOracleJDK8 ()) {
164+ if (profilingEnabled && !isOracleJDK8 ()) {
154165 if (!isJavaVersionAtLeast (9 ) && appUsingCustomLogManager ) {
155166 log .debug ("Custom logger detected. Delaying JMXFetch initialization." );
156167 registerLogManagerCallback (new StartProfilingAgentCallback (inst , bootstrapURL ));
@@ -229,10 +240,13 @@ public void run() {
229240
230241 protected static class StartJmxCallback extends ClassLoadCallBack {
231242 private final int jmxStartDelay ;
243+ private final boolean customJmxBuilder ;
232244
233- StartJmxCallback (final URL bootstrapURL , final int jmxStartDelay ) {
245+ StartJmxCallback (
246+ final URL bootstrapURL , final int jmxStartDelay , final boolean customJmxBuilder ) {
234247 super (bootstrapURL );
235248 this .jmxStartDelay = jmxStartDelay ;
249+ this .customJmxBuilder = customJmxBuilder ;
236250 }
237251
238252 @ Override
@@ -242,8 +256,14 @@ public AgentThread agentThread() {
242256
243257 @ Override
244258 public void execute () {
245- // finish building platform JMX from context of custom builder before starting JMXFetch
246- ManagementFactory .getPlatformMBeanServer ();
259+ if (customJmxBuilder ) {
260+ try {
261+ // finish building platform JMX from context of custom builder before starting JMXFetch
262+ ManagementFactory .getPlatformMBeanServer ();
263+ } catch (Throwable e ) {
264+ log .error ("Error loading custom MBeanServerBuilder" , e );
265+ }
266+ }
247267 scheduleJmxStart (bootstrapURL , jmxStartDelay );
248268 }
249269 }
@@ -363,19 +383,23 @@ private static synchronized void startJmx(final URL bootstrapURL) {
363383 if (jmxStarting .getAndSet (true )) {
364384 return ; // another thread is already in startJmx
365385 }
366- startJmxFetch (bootstrapURL );
386+ if (jmxFetchEnabled ) {
387+ startJmxFetch (bootstrapURL );
388+ }
367389 initializeJmxSystemAccessProvider (AGENT_CLASSLOADER );
368- registerDeadlockDetectionEvent (bootstrapURL );
369- if (PROFILER_INIT_AFTER_JMX != null ) {
370- if (getJmxStartDelay () == 0 ) {
371- log .debug ("Waiting for profiler initialization" );
372- AgentTaskScheduler .INSTANCE .scheduleWithJitter (
373- PROFILER_INIT_AFTER_JMX , bootstrapURL , 500 , TimeUnit .MILLISECONDS );
374- } else {
375- log .debug ("Initializing profiler" );
376- PROFILER_INIT_AFTER_JMX .run (bootstrapURL );
390+ if (profilingEnabled ) {
391+ registerDeadlockDetectionEvent (bootstrapURL );
392+ if (PROFILER_INIT_AFTER_JMX != null ) {
393+ if (getJmxStartDelay () == 0 ) {
394+ log .debug ("Waiting for profiler initialization" );
395+ AgentTaskScheduler .INSTANCE .scheduleWithJitter (
396+ PROFILER_INIT_AFTER_JMX , bootstrapURL , 500 , TimeUnit .MILLISECONDS );
397+ } else {
398+ log .debug ("Initializing profiler" );
399+ PROFILER_INIT_AFTER_JMX .run (bootstrapURL );
400+ }
401+ PROFILER_INIT_AFTER_JMX = null ;
377402 }
378- PROFILER_INIT_AFTER_JMX = null ;
379403 }
380404 }
381405
@@ -619,6 +643,28 @@ private static boolean isStartupLogsEnabled() {
619643 return !"false" .equalsIgnoreCase (startupLogsEnabled );
620644 }
621645
646+ /** @return {@code true} if JMXFetch is enabled */
647+ private static boolean isJmxFetchEnabled () {
648+ final String jmxFetchEnabledSysprop = "dd.jmxfetch.enabled" ;
649+ String jmxFetchEnabled = System .getProperty (jmxFetchEnabledSysprop );
650+ if (jmxFetchEnabled == null ) {
651+ jmxFetchEnabled = ddGetEnv (jmxFetchEnabledSysprop );
652+ }
653+ // assume true unless it's explicitly set to "false"
654+ return !"false" .equalsIgnoreCase (jmxFetchEnabled );
655+ }
656+
657+ /** @return {@code true} if profiling is enabled */
658+ private static boolean isProfilingEnabled () {
659+ final String profilingEnabledSysprop = "dd.profiling.enabled" ;
660+ String profilingEnabled = System .getProperty (profilingEnabledSysprop );
661+ if (profilingEnabled == null ) {
662+ profilingEnabled = ddGetEnv (profilingEnabledSysprop );
663+ }
664+ // assume false unless it's explicitly set to "true"
665+ return "true" .equalsIgnoreCase (profilingEnabled );
666+ }
667+
622668 /** @return configured JMX start delay in seconds */
623669 private static int getJmxStartDelay () {
624670 String startDelay = ddGetProperty ("dd.dogstatsd.start-delay" );
0 commit comments