diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java index 2628e9416cf..9e68a833f09 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/BaseDecorator.java @@ -1,7 +1,5 @@ package datadog.trace.bootstrap.instrumentation.decorator; -import static datadog.trace.bootstrap.instrumentation.java.net.HostNameResolver.hostName; - import datadog.context.Context; import datadog.context.ContextScope; import datadog.trace.api.Config; @@ -14,8 +12,6 @@ import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities; import datadog.trace.bootstrap.instrumentation.api.Tags; import java.lang.reflect.Method; -import java.net.Inet4Address; -import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.util.concurrent.ExecutionException; @@ -150,10 +146,10 @@ public ContextScope onError(final ContextScope scope, final Throwable throwable) public AgentSpan onPeerConnection( final AgentSpan span, final InetSocketAddress remoteConnection) { - if (remoteConnection != null) { - onPeerConnection(span, remoteConnection.getAddress(), !remoteConnection.isUnresolved()); - setPeerPort(span, remoteConnection.getPort()); - } + // Invoke the extractor directly rather than via span.setTags(...): this legacy plumbing path + // is behavior-identical to the old inline code, and a direct call runs on test doubles too + // (the span-first span.setTags(...) sugar is for hand-written integration call sites). + PeerConnectionExtractor.INSTANCE.extract(remoteConnection, span); return span; } @@ -162,17 +158,7 @@ public AgentSpan onPeerConnection(final AgentSpan span, final InetAddress remote } public AgentSpan onPeerConnection(AgentSpan span, InetAddress remoteAddress, boolean resolved) { - if (remoteAddress != null) { - String ip = remoteAddress.getHostAddress(); - if (resolved && Config.get().isPeerHostNameEnabled()) { - span.setTag(Tags.PEER_HOSTNAME, hostName(remoteAddress, ip)); - } - if (remoteAddress instanceof Inet4Address) { - span.setTag(Tags.PEER_HOST_IPV4, ip); - } else if (remoteAddress instanceof Inet6Address) { - span.setTag(Tags.PEER_HOST_IPV6, ip); - } - } + PeerConnectionExtractor.setPeerAddress(span, remoteAddress, resolved); return span; } diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/PeerConnectionExtractor.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/PeerConnectionExtractor.java new file mode 100644 index 00000000000..7592961789e --- /dev/null +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/PeerConnectionExtractor.java @@ -0,0 +1,57 @@ +package datadog.trace.bootstrap.instrumentation.decorator; + +import static datadog.trace.bootstrap.instrumentation.java.net.HostNameResolver.hostName; + +import datadog.trace.api.Config; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.TagExtractor; +import datadog.trace.bootstrap.instrumentation.api.Tags; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +/** + * Named singleton {@link TagExtractor} for peer-connection tags (hostname / IPv4 / IPv6 / port) + * from a remote {@link InetSocketAddress}. + * + *

Promoted from an inline lambda in {@link BaseDecorator} to a named class so it can be: + * referenced by name at call sites ({@code span.setTags(addr, PeerConnectionExtractor.INSTANCE)}), + * composed with other extractors (the axis the Decorator inheritance chain lacked), and + * given a home for the pure statics and the {@code hostName} resolver cache it consults. + * Non-capturing and stateless — the single {@link #INSTANCE} is effectively a static function + * object, so a monomorphic call site inlines it away. + */ +public final class PeerConnectionExtractor implements TagExtractor { + public static final PeerConnectionExtractor INSTANCE = new PeerConnectionExtractor(); + + private static final int UNSET_PORT = 0; + + private PeerConnectionExtractor() {} + + @Override + public void extract(final InetSocketAddress remoteConnection, final AgentSpan span) { + if (remoteConnection != null) { + setPeerAddress(span, remoteConnection.getAddress(), !remoteConnection.isUnresolved()); + final int port = remoteConnection.getPort(); + if (port > UNSET_PORT) { + span.setTag(Tags.PEER_PORT, port); + } + } + } + + static void setPeerAddress( + final AgentSpan span, final InetAddress remoteAddress, final boolean resolved) { + if (remoteAddress != null) { + String ip = remoteAddress.getHostAddress(); + if (resolved && Config.get().isPeerHostNameEnabled()) { + span.setTag(Tags.PEER_HOSTNAME, hostName(remoteAddress, ip)); + } + if (remoteAddress instanceof Inet4Address) { + span.setTag(Tags.PEER_HOST_IPV4, ip); + } else if (remoteAddress instanceof Inet6Address) { + span.setTag(Tags.PEER_HOST_IPV6, ip); + } + } + } +}