Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions dd-java-agent/agent-bootstrap/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ jmh {
jmhVersion = '1.32'
duplicateClassesStrategy = DuplicatesStrategy.EXCLUDE
}

project.afterEvaluate {
tasks.withType(Test).configureEach {
if (javaLauncher.get().metadata.languageVersion.asInt() >= 16) {
jvmArgs += ['--add-opens', 'java.base/java.net=ALL-UNNAMED'] // for HostNameResolverForkedTest
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import static datadog.trace.api.cache.RadixTreeCache.PORTS;
import static datadog.trace.api.cache.RadixTreeCache.UNSET_PORT;
import static datadog.trace.bootstrap.instrumentation.java.net.HostNameResolver.hostName;

import datadog.context.ContextScope;
import datadog.trace.api.Config;
import datadog.trace.api.DDTags;
import datadog.trace.api.Functions;
import datadog.trace.api.cache.DDCache;
import datadog.trace.api.cache.DDCaches;
import datadog.trace.api.cache.QualifiedClassNameCache;
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
Expand Down Expand Up @@ -40,8 +39,6 @@ public String apply(Class<?> clazz) {
},
Functions.PrefixJoin.of("."));

private static final DDCache<String, String> HOSTNAME_CACHE = DDCaches.newFixedSizeCache(64);

protected final boolean traceAnalyticsEnabled;
protected final Double traceAnalyticsSampleRate;

Expand Down Expand Up @@ -200,11 +197,4 @@ public CharSequence className(final Class<?> clazz) {
String simpleName = clazz.getSimpleName();
return simpleName.isEmpty() ? CLASS_NAMES.getClassName(clazz) : simpleName;
}

private static String hostName(InetAddress remoteAddress, String ip) {
if (null != ip) {
return HOSTNAME_CACHE.computeIfAbsent(ip, _ip -> remoteAddress.getHostName());
}
return remoteAddress.getHostName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package datadog.trace.bootstrap.instrumentation.java.net;

import datadog.trace.api.cache.DDCache;
import datadog.trace.api.cache.DDCaches;
import datadog.trace.util.MethodHandles;
import java.lang.invoke.MethodHandle;
import java.net.InetAddress;

public final class HostNameResolver {
private static final MethodHandle HOLDER_GET;
private static final MethodHandle HOSTNAME_GET;

private static final DDCache<String, String> HOSTNAME_CACHE = DDCaches.newFixedSizeCache(64);

static {
MethodHandle holderTmp = null, hostnameTmp = null;
try {
final ClassLoader cl = HostNameResolver.class.getClassLoader();
final MethodHandles methodHandles = new MethodHandles(cl);

final Class<?> holderClass =
Class.forName("java.net.InetAddress$InetAddressHolder", false, cl);
holderTmp = methodHandles.method(InetAddress.class, "holder");
if (holderTmp != null) {
hostnameTmp = methodHandles.method(holderClass, "getHostName");
}
} catch (Throwable ignored) {
holderTmp = null;
} finally {
if (holderTmp != null && hostnameTmp != null) {
HOLDER_GET = holderTmp;
HOSTNAME_GET = hostnameTmp;
} else {
HOLDER_GET = null;
HOSTNAME_GET = null;
}
}
}

private HostNameResolver() {}

static String getAlreadyResolvedHostName(InetAddress address) {
if (HOLDER_GET == null) {
return null;
}
try {
final Object holder = HOLDER_GET.invoke(address);
return (String) HOSTNAME_GET.invoke(holder);
} catch (final Throwable ignored) {
}
return null;
Comment on lines +49 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} catch (final Throwable ignored) {
}
return null;
} catch (final Throwable ignored) {
return null;
}

minor suggestion, so the returns are aligned :)

}

private static String fromCache(InetAddress remoteAddress, String ip) {
if (null != ip) {
return HOSTNAME_CACHE.computeIfAbsent(ip, _ip -> remoteAddress.getHostName());
}
return remoteAddress.getHostName();
}

public static String hostName(InetAddress address, String ip) {
final String alreadyResolved = getAlreadyResolvedHostName(address);
if (alreadyResolved != null) {
return alreadyResolved;
}
return fromCache(address, ip);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package datadog.trace.bootstrap.instrumentation.java.net

import datadog.trace.test.util.DDSpecification

class HostNameResolverForkedTest extends DDSpecification {
def "should directly get the hostname for already resolved address #address"() {
given:
def host = HostNameResolver.getAlreadyResolvedHostName(address)
expect:
host == expected
where:
address | expected
new Inet4Address("test", InetAddress.getLocalHost().getAddress()) | "test"
new Inet6Address("test", InetAddress.getLocalHost().getAddress()) | "test"
}

def "should return null when directly get the address for unresolved #address"() {
given:
def host = HostNameResolver.getAlreadyResolvedHostName(address)
expect:
host == null
where:
address | _
InetAddress.getByAddress(InetAddress.getLocalHost().getAddress()) | _
new Inet6Address(null, InetAddress.getLocalHost().getAddress()) | _
}

def "should use the cache for unresolved addresses"() {
given:
def inet1 = new Inet4Address(null, InetAddress.getLocalHost().getAddress())
def inet2 = new Inet4Address(null, 0) // this will fail if a resolution will happen
when:
def address = new InetSocketAddress(inet1, 666)
def host = HostNameResolver.hostName(address.getAddress(), "127.0.0.1")
then:
host != null
when:
address = new InetSocketAddress(inet2, 666)
def host2 = HostNameResolver.hostName(address.getAddress(), "127.0.0.1")
then:
host == host2
}
}