From 64a03d6c6fee7fe0cf618217ab0e56d672d61919 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Thu, 4 Nov 2021 13:36:23 +0100 Subject: [PATCH 1/3] Trace DNS resolution in Netty 4.1 --- .../v3_8/NettyChannelInstrumentation.java | 16 +-- .../netty/v3_8/client/ConnectionListener.java | 14 +- .../v3_8/client/NettyClientSingletons.java | 14 +- .../NettyConnectNetAttributesExtractor.java | 8 +- .../client/ConnectionCompleteListener.java | 8 +- .../NettyClientInstrumenterFactory.java | 14 +- .../NettyConnectNetAttributesExtractor.java | 8 +- ....java => NettyConnectionInstrumenter.java} | 10 +- ...a => NettyConnectionInstrumenterImpl.java} | 14 +- ...NettyErrorOnlyConnectionInstrumenter.java} | 14 +- .../netty/v4_0/BootstrapInstrumentation.java | 18 +-- .../v4_0/client/NettyClientSingletons.java | 10 +- .../netty/v4_1/BootstrapInstrumentation.java | 65 ++++++++-- .../InstrumentedAddressResolverGroup.java | 121 ++++++++++++++++++ .../v4_1/client/NettyClientSingletons.java | 10 +- .../groovy/Netty41ConnectionSpanTest.groovy | 32 ++++- .../netty/common/NettyConnectRequest.java | 23 ---- .../netty/common/NettyConnectionRequest.java | 29 +++++ .../reactornetty/v1_0/ConnectionWrapper.java | 10 +- .../v1_0/ReactorNettySingletons.java | 10 +- .../TransportConnectorInstrumentation.java | 16 +-- 21 files changed, 325 insertions(+), 139 deletions(-) rename instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/{NettyConnectInstrumenter.java => NettyConnectionInstrumenter.java} (52%) rename instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/{NettyConnectInstrumenterImpl.java => NettyConnectionInstrumenterImpl.java} (60%) rename instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/{NettyErrorOnlyConnectInstrumenter.java => NettyErrorOnlyConnectionInstrumenter.java} (64%) create mode 100644 instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java delete mode 100644 instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectRequest.java create mode 100644 instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectionRequest.java diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java index e2a85c4580f9..0f8a4f5d96a5 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/NettyChannelInstrumentation.java @@ -7,7 +7,7 @@ import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyClientSingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyClientSingletons.connectionInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; @@ -19,7 +19,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.ConnectionListener; import java.net.SocketAddress; import net.bytebuddy.asm.Advice; @@ -58,7 +58,7 @@ public static void onEnter( @Advice.This Channel channel, @Advice.Argument(0) SocketAddress remoteAddress, @Advice.Local("otelParentContext") Context parentContext, - @Advice.Local("otelRequest") NettyConnectRequest request) { + @Advice.Local("otelRequest") NettyConnectionRequest request) { parentContext = Java8BytecodeBridge.currentContext(); Span span = Java8BytecodeBridge.spanFromContext(parentContext); @@ -73,7 +73,7 @@ public static void onEnter( } virtualField.set(channel, new NettyConnectionContext(parentContext)); - request = NettyConnectRequest.create(remoteAddress); + request = NettyConnectionRequest.connect(remoteAddress); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) @@ -81,16 +81,16 @@ public static void onExit( @Advice.Return ChannelFuture channelFuture, @Advice.Thrown Throwable error, @Advice.Local("otelParentContext") Context parentContext, - @Advice.Local("otelRequest") NettyConnectRequest request) { + @Advice.Local("otelRequest") NettyConnectionRequest request) { if (request == null) { return; } if (error != null) { - if (connectInstrumenter().shouldStart(parentContext, request)) { - Context context = connectInstrumenter().start(parentContext, request); - connectInstrumenter().end(context, request, null, error); + if (connectionInstrumenter().shouldStart(parentContext, request)) { + Context context = connectionInstrumenter().start(parentContext, request); + connectionInstrumenter().end(context, request, null, error); } } else { channelFuture.addListener(new ConnectionListener(parentContext, request)); diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/ConnectionListener.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/ConnectionListener.java index 3e65eccc1359..cd1208f54c3c 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/ConnectionListener.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/ConnectionListener.java @@ -5,19 +5,19 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client; -import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyClientSingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyClientSingletons.connectionInstrumenter; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelFutureListener; public final class ConnectionListener implements ChannelFutureListener { private final Context parentContext; - private final NettyConnectRequest request; + private final NettyConnectionRequest request; - public ConnectionListener(Context parentContext, NettyConnectRequest request) { + public ConnectionListener(Context parentContext, NettyConnectionRequest request) { this.parentContext = parentContext; this.request = request; } @@ -25,9 +25,9 @@ public ConnectionListener(Context parentContext, NettyConnectRequest request) { @Override public void operationComplete(ChannelFuture future) { Throwable cause = future.getCause(); - if (cause != null && connectInstrumenter().shouldStart(parentContext, request)) { - Context context = connectInstrumenter().start(parentContext, request); - connectInstrumenter().end(context, request, future.getChannel(), cause); + if (cause != null && connectionInstrumenter().shouldStart(parentContext, request)) { + Context context = connectionInstrumenter().start(parentContext, request); + connectionInstrumenter().end(context, request, future.getChannel(), cause); } } } diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java index 5ea370b10ba4..cc22296be4b7 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyClientSingletons.java @@ -12,7 +12,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientMetrics; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import io.opentelemetry.javaagent.instrumentation.netty.common.NettyErrorHolder; import io.opentelemetry.javaagent.instrumentation.netty.v3_8.HttpRequestAndChannel; import org.jboss.netty.channel.Channel; @@ -23,7 +23,7 @@ public final class NettyClientSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.netty-3.8"; private static final Instrumenter INSTRUMENTER; - private static final Instrumenter CONNECT_INSTRUMENTER; + private static final Instrumenter CONNECTION_INSTRUMENTER; static { NettyHttpClientAttributesExtractor httpClientAttributesExtractor = @@ -48,9 +48,9 @@ public final class NettyClientSingletons { NettyConnectNetAttributesExtractor nettyConnectAttributesExtractor = new NettyConnectNetAttributesExtractor(); - CONNECT_INSTRUMENTER = - Instrumenter.builder( - GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, rq -> "CONNECT") + CONNECTION_INSTRUMENTER = + Instrumenter.builder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, NettyConnectionRequest::spanName) .addAttributesExtractor(nettyConnectAttributesExtractor) .addAttributesExtractor( PeerServiceAttributesExtractor.create(nettyConnectAttributesExtractor)) @@ -64,8 +64,8 @@ public static Instrumenter instrumenter() { return INSTRUMENTER; } - public static Instrumenter connectInstrumenter() { - return CONNECT_INSTRUMENTER; + public static Instrumenter connectionInstrumenter() { + return CONNECTION_INSTRUMENTER; } private NettyClientSingletons() {} diff --git a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyConnectNetAttributesExtractor.java b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyConnectNetAttributesExtractor.java index 38a0d5c1c371..7def69496a69 100644 --- a/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyConnectNetAttributesExtractor.java +++ b/instrumentation/netty/netty-3.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v3_8/client/NettyConnectNetAttributesExtractor.java @@ -9,7 +9,7 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_UDP; import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetClientAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import java.net.InetSocketAddress; import java.net.SocketAddress; import javax.annotation.Nullable; @@ -17,11 +17,11 @@ import org.jboss.netty.channel.socket.DatagramChannel; final class NettyConnectNetAttributesExtractor - extends InetSocketAddressNetClientAttributesExtractor { + extends InetSocketAddressNetClientAttributesExtractor { @Nullable @Override - public InetSocketAddress getAddress(NettyConnectRequest request, @Nullable Channel channel) { + public InetSocketAddress getAddress(NettyConnectionRequest request, @Nullable Channel channel) { SocketAddress remoteAddress = null; if (channel != null) { remoteAddress = channel.getRemoteAddress(); @@ -37,7 +37,7 @@ public InetSocketAddress getAddress(NettyConnectRequest request, @Nullable Chann } @Override - public String transport(NettyConnectRequest request, @Nullable Channel channel) { + public String transport(NettyConnectionRequest request, @Nullable Channel channel) { return channel instanceof DatagramChannel ? IP_UDP : IP_TCP; } } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/ConnectionCompleteListener.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/ConnectionCompleteListener.java index 68f364759c84..f058ccd59c09 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/ConnectionCompleteListener.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/ConnectionCompleteListener.java @@ -10,15 +10,15 @@ import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; public class ConnectionCompleteListener implements GenericFutureListener> { - private final NettyConnectInstrumenter instrumenter; + private final NettyConnectionInstrumenter instrumenter; private final Context context; - private final NettyConnectRequest request; + private final NettyConnectionRequest request; public ConnectionCompleteListener( - NettyConnectInstrumenter instrumenter, Context context, NettyConnectRequest request) { + NettyConnectionInstrumenter instrumenter, Context context, NettyConnectionRequest request) { this.instrumenter = instrumenter; this.context = context; this.request = request; diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyClientInstrumenterFactory.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyClientInstrumenterFactory.java index 4e63a13f741e..f709d8f19355 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyClientInstrumenterFactory.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyClientInstrumenterFactory.java @@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor; import io.opentelemetry.javaagent.instrumentation.netty.common.HttpRequestAndChannel; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; public final class NettyClientInstrumenterFactory { @@ -46,12 +46,12 @@ public Instrumenter createHttpInstrumenter( .newClientInstrumenter(new HttpRequestHeadersSetter()); } - public NettyConnectInstrumenter createConnectInstrumenter() { + public NettyConnectionInstrumenter createConnectionInstrumenter() { NettyConnectNetAttributesExtractor netAttributesExtractor = new NettyConnectNetAttributesExtractor(); - Instrumenter instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), instrumentationName, rq -> "CONNECT") + Instrumenter instrumenter = + Instrumenter.builder( + GlobalOpenTelemetry.get(), instrumentationName, NettyConnectionRequest::spanName) .addAttributesExtractor(netAttributesExtractor) .addAttributesExtractor(PeerServiceAttributesExtractor.create(netAttributesExtractor)) .setTimeExtractors( @@ -63,7 +63,7 @@ public NettyConnectInstrumenter createConnectInstrumenter() { : SpanKindExtractor.alwaysClient()); return alwaysCreateConnectSpan - ? new NettyConnectInstrumenterImpl(instrumenter) - : new NettyErrorOnlyConnectInstrumenter(instrumenter); + ? new NettyConnectionInstrumenterImpl(instrumenter) + : new NettyErrorOnlyConnectionInstrumenter(instrumenter); } } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectNetAttributesExtractor.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectNetAttributesExtractor.java index 98ca5cde4b78..d4754eed18d6 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectNetAttributesExtractor.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectNetAttributesExtractor.java @@ -11,17 +11,17 @@ import io.netty.channel.Channel; import io.netty.channel.socket.DatagramChannel; import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetClientAttributesExtractor; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import java.net.InetSocketAddress; import java.net.SocketAddress; import javax.annotation.Nullable; final class NettyConnectNetAttributesExtractor - extends InetSocketAddressNetClientAttributesExtractor { + extends InetSocketAddressNetClientAttributesExtractor { @Nullable @Override - public InetSocketAddress getAddress(NettyConnectRequest request, @Nullable Channel channel) { + public InetSocketAddress getAddress(NettyConnectionRequest request, @Nullable Channel channel) { SocketAddress remoteAddress = null; if (channel != null) { remoteAddress = channel.remoteAddress(); @@ -37,7 +37,7 @@ public InetSocketAddress getAddress(NettyConnectRequest request, @Nullable Chann } @Override - public String transport(NettyConnectRequest request, @Nullable Channel channel) { + public String transport(NettyConnectionRequest request, @Nullable Channel channel) { return channel instanceof DatagramChannel ? IP_UDP : IP_TCP; } } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenter.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenter.java similarity index 52% rename from instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenter.java rename to instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenter.java index 000a8fe3f342..4c82f74e11fb 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenter.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenter.java @@ -7,15 +7,15 @@ import io.netty.channel.Channel; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import javax.annotation.Nullable; -public interface NettyConnectInstrumenter { +public interface NettyConnectionInstrumenter { - boolean shouldStart(Context parentContext, NettyConnectRequest request); + boolean shouldStart(Context parentContext, NettyConnectionRequest request); - Context start(Context parentContext, NettyConnectRequest request); + Context start(Context parentContext, NettyConnectionRequest request); void end( - Context context, NettyConnectRequest request, Channel channel, @Nullable Throwable error); + Context context, NettyConnectionRequest request, Channel channel, @Nullable Throwable error); } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenterImpl.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenterImpl.java similarity index 60% rename from instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenterImpl.java rename to instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenterImpl.java index 55f342f222b9..f6fee3d189d4 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectInstrumenterImpl.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyConnectionInstrumenterImpl.java @@ -8,30 +8,30 @@ import io.netty.channel.Channel; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import javax.annotation.Nullable; -final class NettyConnectInstrumenterImpl implements NettyConnectInstrumenter { +final class NettyConnectionInstrumenterImpl implements NettyConnectionInstrumenter { - private final Instrumenter instrumenter; + private final Instrumenter instrumenter; - NettyConnectInstrumenterImpl(Instrumenter instrumenter) { + NettyConnectionInstrumenterImpl(Instrumenter instrumenter) { this.instrumenter = instrumenter; } @Override - public boolean shouldStart(Context parentContext, NettyConnectRequest request) { + public boolean shouldStart(Context parentContext, NettyConnectionRequest request) { return instrumenter.shouldStart(parentContext, request); } @Override - public Context start(Context parentContext, NettyConnectRequest request) { + public Context start(Context parentContext, NettyConnectionRequest request) { return instrumenter.start(parentContext, request); } @Override public void end( - Context context, NettyConnectRequest request, Channel channel, @Nullable Throwable error) { + Context context, NettyConnectionRequest request, Channel channel, @Nullable Throwable error) { instrumenter.end(context, request, channel, error); } } diff --git a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectInstrumenter.java b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectionInstrumenter.java similarity index 64% rename from instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectInstrumenter.java rename to instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectionInstrumenter.java index 6550f96c386b..6f3cbb96a73f 100644 --- a/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectInstrumenter.java +++ b/instrumentation/netty/netty-4-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/client/NettyErrorOnlyConnectionInstrumenter.java @@ -8,31 +8,31 @@ import io.netty.channel.Channel; import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import javax.annotation.Nullable; -final class NettyErrorOnlyConnectInstrumenter implements NettyConnectInstrumenter { +final class NettyErrorOnlyConnectionInstrumenter implements NettyConnectionInstrumenter { - private final Instrumenter instrumenter; + private final Instrumenter instrumenter; - NettyErrorOnlyConnectInstrumenter(Instrumenter instrumenter) { + NettyErrorOnlyConnectionInstrumenter(Instrumenter instrumenter) { this.instrumenter = instrumenter; } @Override - public boolean shouldStart(Context parentContext, NettyConnectRequest request) { + public boolean shouldStart(Context parentContext, NettyConnectionRequest request) { // the "real" check is done on end() anyway return true; } @Override - public Context start(Context parentContext, NettyConnectRequest request) { + public Context start(Context parentContext, NettyConnectionRequest request) { return parentContext; } @Override public void end( - Context context, NettyConnectRequest request, Channel channel, @Nullable Throwable error) { + Context context, NettyConnectionRequest request, Channel channel, @Nullable Throwable error) { if (error != null && instrumenter.shouldStart(context, request)) { Context connectContext = instrumenter.start(context, request); instrumenter.end(connectContext, request, channel, error); diff --git a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/BootstrapInstrumentation.java b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/BootstrapInstrumentation.java index f7b23951b87f..4e9943a5140f 100644 --- a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/BootstrapInstrumentation.java +++ b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/BootstrapInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.netty.v4_0; -import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyClientSingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.netty.v4_0.client.NettyClientSingletons.connectionInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -15,7 +15,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import io.opentelemetry.javaagent.instrumentation.netty.common.client.ConnectionCompleteListener; import java.net.SocketAddress; import net.bytebuddy.asm.Advice; @@ -40,17 +40,17 @@ public static class ConnectAdvice { public static void startConnect( @Advice.Argument(0) SocketAddress remoteAddress, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { Context parentContext = Java8BytecodeBridge.currentContext(); - request = NettyConnectRequest.create(remoteAddress); + request = NettyConnectionRequest.connect(remoteAddress); - if (!connectInstrumenter().shouldStart(parentContext, request)) { + if (!connectionInstrumenter().shouldStart(parentContext, request)) { return; } - context = connectInstrumenter().start(parentContext, request); + context = connectionInstrumenter().start(parentContext, request); scope = context.makeCurrent(); } @@ -59,7 +59,7 @@ public static void endConnect( @Advice.Thrown Throwable throwable, @Advice.Return ChannelFuture channelFuture, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { if (scope == null) { @@ -68,10 +68,10 @@ public static void endConnect( scope.close(); if (throwable != null) { - connectInstrumenter().end(context, request, null, throwable); + connectionInstrumenter().end(context, request, null, throwable); } else { channelFuture.addListener( - new ConnectionCompleteListener(connectInstrumenter(), context, request)); + new ConnectionCompleteListener(connectionInstrumenter(), context, request)); } } } diff --git a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java index 902219976b54..6aa470db252f 100644 --- a/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java +++ b/instrumentation/netty/netty-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_0/client/NettyClientSingletons.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.instrumentation.netty.common.HttpRequestAndChannel; import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyClientInstrumenterFactory; -import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectInstrumenter; +import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectionInstrumenter; public final class NettyClientSingletons { @@ -18,21 +18,21 @@ public final class NettyClientSingletons { Config.get().getBoolean("otel.instrumentation.netty.always-create-connect-span", false); private static final Instrumenter INSTRUMENTER; - private static final NettyConnectInstrumenter CONNECT_INSTRUMENTER; + private static final NettyConnectionInstrumenter CONNECTION_INSTRUMENTER; static { NettyClientInstrumenterFactory factory = new NettyClientInstrumenterFactory("io.opentelemetry.netty-4.0", alwaysCreateConnectSpan); INSTRUMENTER = factory.createHttpInstrumenter(); - CONNECT_INSTRUMENTER = factory.createConnectInstrumenter(); + CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter(); } public static Instrumenter instrumenter() { return INSTRUMENTER; } - public static NettyConnectInstrumenter connectInstrumenter() { - return CONNECT_INSTRUMENTER; + public static NettyConnectionInstrumenter connectionInstrumenter() { + return CONNECTION_INSTRUMENTER; } private NettyClientSingletons() {} diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/BootstrapInstrumentation.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/BootstrapInstrumentation.java index a00a3b1b597c..aa9529a9d0ee 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/BootstrapInstrumentation.java +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/BootstrapInstrumentation.java @@ -5,18 +5,24 @@ package io.opentelemetry.javaagent.instrumentation.netty.v4_1; -import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.connectionInstrumenter; +import static net.bytebuddy.matcher.ElementMatchers.isConstructor; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import io.netty.channel.ChannelFuture; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelPromise; +import io.netty.resolver.AddressResolverGroup; +import io.netty.resolver.DefaultAddressResolverGroup; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import io.opentelemetry.javaagent.instrumentation.netty.common.client.ConnectionCompleteListener; +import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.InstrumentedAddressResolverGroup; import java.net.SocketAddress; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -31,35 +37,68 @@ public ElementMatcher typeMatcher() { @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( - named("doResolveAndConnect").and(takesArgument(0, SocketAddress.class)), + isConstructor().and(takesArguments(0)), + BootstrapInstrumentation.class.getName() + "$ConstructorAdvice"); + transformer.applyAdviceToMethod( + named("resolver") + .and(takesArguments(1)) + .and(takesArgument(0, named("io.netty.resolver.AddressResolverGroup"))), + BootstrapInstrumentation.class.getName() + "$SetResolverAdvice"); + transformer.applyAdviceToMethod( + named("doConnect") + .and(takesArguments(3)) + .and(takesArgument(0, SocketAddress.class)) + .and(takesArgument(2, named("io.netty.channel.ChannelPromise"))), BootstrapInstrumentation.class.getName() + "$ConnectAdvice"); } + @SuppressWarnings("unused") + public static class ConstructorAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit(@Advice.This Bootstrap bootstrap) { + // this is already the default value, but we're calling the resolver() method to invoke its + // instrumentation + bootstrap.resolver(DefaultAddressResolverGroup.INSTANCE); + } + } + + @SuppressWarnings("unused") + public static class SetResolverAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter( + @Advice.Argument(value = 0, readOnly = false) AddressResolverGroup resolver) { + resolver = InstrumentedAddressResolverGroup.wrap(connectionInstrumenter(), resolver); + } + } + + @SuppressWarnings("unused") public static class ConnectAdvice { @Advice.OnMethodEnter public static void startConnect( @Advice.Argument(0) SocketAddress remoteAddress, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { Context parentContext = Java8BytecodeBridge.currentContext(); - request = NettyConnectRequest.create(remoteAddress); + request = NettyConnectionRequest.connect(remoteAddress); - if (!connectInstrumenter().shouldStart(parentContext, request)) { + if (!connectionInstrumenter().shouldStart(parentContext, request)) { return; } - context = connectInstrumenter().start(parentContext, request); + context = connectionInstrumenter().start(parentContext, request); scope = context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void endConnect( @Advice.Thrown Throwable throwable, - @Advice.Return ChannelFuture channelFuture, + @Advice.Argument(2) ChannelPromise channelPromise, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { if (scope == null) { @@ -68,10 +107,10 @@ public static void endConnect( scope.close(); if (throwable != null) { - connectInstrumenter().end(context, request, null, throwable); + connectionInstrumenter().end(context, request, null, throwable); } else { - channelFuture.addListener( - new ConnectionCompleteListener(connectInstrumenter(), context, request)); + channelPromise.addListener( + new ConnectionCompleteListener(connectionInstrumenter(), context, request)); } } } diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java new file mode 100644 index 000000000000..5c020ce430de --- /dev/null +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java @@ -0,0 +1,121 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client; + +import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.connectionInstrumenter; + +import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.Promise; +import io.opentelemetry.context.Context; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectionInstrumenter; +import java.net.SocketAddress; +import java.util.List; +import java.util.function.Supplier; + +public final class InstrumentedAddressResolverGroup + extends AddressResolverGroup { + + public static AddressResolverGroup wrap( + NettyConnectionInstrumenter instrumenter, AddressResolverGroup delegate) { + if (delegate instanceof InstrumentedAddressResolverGroup) { + return delegate; + } + return new InstrumentedAddressResolverGroup<>(connectionInstrumenter(), delegate); + } + + private final NettyConnectionInstrumenter instrumenter; + private final AddressResolverGroup delegate; + + private InstrumentedAddressResolverGroup( + NettyConnectionInstrumenter instrumenter, AddressResolverGroup delegate) { + this.instrumenter = instrumenter; + this.delegate = delegate; + } + + @Override + public AddressResolver getResolver(EventExecutor executor) { + return new InstrumentedResolver<>(instrumenter, delegate.getResolver(executor)); + } + + @Override + public void close() { + delegate.close(); + } + + @Override + protected AddressResolver newResolver(EventExecutor eventExecutor) { + throw new UnsupportedOperationException("This method should never be called"); + } + + private static final class InstrumentedResolver + implements AddressResolver { + + private final NettyConnectionInstrumenter instrumenter; + private final AddressResolver delegate; + + private InstrumentedResolver( + NettyConnectionInstrumenter instrumenter, AddressResolver delegate) { + this.instrumenter = instrumenter; + this.delegate = delegate; + } + + @Override + public boolean isSupported(SocketAddress socketAddress) { + return delegate.isSupported(socketAddress); + } + + @Override + public boolean isResolved(SocketAddress socketAddress) { + return delegate.isResolved(socketAddress); + } + + @Override + public Future resolve(SocketAddress socketAddress) { + return instrumentResolve(socketAddress, () -> delegate.resolve(socketAddress)); + } + + @Override + public Future resolve(SocketAddress socketAddress, Promise promise) { + return instrumentResolve(socketAddress, () -> delegate.resolve(socketAddress, promise)); + } + + @Override + public Future> resolveAll(SocketAddress socketAddress) { + return instrumentResolve(socketAddress, () -> delegate.resolveAll(socketAddress)); + } + + @Override + public Future> resolveAll(SocketAddress socketAddress, Promise> promise) { + return instrumentResolve(socketAddress, () -> delegate.resolveAll(socketAddress, promise)); + } + + private Future instrumentResolve( + SocketAddress socketAddress, Supplier> resolveFunc) { + Context parentContext = Context.current(); + NettyConnectionRequest request = NettyConnectionRequest.resolve(socketAddress); + if (!instrumenter.shouldStart(parentContext, request)) { + return resolveFunc.get(); + } + Context context = instrumenter.start(parentContext, request); + try { + Future future = resolveFunc.get(); + return future.addListener(f -> instrumenter.end(context, request, null, f.cause())); + } catch (Throwable t) { + instrumenter.end(context, request, null, t); + throw t; + } + } + + @Override + public void close() { + delegate.close(); + } + } +} diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyClientSingletons.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyClientSingletons.java index 4eb68bcefd7f..d2704272a582 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyClientSingletons.java +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/NettyClientSingletons.java @@ -11,7 +11,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.instrumentation.netty.common.HttpRequestAndChannel; import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyClientInstrumenterFactory; -import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectInstrumenter; +import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectionInstrumenter; public final class NettyClientSingletons { @@ -24,21 +24,21 @@ public final class NettyClientSingletons { Config.get().getBoolean("otel.instrumentation.netty.always-create-connect-span", false); private static final Instrumenter INSTRUMENTER; - private static final NettyConnectInstrumenter CONNECT_INSTRUMENTER; + private static final NettyConnectionInstrumenter CONNECTION_INSTRUMENTER; static { NettyClientInstrumenterFactory factory = new NettyClientInstrumenterFactory("io.opentelemetry.netty-4.1", alwaysCreateConnectSpan); INSTRUMENTER = factory.createHttpInstrumenter(); - CONNECT_INSTRUMENTER = factory.createConnectInstrumenter(); + CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter(); } public static Instrumenter instrumenter() { return INSTRUMENTER; } - public static NettyConnectInstrumenter connectInstrumenter() { - return CONNECT_INSTRUMENTER; + public static NettyConnectionInstrumenter connectionInstrumenter() { + return CONNECTION_INSTRUMENTER; } private NettyClientSingletons() {} diff --git a/instrumentation/netty/netty-4.1/javaagent/src/test/groovy/Netty41ConnectionSpanTest.groovy b/instrumentation/netty/netty-4.1/javaagent/src/test/groovy/Netty41ConnectionSpanTest.groovy index 8fcb6ae3082b..ed58f1fb72cf 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/test/groovy/Netty41ConnectionSpanTest.groovy +++ b/instrumentation/netty/netty-4.1/javaagent/src/test/groovy/Netty41ConnectionSpanTest.groovy @@ -94,13 +94,23 @@ class Netty41ConnectionSpanTest extends InstrumentationSpecification implements then: responseCode == 200 assertTraces(1) { - trace(0, 4) { + trace(0, 5) { span(0) { name "parent" kind INTERNAL hasNoParent() } span(1) { + name "RESOLVE" + kind INTERNAL + childOf span(0) + attributes { + "${SemanticAttributes.NET_TRANSPORT.key}" IP_TCP + "${SemanticAttributes.NET_PEER_NAME.key}" uri.host + "${SemanticAttributes.NET_PEER_PORT.key}" uri.port + } + } + span(2) { name "CONNECT" kind INTERNAL childOf(span(0)) @@ -111,15 +121,15 @@ class Netty41ConnectionSpanTest extends InstrumentationSpecification implements "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" } } - span(2) { + span(3) { name "HTTP GET" kind CLIENT childOf(span(0)) } - span(3) { + span(4) { name "test-http-server" kind SERVER - childOf(span(2)) + childOf(span(3)) } } } @@ -138,7 +148,7 @@ class Netty41ConnectionSpanTest extends InstrumentationSpecification implements and: assertTraces(1) { - trace(0, 2) { + trace(0, 3) { span(0) { name "parent" kind INTERNAL @@ -147,9 +157,19 @@ class Netty41ConnectionSpanTest extends InstrumentationSpecification implements errorEvent(thrownException.class, thrownException.message) } span(1) { + name "RESOLVE" + kind INTERNAL + childOf span(0) + attributes { + "${SemanticAttributes.NET_TRANSPORT.key}" IP_TCP + "${SemanticAttributes.NET_PEER_NAME.key}" uri.host + "${SemanticAttributes.NET_PEER_PORT.key}" uri.port + } + } + span(2) { name "CONNECT" kind INTERNAL - childOf(span(0)) + childOf span(0) status ERROR errorEvent(thrownException.class, thrownException.message) attributes { diff --git a/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectRequest.java b/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectRequest.java deleted file mode 100644 index bf92465a2caf..000000000000 --- a/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectRequest.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.netty.common; - -import com.google.auto.value.AutoValue; -import java.net.SocketAddress; -import javax.annotation.Nullable; - -@AutoValue -public abstract class NettyConnectRequest { - - public static NettyConnectRequest create(SocketAddress remoteAddress) { - return new AutoValue_NettyConnectRequest(Timer.start(), remoteAddress); - } - - public abstract Timer timer(); - - @Nullable - public abstract SocketAddress remoteAddressOnStart(); -} diff --git a/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectionRequest.java b/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectionRequest.java new file mode 100644 index 000000000000..a8e214f35209 --- /dev/null +++ b/instrumentation/netty/netty-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/common/NettyConnectionRequest.java @@ -0,0 +1,29 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.netty.common; + +import com.google.auto.value.AutoValue; +import java.net.SocketAddress; +import javax.annotation.Nullable; + +@AutoValue +public abstract class NettyConnectionRequest { + + public static NettyConnectionRequest resolve(SocketAddress remoteAddress) { + return new AutoValue_NettyConnectionRequest("RESOLVE", Timer.start(), remoteAddress); + } + + public static NettyConnectionRequest connect(SocketAddress remoteAddress) { + return new AutoValue_NettyConnectionRequest("CONNECT", Timer.start(), remoteAddress); + } + + public abstract String spanName(); + + public abstract Timer timer(); + + @Nullable + public abstract SocketAddress remoteAddressOnStart(); +} diff --git a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ConnectionWrapper.java b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ConnectionWrapper.java index 5615b17fc821..d68f777cb65c 100644 --- a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ConnectionWrapper.java +++ b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ConnectionWrapper.java @@ -5,18 +5,18 @@ package io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0; -import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.ReactorNettySingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.ReactorNettySingletons.connectionInstrumenter; import io.netty.channel.Channel; import io.opentelemetry.context.Context; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import reactor.core.publisher.Mono; public class ConnectionWrapper { public static Mono wrap( - Context context, NettyConnectRequest request, Mono mono) { - return mono.doOnError(error -> connectInstrumenter().end(context, request, null, error)) - .doOnSuccess(channel -> connectInstrumenter().end(context, request, channel, null)); + Context context, NettyConnectionRequest request, Mono mono) { + return mono.doOnError(error -> connectionInstrumenter().end(context, request, null, error)) + .doOnSuccess(channel -> connectionInstrumenter().end(context, request, channel, null)); } } diff --git a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java index 4909b7726847..b0a0fd7ddcf9 100644 --- a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java +++ b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/ReactorNettySingletons.java @@ -7,7 +7,7 @@ import io.opentelemetry.instrumentation.api.config.Config; import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyClientInstrumenterFactory; -import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectInstrumenter; +import io.opentelemetry.javaagent.instrumentation.netty.common.client.NettyConnectionInstrumenter; public final class ReactorNettySingletons { @@ -15,17 +15,17 @@ public final class ReactorNettySingletons { Config.get() .getBoolean("otel.instrumentation.reactor-netty.always-create-connect-span", false); - private static final NettyConnectInstrumenter CONNECT_INSTRUMENTER; + private static final NettyConnectionInstrumenter CONNECTION_INSTRUMENTER; static { NettyClientInstrumenterFactory instrumenterFactory = new NettyClientInstrumenterFactory( "io.opentelemetry.reactor-netty-1.0", alwaysCreateConnectSpan); - CONNECT_INSTRUMENTER = instrumenterFactory.createConnectInstrumenter(); + CONNECTION_INSTRUMENTER = instrumenterFactory.createConnectionInstrumenter(); } - public static NettyConnectInstrumenter connectInstrumenter() { - return CONNECT_INSTRUMENTER; + public static NettyConnectionInstrumenter connectionInstrumenter() { + return CONNECTION_INSTRUMENTER; } private ReactorNettySingletons() {} diff --git a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/TransportConnectorInstrumentation.java b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/TransportConnectorInstrumentation.java index b43e1f6b6906..527ec8530750 100644 --- a/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/TransportConnectorInstrumentation.java +++ b/instrumentation/reactor-netty/reactor-netty-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/reactornetty/v1_0/TransportConnectorInstrumentation.java @@ -5,7 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0; -import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.ReactorNettySingletons.connectInstrumenter; +import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.ReactorNettySingletons.connectionInstrumenter; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -15,7 +15,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge; -import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectRequest; +import io.opentelemetry.javaagent.instrumentation.netty.common.NettyConnectionRequest; import java.net.SocketAddress; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -41,16 +41,16 @@ public static class ConnectAdvice { public static void startConnect( @Advice.Argument(1) SocketAddress remoteAddress, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { Context parentContext = Java8BytecodeBridge.currentContext(); - request = NettyConnectRequest.create(remoteAddress); - if (!connectInstrumenter().shouldStart(parentContext, request)) { + request = NettyConnectionRequest.connect(remoteAddress); + if (!connectionInstrumenter().shouldStart(parentContext, request)) { return; } - context = connectInstrumenter().start(parentContext, request); + context = connectionInstrumenter().start(parentContext, request); scope = context.makeCurrent(); } @@ -59,7 +59,7 @@ public static void endConnect( @Advice.Thrown Throwable throwable, @Advice.Return(readOnly = false) Mono mono, @Advice.Local("otelContext") Context context, - @Advice.Local("otelRequest") NettyConnectRequest request, + @Advice.Local("otelRequest") NettyConnectionRequest request, @Advice.Local("otelScope") Scope scope) { if (scope != null) { @@ -67,7 +67,7 @@ public static void endConnect( } if (throwable != null) { - connectInstrumenter().end(context, request, null, throwable); + connectionInstrumenter().end(context, request, null, throwable); } else { mono = ConnectionWrapper.wrap(context, request, mono); } From ad3baf6966feaa1debc712430032dd63b1d3375f Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Thu, 4 Nov 2021 14:55:09 +0100 Subject: [PATCH 2/3] Fix reactor-netty 0.9 tests --- .../ReactorNettyConnectionSpanTest.groovy | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/instrumentation/reactor-netty/reactor-netty-0.9/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/reactornetty/v0_9/ReactorNettyConnectionSpanTest.groovy b/instrumentation/reactor-netty/reactor-netty-0.9/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/reactornetty/v0_9/ReactorNettyConnectionSpanTest.groovy index 7122ffebbb72..6762e4ef847a 100644 --- a/instrumentation/reactor-netty/reactor-netty-0.9/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/reactornetty/v0_9/ReactorNettyConnectionSpanTest.groovy +++ b/instrumentation/reactor-netty/reactor-netty-0.9/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/reactornetty/v0_9/ReactorNettyConnectionSpanTest.groovy @@ -50,13 +50,23 @@ class ReactorNettyConnectionSpanTest extends InstrumentationSpecification implem then: responseCode == 200 assertTraces(1) { - trace(0, 4) { + trace(0, 5) { span(0) { name "parent" kind INTERNAL hasNoParent() } span(1) { + name "RESOLVE" + kind INTERNAL + childOf span(0) + attributes { + "${SemanticAttributes.NET_TRANSPORT.key}" IP_TCP + "${SemanticAttributes.NET_PEER_NAME.key}" "localhost" + "${SemanticAttributes.NET_PEER_PORT.key}" server.httpPort() + } + } + span(2) { name "CONNECT" kind INTERNAL childOf(span(0)) @@ -67,15 +77,15 @@ class ReactorNettyConnectionSpanTest extends InstrumentationSpecification implem "${SemanticAttributes.NET_PEER_IP.key}" "127.0.0.1" } } - span(2) { + span(3) { name "HTTP GET" kind CLIENT childOf(span(0)) } - span(3) { + span(4) { name "test-http-server" kind SERVER - childOf(span(2)) + childOf(span(3)) } } } @@ -100,7 +110,7 @@ class ReactorNettyConnectionSpanTest extends InstrumentationSpecification implem and: assertTraces(1) { - trace(0, 2) { + trace(0, 3) { span(0) { name "parent" kind INTERNAL @@ -109,6 +119,16 @@ class ReactorNettyConnectionSpanTest extends InstrumentationSpecification implem errorEvent(thrownException.class, thrownException.message) } span(1) { + name "RESOLVE" + kind INTERNAL + childOf span(0) + attributes { + "${SemanticAttributes.NET_TRANSPORT.key}" IP_TCP + "${SemanticAttributes.NET_PEER_NAME.key}" "localhost" + "${SemanticAttributes.NET_PEER_PORT.key}" PortUtils.UNUSABLE_PORT + } + } + span(2) { name "CONNECT" kind INTERNAL childOf(span(0)) From 0b1ed5ef89893c8eced7611c6320528f89fea253 Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Fri, 5 Nov 2021 07:13:36 +0100 Subject: [PATCH 3/3] Update instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java Co-authored-by: Trask Stalnaker --- .../netty/v4_1/client/InstrumentedAddressResolverGroup.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java index 5c020ce430de..1cb5438229d1 100644 --- a/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java +++ b/instrumentation/netty/netty-4.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/netty/v4_1/client/InstrumentedAddressResolverGroup.java @@ -51,6 +51,8 @@ public void close() { @Override protected AddressResolver newResolver(EventExecutor eventExecutor) { + // this method is called from the super class's implementation of `getResolver` which is + // overridden by this class throw new UnsupportedOperationException("This method should never be called"); }