Skip to content

Add JDK built-in support for UDS on Java 16+ #8314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ec126c8
Use the JDK's built-in support for Unix Domain Sockets on Java 16+
mcculls Jan 14, 2025
87425f1
First draft of timeout test.
sarahchen6 Jan 29, 2025
1634bcd
Add server to test.
sarahchen6 Jan 30, 2025
683e7c1
Fix build.gradle file.
sarahchen6 Jan 31, 2025
662602a
Add debugging statements.
sarahchen6 Jan 31, 2025
64da205
Second draft of timeout test.
sarahchen6 Jan 31, 2025
953f3e8
Update getInputStream to use a selector.
sarahchen6 Feb 6, 2025
d07fc19
Clean code.
sarahchen6 Feb 6, 2025
2aec0e7
Adjust dd-java-agent build.gradle.
sarahchen6 Feb 10, 2025
ea9a237
Revert dd-java-agent build.gradle change
mcculls Feb 12, 2025
e475abd
Revert another build.gradle change.
sarahchen6 Feb 18, 2025
38b98db
Try specifying setSrcDirs.
sarahchen6 Feb 18, 2025
5ae79f9
Try changing compatibility version.
sarahchen6 Feb 18, 2025
e80ce7e
Revert previous two changes.
sarahchen6 Feb 18, 2025
6c188d9
Avoid implementation dependency for Java17.
sarahchen6 Feb 20, 2025
dda0997
Make gradle dependency more specific and add testImplementation to so…
sarahchen6 Feb 20, 2025
412e4d3
Add synchronization to ensure that server starts before client connects.
sarahchen6 Feb 20, 2025
381f841
Try this...
sarahchen6 Feb 27, 2025
beba316
Add print statements.
sarahchen6 Mar 4, 2025
305d9af
Add catch statement.
sarahchen6 Mar 4, 2025
8ff0eab
Refactor getInputStream and getOutputStream.
sarahchen6 Mar 5, 2025
0251e37
Address PR comments.
sarahchen6 Mar 11, 2025
114d230
Add test for when timeout is 0.
sarahchen6 Mar 11, 2025
37ca729
Add config option.
sarahchen6 Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public final class GeneralConfig {
public static final String AGENTLESS_LOG_SUBMISSION_LEVEL = "agentless.log.submission.level";
public static final String AGENTLESS_LOG_SUBMISSION_URL = "agentless.log.submission.url";
public static final String APM_TRACING_ENABLED = "apm.tracing.enabled";
public static final String JDK_SOCKET_ENABLED = "jdk.socket.enabled";

private GeneralConfig() {}
}
10 changes: 8 additions & 2 deletions gradle/java_no_deps.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ if (project.hasProperty('minJavaVersionForTests') && project.getProperty('minJav
targetCompatibility = version
}

// "socket-utils" is only set to compileOnly because the implementation dependency incorrectly adds Java17 classes to all jar prefixes.
// This causes the AgentJarIndex to search for other non-Java17 classes in the wrong prefix location and fail to resolve class names.
dependencies {
compileOnly files(project.sourceSets."main_$name".compileClasspath)
implementation files(project.sourceSets."main_$name".output)
if ("${project.projectDir}".endsWith("socket-utils")) {
compileOnly files(project.sourceSets."main_$name".output)
} else {
compileOnly files(project.sourceSets."main_$name".compileClasspath)
implementation files(project.sourceSets."main_$name".output)
}
}

jar {
Expand Down
10 changes: 10 additions & 0 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,8 @@ public static String getHostName() {

private final boolean apmTracingEnabled;

private final boolean jdkSocketEnabled;

// Read order: System Properties -> Env Variables, [-> properties file], [-> default value]
private Config() {
this(ConfigProvider.createDefault());
Expand Down Expand Up @@ -1924,6 +1926,8 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())

this.apmTracingEnabled = configProvider.getBoolean(GeneralConfig.APM_TRACING_ENABLED, true);

this.jdkSocketEnabled = configProvider.getBoolean(JDK_SOCKET_ENABLED, true);

log.debug("New instance: {}", this);
}

Expand Down Expand Up @@ -3466,6 +3470,10 @@ public boolean isApmTracingEnabled() {
return apmTracingEnabled;
}

public boolean isJdkSocketEnabled() {
return jdkSocketEnabled;
}

/** @return A map of tags to be applied only to the local application root span. */
public Map<String, Object> getLocalRootSpanTags() {
final Map<String, String> runtimeTags = getRuntimeTags();
Expand Down Expand Up @@ -4703,6 +4711,8 @@ public String toString() {
+ dataJobsCommandPattern
+ ", apmTracingEnabled="
+ apmTracingEnabled
+ ", jdkSocketEnabled="
+ jdkSocketEnabled
+ ", cloudRequestPayloadTagging="
+ cloudRequestPayloadTagging
+ ", cloudResponsePayloadTagging="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS
import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED
import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST
import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT
import static datadog.trace.api.config.GeneralConfig.JDK_SOCKET_ENABLED
import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED
import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME
import static datadog.trace.api.config.GeneralConfig.SITE
Expand Down Expand Up @@ -257,6 +258,7 @@ class ConfigTest extends DDSpecification {
prop.setProperty(DYNAMIC_INSTRUMENTATION_EXCLUDE_FILES, "exclude file")
prop.setProperty(EXCEPTION_REPLAY_ENABLED, "true")
prop.setProperty(TRACE_X_DATADOG_TAGS_MAX_LENGTH, "128")
prop.setProperty(JDK_SOCKET_ENABLED, "false")

when:
Config config = Config.get(prop)
Expand Down Expand Up @@ -348,6 +350,7 @@ class ConfigTest extends DDSpecification {
config.dynamicInstrumentationInstrumentTheWorld == true
config.dynamicInstrumentationExcludeFiles == "exclude file"
config.debuggerExceptionEnabled == true
config.jdkSocketEnabled == false

config.xDatadogTagsMaxLength == 128
}
Expand Down
25 changes: 24 additions & 1 deletion utils/socket-utils/build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
ext {
minJavaVersionForTests = JavaVersion.VERSION_17
}

apply from: "$rootDir/gradle/java.gradle"
apply plugin: "idea"

[compileMain_java17Java, compileTestJava].each {
it.configure {
setJavaVersion(it, 17)
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}

dependencies {
implementation libs.slf4j
implementation project(':internal-api')
implementation libs.jnr.unixsocket
testImplementation files(sourceSets.main_java17.output)
}

forbiddenApisMain_java17 {
failOnMissingClasses = false
}

implementation group: 'com.github.jnr', name: 'jnr-unixsocket', version: libs.versions.jnr.unixsocket.get()
idea {
module {
jdkName = '17'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.concurrent.TimeUnit.MINUTES;

import datadog.trace.api.Config;
import datadog.trace.api.Platform;
import datadog.trace.relocate.api.RatelimitedLogger;
import java.io.File;
import java.io.IOException;
Expand All @@ -24,6 +25,8 @@
public final class UnixDomainSocketFactory extends SocketFactory {
private static final Logger log = LoggerFactory.getLogger(UnixDomainSocketFactory.class);

private static final boolean JDK_SUPPORTS_UDS = Platform.isJavaVersionAtLeast(16);

private final RatelimitedLogger rlLog = new RatelimitedLogger(log, 5, MINUTES);

private final File path;
Expand All @@ -35,8 +38,14 @@ public UnixDomainSocketFactory(final File path) {
@Override
public Socket createSocket() throws IOException {
try {
final UnixSocketChannel channel = UnixSocketChannel.open();
return new TunnelingUnixSocket(path, channel);
if (JDK_SUPPORTS_UDS && Config.get().isJdkSocketEnabled()) {
try {
return new TunnelingJdkSocket(path.toPath());
} catch (Throwable ignore) {
// fall back to jnr-unixsocket library
}
}
return new TunnelingUnixSocket(path, UnixSocketChannel.open());
} catch (Throwable e) {
if (Config.get().isAgentConfiguredUsingDefault()) {
// fall back to port if we previously auto-discovered this socket file
Expand Down
Loading
Loading