1717
1818import static com .datadog .profiling .controller .ProfilingSupport .*;
1919import static datadog .environment .JavaVirtualMachine .isJavaVersionAtLeast ;
20+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_ALLOC_ENABLED ;
21+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_CPU_ENABLED ;
22+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_EXCEPTION_ENABLED ;
2023import static datadog .trace .api .config .ProfilingConfig .PROFILING_HEAP_HISTOGRAM_ENABLED ;
2124import static datadog .trace .api .config .ProfilingConfig .PROFILING_HEAP_HISTOGRAM_ENABLED_DEFAULT ;
2225import static datadog .trace .api .config .ProfilingConfig .PROFILING_HEAP_HISTOGRAM_MODE ;
2326import static datadog .trace .api .config .ProfilingConfig .PROFILING_HEAP_HISTOGRAM_MODE_DEFAULT ;
27+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_LATENCY_ENABLED ;
28+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_LIVEHEAP_ENABLED ;
29+ import static datadog .trace .api .config .ProfilingConfig .PROFILING_LIVEHEAP_ENABLED_DEFAULT ;
2430import static datadog .trace .api .config .ProfilingConfig .PROFILING_QUEUEING_TIME_ENABLED ;
2531import static datadog .trace .api .config .ProfilingConfig .PROFILING_QUEUEING_TIME_ENABLED_DEFAULT ;
2632import static datadog .trace .api .config .ProfilingConfig .PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS ;
@@ -192,14 +198,101 @@ public OpenJdkController(final ConfigProvider configProvider)
192198
193199 // Toggle settings from config
194200
195- if (configProvider .getBoolean (
196- ProfilingConfig .PROFILING_HEAP_ENABLED , ProfilingConfig .PROFILING_HEAP_ENABLED_DEFAULT )) {
197- log .debug ("Enabling OldObjectSample JFR event with the config." );
198- recordingSettings .put ("jdk.OldObjectSample#enabled" , "true" );
201+ // --- CPU profiling umbrella (profiling.cpu.enabled) ---
202+ Boolean cpuUmbrella = configProvider .getBoolean (PROFILING_CPU_ENABLED );
203+ if (cpuUmbrella != null ) {
204+ if (cpuUmbrella ) {
205+ // Re-enable the correct CPU sampling event for the current JDK
206+ if (JavaVirtualMachine .isJavaVersionAtLeast (25 ) && OperatingSystem .isLinux ()) {
207+ enableEvent (recordingSettings , "jdk.CPUTimeSample" , EXPLICITLY_ENABLED );
208+ enableEvent (recordingSettings , "jdk.CPUTimeSamplesLost" , EXPLICITLY_ENABLED );
209+ } else {
210+ enableEvent (recordingSettings , "jdk.ExecutionSample" , EXPLICITLY_ENABLED );
211+ }
212+ } else {
213+ disableEvent (recordingSettings , "jdk.ExecutionSample" , EXPLICITLY_DISABLED );
214+ disableEvent (recordingSettings , "jdk.CPUTimeSample" , EXPLICITLY_DISABLED );
215+ disableEvent (recordingSettings , "jdk.CPUTimeSamplesLost" , EXPLICITLY_DISABLED );
216+ }
199217 }
200218
201- if (configProvider .getBoolean (
202- ProfilingConfig .PROFILING_ALLOCATION_ENABLED , isObjectAllocationSampleAvailable ())) {
219+ // --- Latency profiling umbrella (profiling.latency.enabled) ---
220+ Boolean latencyUmbrella = configProvider .getBoolean (PROFILING_LATENCY_ENABLED );
221+ if (latencyUmbrella != null ) {
222+ if (latencyUmbrella ) {
223+ enableEvent (recordingSettings , "jdk.JavaMonitorEnter" , EXPLICITLY_ENABLED );
224+ enableEvent (recordingSettings , "jdk.JavaMonitorWait" , EXPLICITLY_ENABLED );
225+ enableEvent (recordingSettings , "jdk.JavaMonitorInflate" , EXPLICITLY_ENABLED );
226+ enableEvent (recordingSettings , "jdk.FileRead" , EXPLICITLY_ENABLED );
227+ if (isFileWriteDurationCorrect ()) {
228+ enableEvent (recordingSettings , "jdk.FileWrite" , EXPLICITLY_ENABLED );
229+ }
230+ enableEvent (recordingSettings , "jdk.SocketRead" , EXPLICITLY_ENABLED );
231+ enableEvent (recordingSettings , "jdk.SocketWrite" , EXPLICITLY_ENABLED );
232+ enableEvent (recordingSettings , "jdk.ThreadStart" , EXPLICITLY_ENABLED );
233+ } else {
234+ disableEvent (recordingSettings , "jdk.JavaMonitorEnter" , EXPLICITLY_DISABLED );
235+ disableEvent (recordingSettings , "jdk.JavaMonitorWait" , EXPLICITLY_DISABLED );
236+ disableEvent (recordingSettings , "jdk.JavaMonitorInflate" , EXPLICITLY_DISABLED );
237+ disableEvent (recordingSettings , "jdk.FileRead" , EXPLICITLY_DISABLED );
238+ disableEvent (recordingSettings , "jdk.FileWrite" , EXPLICITLY_DISABLED );
239+ disableEvent (recordingSettings , "jdk.SocketRead" , EXPLICITLY_DISABLED );
240+ disableEvent (recordingSettings , "jdk.SocketWrite" , EXPLICITLY_DISABLED );
241+ disableEvent (recordingSettings , "jdk.ThreadStart" , EXPLICITLY_DISABLED );
242+ }
243+ }
244+
245+ // --- Live heap profiling (profiling.liveheap.enabled / profiling.heap.enabled) ---
246+ // profiling.heap.enabled (explicit JFR override) takes precedence over umbrella
247+ Boolean heapExplicit = configProvider .getBoolean (ProfilingConfig .PROFILING_HEAP_ENABLED );
248+ if (heapExplicit != null ) {
249+ if (heapExplicit ) {
250+ log .debug ("Enabling OldObjectSample JFR event with the config." );
251+ recordingSettings .put ("jdk.OldObjectSample#enabled" , "true" );
252+ } else {
253+ disableEvent (recordingSettings , "jdk.OldObjectSample" , EXPLICITLY_DISABLED );
254+ }
255+ } else {
256+ // Umbrella defaults to true — all GA features enabled out of the box.
257+ // Use nullable check to distinguish explicit user setting from default.
258+ Boolean liveheapUmbrella = configProvider .getBoolean (PROFILING_LIVEHEAP_ENABLED );
259+ boolean liveheapEnabled =
260+ liveheapUmbrella != null ? liveheapUmbrella : PROFILING_LIVEHEAP_ENABLED_DEFAULT ;
261+ if (liveheapEnabled ) {
262+ // Enable liveheap on the best available backend.
263+ // ddprof handles it when: ddprof is overall active AND liveheap not explicitly disabled.
264+ boolean ddprofLiveheapExplicitlyDisabled =
265+ Boolean .FALSE .equals (
266+ configProvider .getBoolean (
267+ ProfilingConfig .PROFILING_DATADOG_PROFILER_LIVEHEAP_ENABLED ,
268+ ProfilingConfig .PROFILING_DATADOG_PROFILER_MEMLEAK_ENABLED ));
269+ boolean ddprofEnabled =
270+ configProvider .getBoolean (ProfilingConfig .PROFILING_DATADOG_PROFILER_ENABLED , false );
271+ if (ddprofEnabled && !ddprofLiveheapExplicitlyDisabled ) {
272+ // ddprof will handle live heap; suppress JFR OldObjectSample to avoid redundant overhead
273+ disableEvent (
274+ recordingSettings , "jdk.OldObjectSample" , "ddprof backend handles live heap" );
275+ } else if (liveheapUmbrella != null || isOldObjectSampleAvailable ()) {
276+ // Explicit umbrella=true: force-enable OldObjectSample (even on older JDKs).
277+ // Default (umbrella not set): only enable if OldObjectSample is inexpensive.
278+ recordingSettings .put ("jdk.OldObjectSample#enabled" , "true" );
279+ }
280+ } else {
281+ disableEvent (recordingSettings , "jdk.OldObjectSample" , EXPLICITLY_DISABLED );
282+ }
283+ }
284+
285+ // --- Allocation profiling (profiling.alloc.enabled / profiling.allocation.enabled) ---
286+ // Priority: profiling.allocation.enabled (JFR override) > profiling.alloc.enabled (umbrella)
287+ // > default (ObjectAllocationSample availability)
288+ Boolean allocationExplicit =
289+ configProvider .getBoolean (ProfilingConfig .PROFILING_ALLOCATION_ENABLED );
290+ Boolean allocationUmbrella = configProvider .getBoolean (PROFILING_ALLOC_ENABLED );
291+ boolean allocationEnabled =
292+ allocationExplicit != null
293+ ? allocationExplicit
294+ : allocationUmbrella != null ? allocationUmbrella : isObjectAllocationSampleAvailable ();
295+ if (allocationEnabled ) {
203296 // jdk.ObjectAllocationSample is available and enabled by default
204297 if (!isObjectAllocationSampleAvailable ()) {
205298 log .debug (
@@ -215,6 +308,16 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable(
215308 }
216309 }
217310
311+ // --- Exception profiling umbrella (profiling.exception.enabled) ---
312+ Boolean exceptionUmbrella = configProvider .getBoolean (PROFILING_EXCEPTION_ENABLED );
313+ if (exceptionUmbrella != null ) {
314+ if (exceptionUmbrella ) {
315+ enableEvent (recordingSettings , "datadog.ExceptionSample" , EXPLICITLY_ENABLED );
316+ } else {
317+ disableEvent (recordingSettings , "datadog.ExceptionSample" , EXPLICITLY_DISABLED );
318+ }
319+ }
320+
218321 if (configProvider .getBoolean (
219322 ProfilingConfig .PROFILING_SMAP_COLLECTION_ENABLED ,
220323 ProfilingConfig .PROFILING_SMAP_COLLECTION_ENABLED_DEFAULT )) {
0 commit comments