From 0af1b6038a83604f7f2530c122d0c2b57a3ec12a Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 13 Apr 2026 14:02:37 +0200 Subject: [PATCH 1/6] Add unified profiling feature gate config keys Co-Authored-By: Claude Sonnet 4.6 --- .../controller/openjdk/OpenJdkController.java | 54 +++++++++++++++++ .../controller/ProfilerFlareReporter.java | 49 +++++++++++++++ .../controller/ProfilerSettingsSupport.java | 40 +++++++++++++ .../ddprof/DatadogProfilerConfig.java | 10 ++++ .../ByteBufferInstrumentation.java | 13 ++-- .../DirectByteBufferInstrumentation.java | 13 ++-- .../FileChannelImplInstrumentation.java | 13 ++-- .../trace/api/config/ProfilingConfig.java | 37 +++++++++++- metadata/supported-configurations.json | 60 ++++++++++++++++++- 9 files changed, 273 insertions(+), 16 deletions(-) diff --git a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java index e5a625db7a7..12847714ee8 100644 --- a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java +++ b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java @@ -17,15 +17,27 @@ import static com.datadog.profiling.controller.ProfilingSupport.*; import static datadog.environment.JavaVirtualMachine.isJavaVersionAtLeast; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_CPU_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_CPU_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_MODE; import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_HISTOGRAM_MODE_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_IO_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_IO_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_LOCK_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_LOCK_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_QUEUEING_TIME_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_QUEUEING_TIME_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS; import static datadog.trace.api.config.ProfilingConfig.PROFILING_QUEUEING_TIME_THRESHOLD_MILLIS_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_THREAD_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_THREAD_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_ULTRA_MINIMAL; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT; import com.datadog.profiling.controller.ConfigurationException; import com.datadog.profiling.controller.Controller; @@ -264,6 +276,48 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable( "Aggregated smaps collection is disabled in the config"); } + // Feature gates — unified profiling.*.enabled keys + + if (!configProvider.getBoolean(PROFILING_CPU_ENABLED, PROFILING_CPU_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "jdk.ExecutionSample", "CPU profiling is disabled"); + disableEvent(recordingSettings, "jdk.NativeMethodSample", "CPU profiling is disabled"); + disableEvent(recordingSettings, "jdk.CPUTimeSample", "CPU profiling is disabled"); + disableEvent(recordingSettings, "jdk.CPUTimeSamplesLost", "CPU profiling is disabled"); + } + + if (!configProvider.getBoolean(PROFILING_WALL_ENABLED, PROFILING_WALL_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "jdk.JavaMonitorWait", "wall-clock profiling is disabled"); + disableEvent(recordingSettings, "jdk.ThreadPark", "wall-clock profiling is disabled"); + disableEvent(recordingSettings, "jdk.ThreadSleep", "wall-clock profiling is disabled"); + } + + if (!configProvider.getBoolean( + PROFILING_EXCEPTION_ENABLED, PROFILING_EXCEPTION_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "datadog.ExceptionSample", "exception profiling is disabled"); + disableEvent(recordingSettings, "datadog.ExceptionCount", "exception profiling is disabled"); + } + + if (!configProvider.getBoolean(PROFILING_IO_ENABLED, PROFILING_IO_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "jdk.FileRead", "I/O profiling is disabled"); + disableEvent(recordingSettings, "jdk.FileWrite", "I/O profiling is disabled"); + disableEvent(recordingSettings, "jdk.FileForce", "I/O profiling is disabled"); + disableEvent(recordingSettings, "jdk.SocketRead", "I/O profiling is disabled"); + disableEvent(recordingSettings, "jdk.SocketWrite", "I/O profiling is disabled"); + } + + if (!configProvider.getBoolean(PROFILING_LOCK_ENABLED, PROFILING_LOCK_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "jdk.JavaMonitorEnter", "lock profiling is disabled"); + disableEvent(recordingSettings, "jdk.BiasedLockRevocation", "lock profiling is disabled"); + disableEvent(recordingSettings, "jdk.BiasedLockSelfRevocation", "lock profiling is disabled"); + disableEvent( + recordingSettings, "jdk.BiasedLockClassRevocation", "lock profiling is disabled"); + } + + if (!configProvider.getBoolean(PROFILING_THREAD_ENABLED, PROFILING_THREAD_ENABLED_DEFAULT)) { + disableEvent(recordingSettings, "jdk.ThreadStart", "thread profiling is disabled"); + disableEvent(recordingSettings, "jdk.ThreadEnd", "thread profiling is disabled"); + } + // Warn users for expensive events if (!isOldObjectSampleAvailable() && isEventEnabled(recordingSettings, "jdk.OldObjectSample")) { diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java index 95f538a715c..3fbb13a1965 100644 --- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java +++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerFlareReporter.java @@ -136,6 +136,55 @@ private String getProfilerConfig() { .append(proxyPassword != null ? "[REDACTED]" : null) .append(" (default: null)\n"); + sb.append("\n=== Feature Gates ===\n"); + appendConfig( + sb, + "CPU Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_CPU_ENABLED, ProfilingConfig.PROFILING_CPU_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_CPU_ENABLED_DEFAULT); + appendConfig( + sb, + "Wall Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_WALL_ENABLED, ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT); + appendConfig( + sb, + "Exception Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_EXCEPTION_ENABLED, + ProfilingConfig.PROFILING_EXCEPTION_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_EXCEPTION_ENABLED_DEFAULT); + appendConfig( + sb, + "I/O Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_IO_ENABLED, ProfilingConfig.PROFILING_IO_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_IO_ENABLED_DEFAULT); + appendConfig( + sb, + "Lock Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_LOCK_ENABLED, ProfilingConfig.PROFILING_LOCK_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_LOCK_ENABLED_DEFAULT); + appendConfig( + sb, + "Thread Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_THREAD_ENABLED, + ProfilingConfig.PROFILING_THREAD_ENABLED_DEFAULT), + ProfilingConfig.PROFILING_THREAD_ENABLED_DEFAULT); + appendConfig( + sb, + "Direct Memory Profiling Enabled", + configProvider.getBoolean( + ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED, + configProvider.getBoolean( + ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED, + ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)), + ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT); + sb.append("\n=== Allocation Profiling ===\n"); boolean allocDefault = ProfilingSupport.isObjectAllocationSampleAvailable(); boolean allocEnabled = diff --git a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java index a60e6b8f1dc..81660bae4b2 100644 --- a/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java +++ b/dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/ProfilerSettingsSupport.java @@ -94,6 +94,13 @@ public String toString() { protected final String uploadCompression; protected final boolean allocationProfilingEnabled; protected final boolean heapProfilingEnabled; + protected final boolean cpuProfilingEnabled; + protected final boolean wallProfilingEnabled; + protected final boolean exceptionProfilingEnabled; + protected final boolean ioProfilingEnabled; + protected final boolean lockProfilingEnabled; + protected final boolean threadProfilingEnabled; + protected final boolean directMemoryProfilingEnabled; protected final boolean startForceFirst; protected final String templateOverride; protected final int exceptionSampleLimit; @@ -141,6 +148,32 @@ protected ProfilerSettingsSupport( heapProfilingEnabled = configProvider.getBoolean( ProfilingConfig.PROFILING_HEAP_ENABLED, ProfilingSupport.isLiveHeapProfilingSafe()); + cpuProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_CPU_ENABLED, ProfilingConfig.PROFILING_CPU_ENABLED_DEFAULT); + wallProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_WALL_ENABLED, ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT); + exceptionProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_EXCEPTION_ENABLED, + ProfilingConfig.PROFILING_EXCEPTION_ENABLED_DEFAULT); + ioProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_IO_ENABLED, ProfilingConfig.PROFILING_IO_ENABLED_DEFAULT); + lockProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_LOCK_ENABLED, ProfilingConfig.PROFILING_LOCK_ENABLED_DEFAULT); + threadProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_THREAD_ENABLED, + ProfilingConfig.PROFILING_THREAD_ENABLED_DEFAULT); + directMemoryProfilingEnabled = + configProvider.getBoolean( + ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED, + configProvider.getBoolean( + ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED, + ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); startForceFirst = configProvider.getBoolean( ProfilingConfig.PROFILING_START_FORCE_FIRST, @@ -293,6 +326,13 @@ public String toString() { + ", uploadCompression='" + uploadCompression + '\'' + ", allocationProfilingEnabled=" + allocationProfilingEnabled + ", heapProfilingEnabled=" + heapProfilingEnabled + + ", cpuProfilingEnabled=" + cpuProfilingEnabled + + ", wallProfilingEnabled=" + wallProfilingEnabled + + ", exceptionProfilingEnabled=" + exceptionProfilingEnabled + + ", ioProfilingEnabled=" + ioProfilingEnabled + + ", lockProfilingEnabled=" + lockProfilingEnabled + + ", threadProfilingEnabled=" + threadProfilingEnabled + + ", directMemoryProfilingEnabled=" + directMemoryProfilingEnabled + ", startForceFirst=" + startForceFirst + ", templateOverride='" + templateOverride + '\'' + ", exceptionSampleLimit=" + exceptionSampleLimit diff --git a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java index 60c0d5c2e60..2d0715f6221 100644 --- a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java +++ b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java @@ -6,6 +6,8 @@ import static datadog.trace.api.config.ProfilingConfig.PROFILING_CONTEXT_ATTRIBUTES; import static datadog.trace.api.config.ProfilingConfig.PROFILING_CONTEXT_ATTRIBUTES_RESOURCE_NAME_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_CONTEXT_ATTRIBUTES_SPAN_NAME_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_CPU_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_CPU_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ALLOC_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ALLOC_INTERVAL_DEFAULT; @@ -51,6 +53,8 @@ import static datadog.trace.api.config.ProfilingConfig.PROFILING_STACKDEPTH; import static datadog.trace.api.config.ProfilingConfig.PROFILING_STACKDEPTH_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_ULTRA_MINIMAL; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT; import static datadog.trace.api.config.TraceInstrumentationConfig.TRACE_ENABLED; import com.datadog.profiling.controller.ProfilingSupport; @@ -67,6 +71,9 @@ public class DatadogProfilerConfig { private static final Logger log = LoggerFactory.getLogger(DatadogProfilerConfig.class); public static boolean isCpuProfilerEnabled(ConfigProvider configProvider) { + if (!configProvider.getBoolean(PROFILING_CPU_ENABLED, PROFILING_CPU_ENABLED_DEFAULT)) { + return false; + } return getBoolean( configProvider, PROFILING_DATADOG_PROFILER_CPU_ENABLED, @@ -117,6 +124,9 @@ public static boolean isWallClockProfilerEnabled() { } public static boolean isWallClockProfilerEnabled(ConfigProvider configProvider) { + if (!configProvider.getBoolean(PROFILING_WALL_ENABLED, PROFILING_WALL_ENABLED_DEFAULT)) { + return false; + } boolean isUltraMinimal = getBoolean(configProvider, PROFILING_ULTRA_MINIMAL, false); boolean isTracingEnabled = configProvider.getBoolean(TRACE_ENABLED, true); boolean disableUnlessOptedIn = isUltraMinimal || !isTracingEnabled || isJ9(); diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java index db2f3a6f1fd..70382b38b3d 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java @@ -2,7 +2,8 @@ import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -25,11 +26,15 @@ public ByteBufferInstrumentation() { @Override public boolean isEnabled() { + ConfigProvider cp = ConfigProvider.getInstance(); + boolean enabled = + cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + cp.getBoolean( + PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && ConfigProvider.getInstance() - .getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT) + && enabled && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java index 3c3d8417d8b..f1f91b7fd77 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java @@ -1,7 +1,8 @@ package datadog.trace.instrumentation.directbytebuffer; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -23,11 +24,15 @@ public DirectByteBufferInstrumentation() { @Override public boolean isEnabled() { + ConfigProvider cp = ConfigProvider.getInstance(); + boolean enabled = + cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + cp.getBoolean( + PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && ConfigProvider.getInstance() - .getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT) + && enabled && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java index 0fac441bef8..d6805c945d8 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java @@ -2,7 +2,8 @@ import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -24,11 +25,15 @@ public FileChannelImplInstrumentation() { @Override public boolean isEnabled() { + ConfigProvider cp = ConfigProvider.getInstance(); + boolean enabled = + cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + cp.getBoolean( + PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && ConfigProvider.getInstance() - .getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT) + && enabled && Platform.hasJfr(); } diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java index c90ec39888e..156cdfb4909 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java @@ -10,8 +10,36 @@ public final class ProfilingConfig { public static final String PROFILING_ENABLED = "profiling.enabled"; public static final boolean PROFILING_ENABLED_DEFAULT = false; public static final String PROFILING_ALLOCATION_ENABLED = "profiling.allocation.enabled"; + public static final boolean PROFILING_ALLOCATION_ENABLED_DEFAULT = true; public static final String PROFILING_HEAP_ENABLED = "profiling.heap.enabled"; - public static final boolean PROFILING_HEAP_ENABLED_DEFAULT = false; + + /** + * @deprecated The default is now computed dynamically based on JVM capabilities. + */ + @Deprecated public static final boolean PROFILING_HEAP_ENABLED_DEFAULT = false; + + public static final String PROFILING_CPU_ENABLED = "profiling.cpu.enabled"; + public static final boolean PROFILING_CPU_ENABLED_DEFAULT = true; + public static final String PROFILING_WALL_ENABLED = "profiling.wall.enabled"; + public static final boolean PROFILING_WALL_ENABLED_DEFAULT = true; + public static final String PROFILING_EXCEPTION_ENABLED = "profiling.exception.enabled"; + public static final boolean PROFILING_EXCEPTION_ENABLED_DEFAULT = true; + public static final String PROFILING_IO_ENABLED = "profiling.io.enabled"; + public static final boolean PROFILING_IO_ENABLED_DEFAULT = true; + public static final String PROFILING_LOCK_ENABLED = "profiling.lock.enabled"; + public static final boolean PROFILING_LOCK_ENABLED_DEFAULT = true; + public static final String PROFILING_THREAD_ENABLED = "profiling.thread.enabled"; + public static final boolean PROFILING_THREAD_ENABLED_DEFAULT = true; + + /** + * Unified gate for direct memory (native ByteBuffer / FileChannel) profiling. + * + * @see #PROFILING_DIRECT_ALLOCATION_ENABLED + */ + public static final String PROFILING_DIRECT_MEMORY_ENABLED = "profiling.direct.memory.enabled"; + + public static final boolean PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT = false; + @Deprecated // Use dd.site instead public static final String PROFILING_URL = "profiling.url"; @Deprecated // Use dd.api-key instead @@ -79,9 +107,14 @@ public final class ProfilingConfig { public static final String PROFILING_DATADOG_PROFILER_ENABLED = "profiling.ddprof.enabled"; + /** + * @deprecated Use {@link #PROFILING_DIRECT_MEMORY_ENABLED} instead. + */ + @Deprecated public static final String PROFILING_DIRECT_ALLOCATION_ENABLED = "profiling.directallocation.enabled"; - public static final boolean PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT = false; + + @Deprecated public static final boolean PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT = false; public static final String PROFILING_STACKDEPTH = "profiling.stackdepth"; public static final int PROFILING_STACKDEPTH_DEFAULT = 512; diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index ac7935039e3..a8af02ccbd0 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -2461,7 +2461,7 @@ { "version": "A", "type": "boolean", - "default": "false", + "default": "true", "aliases": ["DD_PROFILING_DDPROF_ALLOC_ENABLED"] } ], @@ -2673,6 +2673,14 @@ "aliases": [] } ], + "DD_PROFILING_CPU_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROFILING_DDPROF_ALLOC_ENABLED": [ { "version": "A", @@ -2913,6 +2921,14 @@ "aliases": [] } ], + "DD_PROFILING_DIRECT_MEMORY_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "false", + "aliases": ["DD_PROFILING_DIRECTALLOCATION_ENABLED"] + } + ], "DD_PROFILING_DISABLED_EVENTS": [ { "version": "A", @@ -2945,6 +2961,14 @@ "aliases": [] } ], + "DD_PROFILING_EXCEPTION_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROFILING_EXCEPTION_HISTOGRAM_MAX_COLLECTION_SIZE": [ { "version": "A", @@ -3045,7 +3069,7 @@ { "version": "A", "type": "boolean", - "default": "false", + "default": "true", "aliases": [] } ], @@ -3081,6 +3105,14 @@ "aliases": [] } ], + "DD_PROFILING_IO_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROFILING_JFR_REPOSITORY_BASE": [ { "version": "A", @@ -3105,6 +3137,14 @@ "aliases": [] } ], + "DD_PROFILING_LOCK_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROFILING_PROXY_HOST": [ { "version": "A", @@ -3233,6 +3273,14 @@ "aliases": [] } ], + "DD_PROFILING_THREAD_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROFILING_TIMELINE_EVENTS_ENABLED": [ { "version": "A", @@ -3289,6 +3337,14 @@ "aliases": [] } ], + "DD_PROFILING_WALL_ENABLED": [ + { + "version": "A", + "type": "boolean", + "default": "true", + "aliases": [] + } + ], "DD_PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED": [ { "version": "A", From ccd799b7971ae06a7b6179bad3c8db779404192a Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 13 Apr 2026 16:41:19 +0200 Subject: [PATCH 2/6] Address muse review findings for PROF-10633 unified config gates - Deprecate misleading PROFILING_ALLOCATION_ENABLED_DEFAULT constant - Update PROFILING_HEAP_ENABLED_DEFAULT javadoc to explain dynamic default - Fix PROFILING_DIRECT_ALLOCATION_ENABLED missing @deprecated javadoc - Drop JavaMonitorWait/ThreadPark/ThreadSleep from wall gate (timeline events) - Add startup-only/no-RC comment to feature gate block in OpenJdkController - Add BiasedLock noop comment for JDK 18+ awareness - Add lock sampler note to DatadogProfilerConfig - Extract DirectMemoryProfilingHelper shared utility - Add gate tests: CPU, exception, I/O, lock, thread, wall-timeline - Set metadata defaults to false (safe fallback for dynamic defaults) Co-Authored-By: Claude Sonnet 4.6 --- .../controller/openjdk/OpenJdkController.java | 16 +-- .../openjdk/OpenJdkControllerTest.java | 123 ++++++++++++++++++ .../ddprof/DatadogProfilerConfig.java | 5 + .../ByteBufferInstrumentation.java | 10 +- .../DirectByteBufferInstrumentation.java | 10 +- .../DirectMemoryProfilingHelper.java | 19 +++ .../FileChannelImplInstrumentation.java | 10 +- .../trace/api/config/ProfilingConfig.java | 15 ++- metadata/supported-configurations.json | 4 +- 9 files changed, 170 insertions(+), 42 deletions(-) create mode 100644 dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java diff --git a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java index 12847714ee8..fe2292b9cfb 100644 --- a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java +++ b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/OpenJdkController.java @@ -36,8 +36,6 @@ import static datadog.trace.api.config.ProfilingConfig.PROFILING_THREAD_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_THREAD_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_ULTRA_MINIMAL; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED_DEFAULT; import com.datadog.profiling.controller.ConfigurationException; import com.datadog.profiling.controller.Controller; @@ -276,7 +274,9 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable( "Aggregated smaps collection is disabled in the config"); } - // Feature gates — unified profiling.*.enabled keys + // Feature gates — unified profiling.*.enabled keys. + // These gates are evaluated at recording creation time only; profiling does not use Remote + // Config, so events disabled here remain disabled for the lifetime of the recording. if (!configProvider.getBoolean(PROFILING_CPU_ENABLED, PROFILING_CPU_ENABLED_DEFAULT)) { disableEvent(recordingSettings, "jdk.ExecutionSample", "CPU profiling is disabled"); @@ -285,11 +285,9 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable( disableEvent(recordingSettings, "jdk.CPUTimeSamplesLost", "CPU profiling is disabled"); } - if (!configProvider.getBoolean(PROFILING_WALL_ENABLED, PROFILING_WALL_ENABLED_DEFAULT)) { - disableEvent(recordingSettings, "jdk.JavaMonitorWait", "wall-clock profiling is disabled"); - disableEvent(recordingSettings, "jdk.ThreadPark", "wall-clock profiling is disabled"); - disableEvent(recordingSettings, "jdk.ThreadSleep", "wall-clock profiling is disabled"); - } + // jdk.JavaMonitorWait, jdk.ThreadPark, and jdk.ThreadSleep are intentionally NOT gated by + // PROFILING_WALL_ENABLED: they serve purposes beyond wall-clock profile construction + // (timeline blocking events, queueing time) and must remain enabled independently. if (!configProvider.getBoolean( PROFILING_EXCEPTION_ENABLED, PROFILING_EXCEPTION_ENABLED_DEFAULT)) { @@ -307,6 +305,8 @@ ProfilingConfig.PROFILING_ALLOCATION_ENABLED, isObjectAllocationSampleAvailable( if (!configProvider.getBoolean(PROFILING_LOCK_ENABLED, PROFILING_LOCK_ENABLED_DEFAULT)) { disableEvent(recordingSettings, "jdk.JavaMonitorEnter", "lock profiling is disabled"); + // BiasedLock events are no-ops on JDK 18+ (biased locking removed via JEP 374); disabling + // them here is harmless on modern JDKs. disableEvent(recordingSettings, "jdk.BiasedLockRevocation", "lock profiling is disabled"); disableEvent(recordingSettings, "jdk.BiasedLockSelfRevocation", "lock profiling is disabled"); disableEvent( diff --git a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java index ef853d07b9a..544b2011b46 100644 --- a/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java +++ b/dd-java-agent/agent-profiling/profiling-controller-openjdk/src/test/java/com/datadog/profiling/controller/openjdk/OpenJdkControllerTest.java @@ -6,9 +6,15 @@ import static datadog.trace.api.config.ProfilingConfig.PROFILING_ALLOCATION_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_AUXILIARY_TYPE; import static datadog.trace.api.config.ProfilingConfig.PROFILING_AUXILIARY_TYPE_DEFAULT; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_CPU_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DATADOG_PROFILER_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_EXCEPTION_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_HEAP_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_IO_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_LOCK_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_TEMPLATE_OVERRIDE_FILE; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_THREAD_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_WALL_ENABLED; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -276,6 +282,123 @@ public void testUnifiedFlagDisabledTurnsOffOldObjectSample() throws Exception { } } + @Test + public void testCpuGateDisablesCpuEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_CPU_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.ExecutionSample#enabled")), + "ExecutionSample must be disabled when CPU profiling is disabled"); + } + } + + @Test + public void testExceptionGateDisablesExceptionEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_EXCEPTION_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("datadog.ExceptionSample#enabled")), + "ExceptionSample must be disabled when exception profiling is disabled"); + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("datadog.ExceptionCount#enabled")), + "ExceptionCount must be disabled when exception profiling is disabled"); + } + } + + @Test + public void testIoGateDisablesIoEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_IO_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.FileRead#enabled")), + "FileRead must be disabled when I/O profiling is disabled"); + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.SocketRead#enabled")), + "SocketRead must be disabled when I/O profiling is disabled"); + } + } + + @Test + public void testLockGateDisablesLockEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_LOCK_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.JavaMonitorEnter#enabled")), + "JavaMonitorEnter must be disabled when lock profiling is disabled"); + } + } + + @Test + public void testThreadGateDisablesThreadEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_THREAD_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.ThreadStart#enabled")), + "ThreadStart must be disabled when thread profiling is disabled"); + assertFalse( + Boolean.parseBoolean(recording.getSettings().get("jdk.ThreadEnd#enabled")), + "ThreadEnd must be disabled when thread profiling is disabled"); + } + } + + @Test + public void testWallGateDoesNotDisableTimelineEvents() throws Exception { + Properties props = getConfigProperties(); + props.put(PROFILING_WALL_ENABLED, "false"); + + ConfigProvider configProvider = ConfigProvider.withPropertiesOverride(props); + OpenJdkController controller = new OpenJdkController(configProvider); + try (final Recording recording = + ((OpenJdkRecordingData) + controller.createRecording(TEST_NAME, new ControllerContext().snapshot()).stop()) + .getRecording()) { + // JavaMonitorWait and ThreadPark serve timeline purposes beyond wall-clock profiling and must + // NOT be disabled when only wall profiling is disabled. (ThreadSleep is disabled by the + // dd.jfp template by default and is therefore not checked here.) + assertTrue( + Boolean.parseBoolean(recording.getSettings().get("jdk.JavaMonitorWait#enabled")), + "JavaMonitorWait must remain enabled when only wall profiling is disabled"); + assertTrue( + Boolean.parseBoolean(recording.getSettings().get("jdk.ThreadPark#enabled")), + "ThreadPark must remain enabled when only wall profiling is disabled"); + } + } + private static Properties getConfigProperties() { Properties props = new Properties(); // make sure the async profiler is not force-enabled diff --git a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java index 2d0715f6221..cd36591eb69 100644 --- a/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java +++ b/dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilerConfig.java @@ -252,6 +252,11 @@ public static boolean isMemoryLeakProfilingEnabled() { return isMemoryLeakProfilingEnabled(ConfigProvider.getInstance()); } + // Note: ddprof does not currently implement a native lock sampler. The unified gate + // dd.profiling.lock.enabled (PROFILING_LOCK_ENABLED) is honored by the JFR controller + // for jdk.JavaMonitorEnter. If a ddprof-based lock profiler is added in the future, + // it should check PROFILING_LOCK_ENABLED here. + public static boolean isLiveHeapSizeTrackingEnabled(ConfigProvider configProvider) { return getBoolean( configProvider, diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java index 70382b38b3d..9fb904bb7ff 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java @@ -1,9 +1,6 @@ package datadog.trace.instrumentation.directbytebuffer; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -27,14 +24,9 @@ public ByteBufferInstrumentation() { @Override public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); - boolean enabled = - cp.getBoolean( - PROFILING_DIRECT_MEMORY_ENABLED, - cp.getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && enabled + && DirectMemoryProfilingHelper.isEnabled(cp) && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java index f1f91b7fd77..bae643eaf64 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java @@ -1,8 +1,5 @@ package datadog.trace.instrumentation.directbytebuffer; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -25,14 +22,9 @@ public DirectByteBufferInstrumentation() { @Override public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); - boolean enabled = - cp.getBoolean( - PROFILING_DIRECT_MEMORY_ENABLED, - cp.getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && enabled + && DirectMemoryProfilingHelper.isEnabled(cp) && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java new file mode 100644 index 00000000000..44e67276f42 --- /dev/null +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java @@ -0,0 +1,19 @@ +package datadog.trace.instrumentation.directbytebuffer; + +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; + +import datadog.trace.bootstrap.config.provider.ConfigProvider; + +final class DirectMemoryProfilingHelper { + + static boolean isEnabled(ConfigProvider cp) { + return cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + cp.getBoolean( + PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); + } + + private DirectMemoryProfilingHelper() {} +} diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java index d6805c945d8..839f2d8eae2 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java @@ -1,9 +1,6 @@ package datadog.trace.instrumentation.directbytebuffer; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -26,14 +23,9 @@ public FileChannelImplInstrumentation() { @Override public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); - boolean enabled = - cp.getBoolean( - PROFILING_DIRECT_MEMORY_ENABLED, - cp.getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && enabled + && DirectMemoryProfilingHelper.isEnabled(cp) && Platform.hasJfr(); } diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java index 156cdfb4909..1b5336865c1 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java @@ -10,11 +10,17 @@ public final class ProfilingConfig { public static final String PROFILING_ENABLED = "profiling.enabled"; public static final boolean PROFILING_ENABLED_DEFAULT = false; public static final String PROFILING_ALLOCATION_ENABLED = "profiling.allocation.enabled"; - public static final boolean PROFILING_ALLOCATION_ENABLED_DEFAULT = true; + + /** + * @deprecated Not used. The actual default is computed dynamically by {@link + * datadog.trace.api.profiling.ProfilingSupport#isObjectAllocationSampleAvailable()}. + */ + @Deprecated public static final boolean PROFILING_ALLOCATION_ENABLED_DEFAULT = true; public static final String PROFILING_HEAP_ENABLED = "profiling.heap.enabled"; /** - * @deprecated The default is now computed dynamically based on JVM capabilities. + * @deprecated The old value was {@code false}. The default is now computed dynamically via + * {@link datadog.trace.api.profiling.ProfilingSupport#isLiveHeapProfilingSafe()}. */ @Deprecated public static final boolean PROFILING_HEAP_ENABLED_DEFAULT = false; @@ -32,9 +38,8 @@ public final class ProfilingConfig { public static final boolean PROFILING_THREAD_ENABLED_DEFAULT = true; /** - * Unified gate for direct memory (native ByteBuffer / FileChannel) profiling. - * - * @see #PROFILING_DIRECT_ALLOCATION_ENABLED + * Unified gate for direct memory (native ByteBuffer / FileChannel) profiling. Replaces the + * deprecated {@link #PROFILING_DIRECT_ALLOCATION_ENABLED}. */ public static final String PROFILING_DIRECT_MEMORY_ENABLED = "profiling.direct.memory.enabled"; diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index a8af02ccbd0..619f24eddac 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -2461,7 +2461,7 @@ { "version": "A", "type": "boolean", - "default": "true", + "default": "false", "aliases": ["DD_PROFILING_DDPROF_ALLOC_ENABLED"] } ], @@ -3069,7 +3069,7 @@ { "version": "A", "type": "boolean", - "default": "true", + "default": "false", "aliases": [] } ], From d19b09bc1c43f2888d2437260aa125099c3b9ae5 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 13 Apr 2026 17:01:37 +0200 Subject: [PATCH 3/6] Spotless! --- .../main/java/datadog/trace/api/config/ProfilingConfig.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java index 1b5336865c1..e8989d4e057 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java @@ -16,11 +16,12 @@ public final class ProfilingConfig { * datadog.trace.api.profiling.ProfilingSupport#isObjectAllocationSampleAvailable()}. */ @Deprecated public static final boolean PROFILING_ALLOCATION_ENABLED_DEFAULT = true; + public static final String PROFILING_HEAP_ENABLED = "profiling.heap.enabled"; /** - * @deprecated The old value was {@code false}. The default is now computed dynamically via - * {@link datadog.trace.api.profiling.ProfilingSupport#isLiveHeapProfilingSafe()}. + * @deprecated The old value was {@code false}. The default is now computed dynamically via {@link + * datadog.trace.api.profiling.ProfilingSupport#isLiveHeapProfilingSafe()}. */ @Deprecated public static final boolean PROFILING_HEAP_ENABLED_DEFAULT = false; From 87efa870a1a61c4f543623d38803ce85a3015a04 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 13 Apr 2026 19:41:18 +0200 Subject: [PATCH 4/6] Rename DD_PROFILING_WALL_ENABLED to DD_PROFILING_WALLTIME_ENABLED --- .../src/main/java/datadog/trace/api/config/ProfilingConfig.java | 2 +- metadata/supported-configurations.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java index e8989d4e057..7e43cb4bdc1 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/ProfilingConfig.java @@ -27,7 +27,7 @@ public final class ProfilingConfig { public static final String PROFILING_CPU_ENABLED = "profiling.cpu.enabled"; public static final boolean PROFILING_CPU_ENABLED_DEFAULT = true; - public static final String PROFILING_WALL_ENABLED = "profiling.wall.enabled"; + public static final String PROFILING_WALL_ENABLED = "profiling.walltime.enabled"; public static final boolean PROFILING_WALL_ENABLED_DEFAULT = true; public static final String PROFILING_EXCEPTION_ENABLED = "profiling.exception.enabled"; public static final boolean PROFILING_EXCEPTION_ENABLED_DEFAULT = true; diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 619f24eddac..5e900374a9b 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -3337,7 +3337,7 @@ "aliases": [] } ], - "DD_PROFILING_WALL_ENABLED": [ + "DD_PROFILING_WALLTIME_ENABLED": [ { "version": "A", "type": "boolean", From b8c0c1a6f8b00441285799052bde882e8041bb57 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 13 Apr 2026 19:59:22 +0200 Subject: [PATCH 5/6] Fix direct memory key order in supported-configurations.json to match FPD --- metadata/supported-configurations.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 5e900374a9b..d6071fad144 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -2921,12 +2921,12 @@ "aliases": [] } ], - "DD_PROFILING_DIRECT_MEMORY_ENABLED": [ + "DD_PROFILING_DIRECTALLOCATION_ENABLED": [ { "version": "A", "type": "boolean", "default": "false", - "aliases": ["DD_PROFILING_DIRECTALLOCATION_ENABLED"] + "aliases": ["DD_PROFILING_DIRECT_MEMORY_ENABLED"] } ], "DD_PROFILING_DISABLED_EVENTS": [ From 8c097167db0f5e5a7facbc4f595e8c38b146dd13 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 14 Apr 2026 13:14:54 +0200 Subject: [PATCH 6/6] Inline direct memory config check; drop DirectMemoryProfilingHelper Co-Authored-By: Claude Sonnet 4.6 --- .../ByteBufferInstrumentation.java | 8 +++++++- .../DirectByteBufferInstrumentation.java | 8 +++++++- .../DirectMemoryProfilingHelper.java | 19 ------------------- .../FileChannelImplInstrumentation.java | 8 +++++++- 4 files changed, 21 insertions(+), 22 deletions(-) delete mode 100644 dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java index 9fb904bb7ff..9b44f13e4a3 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/ByteBufferInstrumentation.java @@ -1,6 +1,9 @@ package datadog.trace.instrumentation.directbytebuffer; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -26,7 +29,10 @@ public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && DirectMemoryProfilingHelper.isEnabled(cp) + && cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT, + PROFILING_DIRECT_ALLOCATION_ENABLED) && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java index bae643eaf64..c85ec9d6cfa 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectByteBufferInstrumentation.java @@ -1,5 +1,8 @@ package datadog.trace.instrumentation.directbytebuffer; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -24,7 +27,10 @@ public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && DirectMemoryProfilingHelper.isEnabled(cp) + && cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT, + PROFILING_DIRECT_ALLOCATION_ENABLED) && Platform.hasJfr(); } diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java deleted file mode 100644 index 44e67276f42..00000000000 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/DirectMemoryProfilingHelper.java +++ /dev/null @@ -1,19 +0,0 @@ -package datadog.trace.instrumentation.directbytebuffer; - -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; -import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; - -import datadog.trace.bootstrap.config.provider.ConfigProvider; - -final class DirectMemoryProfilingHelper { - - static boolean isEnabled(ConfigProvider cp) { - return cp.getBoolean( - PROFILING_DIRECT_MEMORY_ENABLED, - cp.getBoolean( - PROFILING_DIRECT_ALLOCATION_ENABLED, PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT)); - } - - private DirectMemoryProfilingHelper() {} -} diff --git a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java index 839f2d8eae2..9bbf099014a 100644 --- a/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-nio-1.8/src/main/java/datadog/trace/instrumentation/directbytebuffer/FileChannelImplInstrumentation.java @@ -1,6 +1,9 @@ package datadog.trace.instrumentation.directbytebuffer; import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED; +import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; @@ -25,7 +28,10 @@ public boolean isEnabled() { ConfigProvider cp = ConfigProvider.getInstance(); return JavaVirtualMachine.isJavaVersionAtLeast(11) && super.isEnabled() - && DirectMemoryProfilingHelper.isEnabled(cp) + && cp.getBoolean( + PROFILING_DIRECT_MEMORY_ENABLED, + PROFILING_DIRECT_MEMORY_ENABLED_DEFAULT, + PROFILING_DIRECT_ALLOCATION_ENABLED) && Platform.hasJfr(); }