Split out :instrumentation:netty:netty-4.1 library (#6820)

Resolves #6734. Builds on #6811.
This commit is contained in:
jack-berg 2022-10-10 18:01:14 -05:00 committed by GitHub
parent 77035fc88c
commit d5aadbab04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 550 additions and 177 deletions

View File

@ -153,6 +153,11 @@ public abstract class AbstractNettyChannelPipelineInstrumentation implements Typ
.getName()
.startsWith("io.opentelemetry.javaagent.instrumentation.netty.")) {
pipeline.removeLast();
} else if (handler
.getClass()
.getName()
.startsWith("io.opentelemetry.instrumentation.netty.")) {
pipeline.removeLast();
}
}
}

View File

@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4.common.internal;
package io.opentelemetry.instrumentation.netty.v4.common;
import com.google.auto.value.AutoValue;
import io.netty.channel.Channel;
@ -11,23 +11,29 @@ import io.netty.handler.codec.http.HttpRequest;
import java.net.SocketAddress;
import javax.annotation.Nullable;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
/** A tuple of an {@link HttpRequest} and a {@link Channel}. */
@AutoValue
public abstract class HttpRequestAndChannel {
/** Create a new {@link HttpRequestAndChannel}. */
public static HttpRequestAndChannel create(HttpRequest request, Channel channel) {
return new AutoValue_HttpRequestAndChannel(request, channel, channel.remoteAddress());
}
/** Returns the {@link HttpRequest}. */
public abstract HttpRequest request();
/** Returns the {@link Channel}. */
public abstract Channel channel();
// we're capturing the remote address early because in case of timeouts or other connection issues
// netty may return null when calling Channel.remoteAddress() at the end of processing
/**
* Return the {@link Channel#remoteAddress()} present when this {@link HttpRequestAndChannel} was
* created.
*
* <p>We capture the remote address early because netty may return null when calling {@link
* Channel#remoteAddress()} at the end of processing in cases of timeouts or other connection
* issues.
*/
@Nullable
public abstract SocketAddress remoteAddress();
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.netty.v4.common.internal;
import io.netty.channel.ChannelHandler;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at

View File

@ -6,7 +6,7 @@
package io.opentelemetry.instrumentation.netty.v4.common.internal.client;
import io.opentelemetry.context.propagation.TextMapSetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
enum HttpRequestHeadersSetter implements TextMapSetter<HttpRequestAndChannel> {
INSTANCE;

View File

@ -7,7 +7,8 @@ package io.opentelemetry.instrumentation.netty.v4.common.internal.client;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
@ -19,7 +20,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributes
import io.opentelemetry.instrumentation.api.instrumenter.net.PeerServiceAttributesExtractor;
import io.opentelemetry.instrumentation.netty.common.internal.HttpClientSpanKeyAttributesExtractor;
import io.opentelemetry.instrumentation.netty.common.internal.NettyConnectionRequest;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.util.List;
import java.util.Map;
@ -29,35 +30,36 @@ import java.util.Map;
*/
public final class NettyClientInstrumenterFactory {
private final OpenTelemetry openTelemetry;
private final String instrumentationName;
private final boolean connectionTelemetryEnabled;
private final boolean sslTelemetryEnabled;
private final List<String> capturedRequestHeaders;
private final List<String> capturedResponseHeaders;
private final Map<String, String> peerServiceMapping;
public NettyClientInstrumenterFactory(
OpenTelemetry openTelemetry,
String instrumentationName,
boolean connectionTelemetryEnabled,
boolean sslTelemetryEnabled,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders,
Map<String, String> peerServiceMapping) {
this.openTelemetry = openTelemetry;
this.instrumentationName = instrumentationName;
this.connectionTelemetryEnabled = connectionTelemetryEnabled;
this.sslTelemetryEnabled = sslTelemetryEnabled;
this.capturedRequestHeaders = capturedRequestHeaders;
this.capturedResponseHeaders = capturedResponseHeaders;
this.peerServiceMapping = peerServiceMapping;
}
public Instrumenter<HttpRequestAndChannel, HttpResponse> createHttpInstrumenter() {
public Instrumenter<HttpRequestAndChannel, HttpResponse> createHttpInstrumenter(
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders,
List<AttributesExtractor<HttpRequestAndChannel, HttpResponse>>
additionalHttpAttributeExtractors) {
NettyHttpClientAttributesGetter httpClientAttributesGetter =
new NettyHttpClientAttributesGetter();
NettyNetClientAttributesGetter netAttributesGetter = new NettyNetClientAttributesGetter();
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
GlobalOpenTelemetry.get(),
openTelemetry,
instrumentationName,
HttpSpanNameExtractor.create(httpClientAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpClientAttributesGetter))
@ -69,6 +71,7 @@ public final class NettyClientInstrumenterFactory {
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractor(
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))
.addAttributesExtractors(additionalHttpAttributeExtractors)
.addOperationMetrics(HttpClientMetrics.get())
.buildClientInstrumenter(HttpRequestHeadersSetter.INSTANCE);
}
@ -78,7 +81,7 @@ public final class NettyClientInstrumenterFactory {
InstrumenterBuilder<NettyConnectionRequest, Channel> instrumenterBuilder =
Instrumenter.<NettyConnectionRequest, Channel>builder(
GlobalOpenTelemetry.get(), instrumentationName, NettyConnectionRequest::spanName)
openTelemetry, instrumentationName, NettyConnectionRequest::spanName)
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractor(
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping));
@ -108,7 +111,7 @@ public final class NettyClientInstrumenterFactory {
NettySslNetAttributesGetter netAttributesGetter = new NettySslNetAttributesGetter();
Instrumenter<NettySslRequest, Void> instrumenter =
Instrumenter.<NettySslRequest, Void>builder(
GlobalOpenTelemetry.get(), instrumentationName, NettySslRequest::spanName)
openTelemetry, instrumentationName, NettySslRequest::spanName)
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractor(
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))

View File

@ -9,7 +9,7 @@ import static io.opentelemetry.instrumentation.netty.v4.common.internal.HttpSche
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesGetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

View File

@ -11,7 +11,7 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTr
import io.netty.channel.socket.DatagramChannel;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetClientAttributesGetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import javax.annotation.Nullable;

View File

@ -6,7 +6,7 @@
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import javax.annotation.Nullable;
enum HttpRequestHeadersGetter implements TextMapGetter<HttpRequestAndChannel> {

View File

@ -9,7 +9,7 @@ import static io.opentelemetry.instrumentation.netty.v4.common.internal.HttpSche
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesGetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.util.List;
import javax.annotation.Nullable;

View File

@ -10,7 +10,7 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTr
import io.netty.channel.socket.DatagramChannel;
import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetServerAttributesGetter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import javax.annotation.Nullable;

View File

@ -6,7 +6,7 @@
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteHolder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
@ -15,7 +15,7 @@ import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtrac
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor;
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.util.List;
/**
@ -25,6 +25,7 @@ import java.util.List;
public final class NettyServerInstrumenterFactory {
public static Instrumenter<HttpRequestAndChannel, HttpResponse> create(
OpenTelemetry openTelemetry,
String instrumentationName,
List<String> capturedRequestHeaders,
List<String> capturedResponseHeaders) {
@ -32,9 +33,7 @@ public final class NettyServerInstrumenterFactory {
NettyHttpServerAttributesGetter httpAttributesGetter = new NettyHttpServerAttributesGetter();
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
GlobalOpenTelemetry.get(),
instrumentationName,
HttpSpanNameExtractor.create(httpAttributesGetter))
openTelemetry, instrumentationName, HttpSpanNameExtractor.create(httpAttributesGetter))
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
.addAttributesExtractor(
HttpServerAttributesExtractor.builder(httpAttributesGetter)

View File

@ -15,7 +15,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.util.Attribute;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import net.bytebuddy.asm.Advice;

View File

@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.netty.v4_0;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

View File

@ -14,7 +14,7 @@ import io.netty.handler.codec.http.HttpRequest;
import io.netty.util.Attribute;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {

View File

@ -15,7 +15,7 @@ import io.netty.handler.codec.http.LastHttpContent;
import io.netty.util.Attribute;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter {

View File

@ -6,14 +6,16 @@
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyClientInstrumenterFactory;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
import java.util.Collections;
public final class NettyClientSingletons {
@ -42,13 +44,16 @@ public final class NettyClientSingletons {
static {
NettyClientInstrumenterFactory factory =
new NettyClientInstrumenterFactory(
GlobalOpenTelemetry.get(),
"io.opentelemetry.netty-4.0",
connectionTelemetryEnabled,
sslTelemetryEnabled,
CommonConfig.get().getPeerServiceMapping());
INSTRUMENTER =
factory.createHttpInstrumenter(
CommonConfig.get().getClientRequestHeaders(),
CommonConfig.get().getClientResponseHeaders(),
CommonConfig.get().getPeerServiceMapping());
INSTRUMENTER = factory.createHttpInstrumenter();
Collections.emptyList());
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
SSL_INSTRUMENTER = factory.createSslInstrumenter();
}

View File

@ -14,7 +14,7 @@ import io.netty.handler.codec.http.HttpRequest;
import io.netty.util.Attribute;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {

View File

@ -15,7 +15,7 @@ import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
import javax.annotation.Nullable;

View File

@ -6,8 +6,9 @@
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
@ -15,6 +16,7 @@ public final class NettyServerSingletons {
private static final Instrumenter<HttpRequestAndChannel, HttpResponse> INSTRUMENTER =
NettyServerInstrumenterFactory.create(
GlobalOpenTelemetry.get(),
"io.opentelemetry.netty-4.0",
CommonConfig.get().getServerRequestHeaders(),
CommonConfig.get().getServerResponseHeaders());

View File

@ -25,6 +25,7 @@ muzzle {
dependencies {
library("io.netty:netty-codec-http:4.1.0.Final")
implementation(project(":instrumentation:netty:netty-4.1:library"))
implementation(project(":instrumentation:netty:netty-4-common:javaagent"))
implementation(project(":instrumentation:netty:netty-4-common:library"))
implementation(project(":instrumentation:netty:netty-common:library"))

View File

@ -5,7 +5,8 @@
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.instrumenter;
import static io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler.HTTP_REQUEST;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyClientSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@ -14,10 +15,10 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.util.Attribute;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@ -51,8 +52,7 @@ public class AbstractChannelHandlerContextInstrumentation implements TypeInstrum
if (clientContext != null) {
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).remove();
contextAttr.remove();
HttpRequestAndChannel request =
ctx.channel().attr(NettyClientSingletons.HTTP_REQUEST).getAndRemove();
HttpRequestAndChannel request = ctx.channel().attr(HTTP_REQUEST).getAndRemove();
instrumenter().end(clientContext, request, null, throwable);
return;
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.connectionInstrumenter;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyClientSingletons.connectionInstrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;

View File

@ -12,6 +12,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
import io.netty.channel.Channel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;

View File

@ -5,7 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.sslInstrumenter;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.NettyClientSingletons.sslInstrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
@ -22,15 +22,15 @@ import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpServerCodec;
import io.opentelemetry.instrumentation.api.util.VirtualField;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumentationHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientResponseTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerRequestTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerResponseTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerTracingHandler;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.netty.v4.common.AbstractNettyChannelPipelineInstrumentation;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientRequestTracingHandler;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientResponseTracingHandler;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerRequestTracingHandler;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerResponseTracingHandler;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.HttpServerTracingHandler;
import net.bytebuddy.asm.Advice;
public class NettyChannelPipelineInstrumentation
@ -105,18 +105,18 @@ public class NettyChannelPipelineInstrumentation
ChannelHandler ourHandler = null;
// Server pipeline handlers
if (handler instanceof HttpServerCodec) {
ourHandler = new HttpServerTracingHandler();
ourHandler = new HttpServerTracingHandler(NettyServerSingletons.instrumenter());
} else if (handler instanceof HttpRequestDecoder) {
ourHandler = new HttpServerRequestTracingHandler();
ourHandler = new HttpServerRequestTracingHandler(NettyServerSingletons.instrumenter());
} else if (handler instanceof HttpResponseEncoder) {
ourHandler = new HttpServerResponseTracingHandler();
ourHandler = new HttpServerResponseTracingHandler(NettyServerSingletons.instrumenter());
// Client pipeline handlers
} else if (handler instanceof HttpClientCodec) {
ourHandler = new HttpClientTracingHandler();
ourHandler = new HttpClientTracingHandler(NettyClientSingletons.instrumenter());
} else if (handler instanceof HttpRequestEncoder) {
ourHandler = new HttpClientRequestTracingHandler();
ourHandler = new HttpClientRequestTracingHandler(NettyClientSingletons.instrumenter());
} else if (handler instanceof HttpResponseDecoder) {
ourHandler = new HttpClientResponseTracingHandler();
ourHandler = new HttpClientResponseTracingHandler(NettyClientSingletons.instrumenter());
// the SslHandler lives in the netty-handler module, using class name comparison to avoid
// adding a dependency
} else if (handler.getClass().getName().equals("io.netty.handler.ssl.SslHandler")) {

View File

@ -3,26 +3,22 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client;
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.AttributeKey;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyClientInstrumenterFactory;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
import java.util.Collections;
public final class NettyClientSingletons {
public static final AttributeKey<HttpRequestAndChannel> HTTP_REQUEST =
AttributeKey.valueOf(NettyClientSingletons.class, "http-client-request");
static final AttributeKey<HttpResponse> HTTP_RESPONSE =
AttributeKey.valueOf(NettyClientSingletons.class, "http-client-response");
private static final boolean connectionTelemetryEnabled;
private static final boolean sslTelemetryEnabled;
@ -48,13 +44,16 @@ public final class NettyClientSingletons {
static {
NettyClientInstrumenterFactory factory =
new NettyClientInstrumenterFactory(
GlobalOpenTelemetry.get(),
"io.opentelemetry.netty-4.1",
connectionTelemetryEnabled,
sslTelemetryEnabled,
CommonConfig.get().getPeerServiceMapping());
INSTRUMENTER =
factory.createHttpInstrumenter(
CommonConfig.get().getClientRequestHeaders(),
CommonConfig.get().getClientResponseHeaders(),
CommonConfig.get().getPeerServiceMapping());
INSTRUMENTER = factory.createHttpInstrumenter();
Collections.emptyList());
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
SSL_INSTRUMENTER = factory.createSslInstrumenter();
}

View File

@ -3,24 +3,20 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server;
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.AttributeKey;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory;
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
public final class NettyServerSingletons {
static final AttributeKey<HttpRequestAndChannel> HTTP_REQUEST =
AttributeKey.valueOf(NettyServerSingletons.class, "http-server-request");
static final AttributeKey<HttpResponse> HTTP_RESPONSE =
AttributeKey.valueOf(NettyServerSingletons.class, "http-server-response");
private static final Instrumenter<HttpRequestAndChannel, HttpResponse> INSTRUMENTER =
NettyServerInstrumenterFactory.create(
GlobalOpenTelemetry.get(),
"io.opentelemetry.netty-4.1",
CommonConfig.get().getServerRequestHeaders(),
CommonConfig.get().getServerResponseHeaders());

View File

@ -1,17 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client;
import io.netty.channel.CombinedChannelDuplexHandler;
public class HttpClientTracingHandler
extends CombinedChannelDuplexHandler<
HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> {
public HttpClientTracingHandler() {
super(new HttpClientResponseTracingHandler(), new HttpClientRequestTracingHandler());
}
}

View File

@ -1,17 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server;
import io.netty.channel.CombinedChannelDuplexHandler;
public class HttpServerTracingHandler
extends CombinedChannelDuplexHandler<
HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> {
public HttpServerTracingHandler() {
super(new HttpServerRequestTracingHandler(), new HttpServerResponseTracingHandler());
}
}

View File

@ -8,7 +8,7 @@ import io.netty.channel.DefaultChannelPipeline
import io.netty.channel.embedded.EmbeddedChannel
import io.netty.handler.codec.http.HttpClientCodec
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler
import spock.lang.Unroll
@Unroll
@ -31,7 +31,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
channelPipeline.addLast("http", handler)
channelPipeline.first() == handler
// our handler was also added
channelPipeline.last().getClass() == HttpClientTracingHandler
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
and:
removeMethod.call(channelPipeline, handler)
@ -70,7 +70,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
then: "noop handler was removed; http and instrumentation handlers were added"
channelPipeline.size() == 2
channelPipeline.first() == httpHandler
channelPipeline.last().getClass() == HttpClientTracingHandler
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
when:
def anotherNoopHandler = new NoopChannelHandler()
@ -103,7 +103,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
then: "add http and instrumentation handlers"
channelPipeline.size() == 2
channelPipeline.first() == httpHandler
channelPipeline.last().getClass() == HttpClientTracingHandler
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
when:
def noopHandler = new NoopChannelHandler()
@ -120,7 +120,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
then: "http and instrumentation handlers will be remained"
channelPipeline.size() == 2
channelPipeline.first() == httpHandler
channelPipeline.last().getClass() == HttpClientTracingHandler
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
when:
channelPipeline.removeLast()

View File

@ -30,7 +30,6 @@ import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.HttpClientTracingHandler
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import spock.lang.Shared
import spock.lang.Unroll
@ -253,7 +252,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
then:
// The first one returns the removed tracing handler
pipeline.remove(HttpClientTracingHandler.getName()) != null
pipeline.remove("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler") != null
}
def "when a handler is added to the netty pipeline we add ONLY ONE tracing handler"() {
@ -264,9 +263,9 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
when:
pipeline.addLast("name", new HttpClientCodec())
// The first one returns the removed tracing handler
pipeline.remove(HttpClientTracingHandler.getName())
pipeline.remove("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler")
// There is only one
pipeline.remove(HttpClientTracingHandler.getName()) == null
pipeline.remove("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler") == null
then:
thrown NoSuchElementException
@ -283,7 +282,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
then:
// The first one returns the removed tracing handler
null != pipeline.remove(HttpClientTracingHandler.getName())
null != pipeline.remove("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler")
null != pipeline.remove("some_handler")
null != pipeline.remove("a_traced_handler")
}
@ -311,9 +310,9 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
channel.pipeline().addLast(new TracedHandlerFromInitializerHandler())
then:
null != channel.pipeline().get(HttpClientTracingHandler.getName())
null != channel.pipeline().get("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler")
null != channel.pipeline().remove("added_in_initializer")
null == channel.pipeline().get(HttpClientTracingHandler.getName())
null == channel.pipeline().get("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler")
}
def "request with trace annotated method #method"() {

View File

@ -0,0 +1,9 @@
plugins {
id("otel.library-instrumentation")
}
dependencies {
library("io.netty:netty-codec-http:4.1.0.Final")
implementation(project(":instrumentation:netty:netty-4-common:library"))
implementation(project(":instrumentation:netty:netty-common:library"))
}

View File

@ -0,0 +1,66 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.CombinedChannelDuplexHandler;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientResponseTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler;
/** Entrypoint for instrumenting Netty HTTP clients. */
public final class NettyClientTelemetry {
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
NettyClientTelemetry(Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
/** Returns a new {@link NettyClientTelemetry} configured with the given {@link OpenTelemetry}. */
public static NettyClientTelemetry create(OpenTelemetry openTelemetry) {
return builder(openTelemetry).build();
}
/**
* Returns a new {@link NettyClientTelemetryBuilder} configured with the given {@link
* OpenTelemetry}.
*/
public static NettyClientTelemetryBuilder builder(OpenTelemetry openTelemetry) {
return new NettyClientTelemetryBuilder(openTelemetry);
}
/**
* /** Returns a new {@link ChannelOutboundHandlerAdapter} that generates telemetry for outgoing
* HTTP requests. Must be paired with {@link #createResponseHandler()}.
*/
public ChannelOutboundHandlerAdapter createRequestHandler() {
return new HttpClientRequestTracingHandler(instrumenter);
}
/**
* Returns a new {@link ChannelInboundHandlerAdapter} that generates telemetry for incoming HTTP
* responses. Must be paired with {@link #createRequestHandler()}.
*/
public ChannelInboundHandlerAdapter createResponseHandler() {
return new HttpClientResponseTracingHandler(instrumenter);
}
/**
* Returns a new {@link CombinedChannelDuplexHandler} that generates telemetry for outgoing HTTP
* requests and incoming responses in a single handler.
*/
public CombinedChannelDuplexHandler<
? extends ChannelInboundHandlerAdapter, ? extends ChannelOutboundHandlerAdapter>
createCombinedHandler() {
return new HttpClientTracingHandler(instrumenter);
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyClientInstrumenterFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** A builder of {@link NettyClientTelemetry}. */
public final class NettyClientTelemetryBuilder {
private final OpenTelemetry openTelemetry;
private List<String> capturedRequestHeaders = Collections.emptyList();
private List<String> capturedResponseHeaders = Collections.emptyList();
private final List<AttributesExtractor<HttpRequestAndChannel, HttpResponse>>
additionalAttributesExtractors = new ArrayList<>();
NettyClientTelemetryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
}
/**
* Configures the HTTP request headers that will be captured as span attributes.
*
* @param capturedRequestHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public NettyClientTelemetryBuilder setCapturedRequestHeaders(
List<String> capturedRequestHeaders) {
this.capturedRequestHeaders = capturedRequestHeaders;
return this;
}
/**
* Configures the HTTP response headers that will be captured as span attributes.
*
* @param capturedResponseHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public NettyClientTelemetryBuilder setCapturedResponseHeaders(
List<String> capturedResponseHeaders) {
this.capturedResponseHeaders = capturedResponseHeaders;
return this;
}
/**
* Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented
* items.
*/
@CanIgnoreReturnValue
public NettyClientTelemetryBuilder addAttributesExtractor(
AttributesExtractor<HttpRequestAndChannel, HttpResponse> attributesExtractor) {
additionalAttributesExtractors.add(attributesExtractor);
return this;
}
/** Returns a new {@link NettyClientTelemetry} with the given configuration. */
public NettyClientTelemetry build() {
return new NettyClientTelemetry(
new NettyClientInstrumenterFactory(
openTelemetry, "io.opentelemetry.netty-4.1", false, false, Collections.emptyMap())
.createHttpInstrumenter(
capturedRequestHeaders, capturedResponseHeaders, additionalAttributesExtractors));
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.CombinedChannelDuplexHandler;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerRequestTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerResponseTracingHandler;
import io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerTracingHandler;
/** Entrypoint for instrumenting Netty HTTP servers. */
public final class NettyServerTelemetry {
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
NettyServerTelemetry(Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
/** Returns a new {@link NettyServerTelemetry} configured with the given {@link OpenTelemetry}. */
public static NettyServerTelemetry create(OpenTelemetry openTelemetry) {
return builder(openTelemetry).build();
}
/**
* Returns a new {@link NettyServerTelemetryBuilder} configured with the given {@link
* OpenTelemetry}.
*/
public static NettyServerTelemetryBuilder builder(OpenTelemetry openTelemetry) {
return new NettyServerTelemetryBuilder(openTelemetry);
}
/**
* Returns a new {@link ChannelInboundHandlerAdapter} that generates telemetry for incoming HTTP
* requests. Must be paired with {@link #createResponseHandler()}.
*/
public ChannelInboundHandlerAdapter createRequestHandler() {
return new HttpServerRequestTracingHandler(instrumenter);
}
/**
* Returns a new {@link ChannelOutboundHandlerAdapter} that generates telemetry for outgoing HTTP
* responses. Must be paired with {@link #createRequestHandler()}.
*/
public ChannelOutboundHandlerAdapter createResponseHandler() {
return new HttpServerResponseTracingHandler(instrumenter);
}
/**
* Returns a new {@link CombinedChannelDuplexHandler} that generates telemetry for incoming HTTP
* requests and outgoing responses in a single handler.
*/
public CombinedChannelDuplexHandler<
? extends ChannelInboundHandlerAdapter, ? extends ChannelOutboundHandlerAdapter>
createCombinedHandler() {
return new HttpServerTracingHandler(instrumenter);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory;
import java.util.Collections;
import java.util.List;
/** A builder of {@link NettyServerTelemetry}. */
public final class NettyServerTelemetryBuilder {
private final OpenTelemetry openTelemetry;
private List<String> capturedRequestHeaders = Collections.emptyList();
private List<String> capturedResponseHeaders = Collections.emptyList();
NettyServerTelemetryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
}
/**
* Configures the HTTP request headers that will be captured as span attributes.
*
* @param capturedRequestHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public NettyServerTelemetryBuilder setCapturedRequestHeaders(
List<String> capturedRequestHeaders) {
this.capturedRequestHeaders = capturedRequestHeaders;
return this;
}
/**
* Configures the HTTP response headers that will be captured as span attributes.
*
* @param capturedResponseHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public NettyServerTelemetryBuilder setCapturedResponseHeaders(
List<String> capturedResponseHeaders) {
this.capturedResponseHeaders = capturedResponseHeaders;
return this;
}
/** Returns a new {@link NettyServerTelemetry} with the given configuration. */
public NettyServerTelemetry build() {
return new NettyServerTelemetry(
NettyServerInstrumenterFactory.create(
openTelemetry,
"io.opentelemetry.netty-4.1",
capturedRequestHeaders,
capturedResponseHeaders));
}
}

View File

@ -3,11 +3,15 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
package io.opentelemetry.instrumentation.netty.v4_1.internal;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class AttributeKeys {
public static final AttributeKey<Context> WRITE_CONTEXT =

View File

@ -3,23 +3,37 @@
* 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.HTTP_REQUEST;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.instrumenter;
package io.opentelemetry.instrumentation.netty.v4_1.internal.client;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {
public static final AttributeKey<HttpRequestAndChannel> HTTP_REQUEST =
AttributeKey.valueOf(HttpClientRequestTracingHandler.class, "http-client-request");
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
public HttpClientRequestTracingHandler(
Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
if (!(msg instanceof HttpRequest)) {
@ -27,13 +41,13 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return;
}
Context parentContext = ctx.channel().attr(AttributeKeys.WRITE_CONTEXT).getAndRemove();
Context parentContext = ctx.channel().attr(AttributeKeys.WRITE_CONTEXT).getAndSet(null);
if (parentContext == null) {
parentContext = Context.current();
}
HttpRequestAndChannel request = HttpRequestAndChannel.create((HttpRequest) msg, ctx.channel());
if (!instrumenter().shouldStart(parentContext, request) || isAwsRequest(request)) {
if (!instrumenter.shouldStart(parentContext, request) || isAwsRequest(request)) {
ctx.write(msg, prm);
return;
}
@ -42,7 +56,7 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
Attribute<HttpRequestAndChannel> requestAttr = ctx.channel().attr(HTTP_REQUEST);
Context context = instrumenter().start(parentContext, request);
Context context = instrumenter.start(parentContext, request);
parentContextAttr.set(parentContext);
contextAttr.set(context);
requestAttr.set(request);
@ -51,8 +65,8 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
ctx.write(msg, prm);
// span is ended normally in HttpClientResponseTracingHandler
} catch (Throwable throwable) {
instrumenter().end(contextAttr.getAndRemove(), requestAttr.getAndRemove(), null, throwable);
parentContextAttr.remove();
instrumenter.end(contextAttr.getAndSet(null), requestAttr.getAndSet(null), null, throwable);
parentContextAttr.set(null);
throw throwable;
}
}

View File

@ -3,10 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.client;
package io.opentelemetry.instrumentation.netty.v4_1.internal.client;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.HTTP_RESPONSE;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.instrumenter;
import static io.opentelemetry.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler.HTTP_REQUEST;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
@ -14,13 +13,29 @@ import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter {
private static final AttributeKey<HttpResponse> HTTP_RESPONSE =
AttributeKey.valueOf(HttpClientResponseTracingHandler.class, "http-client-response");
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
public HttpClientResponseTracingHandler(
Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
@ -31,25 +46,24 @@ public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapt
}
Attribute<Context> parentContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT);
Attribute<HttpRequestAndChannel> requestAttr =
ctx.channel().attr(NettyClientSingletons.HTTP_REQUEST);
Attribute<HttpRequestAndChannel> requestAttr = ctx.channel().attr(HTTP_REQUEST);
Context parentContext = parentContextAttr.get();
HttpRequestAndChannel request = requestAttr.get();
if (msg instanceof FullHttpResponse) {
parentContextAttr.remove();
contextAttr.remove();
requestAttr.remove();
parentContextAttr.set(null);
contextAttr.set(null);
requestAttr.set(null);
} else if (msg instanceof HttpResponse) {
// Headers before body have been received, store them to use when finishing the span.
ctx.channel().attr(HTTP_RESPONSE).set((HttpResponse) msg);
} else if (msg instanceof LastHttpContent) {
// Not a FullHttpResponse so this is content that has been received after headers. Finish the
// span using what we stored in attrs.
parentContextAttr.remove();
contextAttr.remove();
requestAttr.remove();
parentContextAttr.set(null);
contextAttr.set(null);
requestAttr.set(null);
}
// We want the callback in the scope of the parent, not the client span
@ -62,9 +76,9 @@ public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapt
}
if (msg instanceof FullHttpResponse) {
instrumenter().end(context, request, (HttpResponse) msg, null);
instrumenter.end(context, request, (HttpResponse) msg, null);
} else if (msg instanceof LastHttpContent) {
instrumenter().end(context, request, ctx.channel().attr(HTTP_RESPONSE).getAndRemove(), null);
instrumenter.end(context, request, ctx.channel().attr(HTTP_RESPONSE).getAndSet(null), null);
}
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1.internal.client;
import io.netty.channel.CombinedChannelDuplexHandler;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpClientTracingHandler
extends CombinedChannelDuplexHandler<
HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> {
public HttpClientTracingHandler(Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
super(
new HttpClientResponseTracingHandler(instrumenter),
new HttpClientRequestTracingHandler(instrumenter));
}
}

View File

@ -3,27 +3,42 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.NettyServerSingletons.instrumenter;
package io.opentelemetry.instrumentation.netty.v4_1.internal.server;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
static final AttributeKey<HttpRequestAndChannel> HTTP_REQUEST =
AttributeKey.valueOf(HttpServerRequestTracingHandler.class, "http-server-request");
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
public HttpServerRequestTracingHandler(
Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Channel channel = ctx.channel();
Attribute<Context> contextAttr = channel.attr(AttributeKeys.SERVER_CONTEXT);
Attribute<HttpRequestAndChannel> requestAttr = channel.attr(NettyServerSingletons.HTTP_REQUEST);
Attribute<HttpRequestAndChannel> requestAttr = channel.attr(HTTP_REQUEST);
if (!(msg instanceof HttpRequest)) {
Context serverContext = contextAttr.get();
@ -43,12 +58,12 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
}
HttpRequestAndChannel request = HttpRequestAndChannel.create((HttpRequest) msg, channel);
if (!instrumenter().shouldStart(parentContext, request)) {
if (!instrumenter.shouldStart(parentContext, request)) {
ctx.fireChannelRead(msg);
return;
}
Context context = instrumenter().start(parentContext, request);
Context context = instrumenter.start(parentContext, request);
contextAttr.set(context);
requestAttr.set(request);
@ -57,7 +72,7 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
// the span is ended normally in HttpServerResponseTracingHandler
} catch (Throwable throwable) {
// make sure to remove the server context on end() call
instrumenter().end(contextAttr.getAndRemove(), requestAttr.getAndRemove(), null, throwable);
instrumenter.end(contextAttr.getAndSet(null), requestAttr.getAndSet(null), null, throwable);
throw throwable;
}
}

View File

@ -3,9 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v4_1.server;
package io.opentelemetry.instrumentation.netty.v4_1.internal.server;
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.server.NettyServerSingletons.instrumenter;
import static io.opentelemetry.instrumentation.netty.v4_1.internal.server.HttpServerRequestTracingHandler.HTTP_REQUEST;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@ -16,15 +16,31 @@ import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import javax.annotation.Nullable;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdapter {
static final AttributeKey<HttpResponse> HTTP_RESPONSE =
AttributeKey.valueOf(HttpServerResponseTracingHandler.class, "http-server-response");
private final Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter;
public HttpServerResponseTracingHandler(
Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
this.instrumenter = instrumenter;
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.SERVER_CONTEXT);
@ -59,14 +75,14 @@ public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdap
future ->
end(
ctx.channel(),
ctx.channel().attr(NettyServerSingletons.HTTP_RESPONSE).getAndRemove(),
ctx.channel().attr(HTTP_RESPONSE).getAndSet(null),
writePromise));
}
} else {
writePromise = prm;
if (msg instanceof HttpResponse) {
// Headers before body has been sent, store them to use when finishing the span.
ctx.channel().attr(NettyServerSingletons.HTTP_RESPONSE).set((HttpResponse) msg);
ctx.channel().attr(HTTP_RESPONSE).set((HttpResponse) msg);
}
}
@ -78,17 +94,16 @@ public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdap
}
}
private static void end(Channel channel, HttpResponse response, ChannelFuture future) {
private void end(Channel channel, HttpResponse response, ChannelFuture future) {
Throwable error = future.isSuccess() ? null : future.cause();
end(channel, response, error);
}
// make sure to remove the server context on end() call
private static void end(
Channel channel, @Nullable HttpResponse response, @Nullable Throwable error) {
Context context = channel.attr(AttributeKeys.SERVER_CONTEXT).getAndRemove();
HttpRequestAndChannel request = channel.attr(NettyServerSingletons.HTTP_REQUEST).getAndRemove();
private void end(Channel channel, @Nullable HttpResponse response, @Nullable Throwable error) {
Context context = channel.attr(AttributeKeys.SERVER_CONTEXT).getAndSet(null);
HttpRequestAndChannel request = channel.attr(HTTP_REQUEST).getAndSet(null);
error = NettyErrorHolder.getOrDefault(context, error);
instrumenter().end(context, request, response, error);
instrumenter.end(context, request, response, error);
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.netty.v4_1.internal.server;
import io.netty.channel.CombinedChannelDuplexHandler;
import io.netty.handler.codec.http.HttpResponse;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public class HttpServerTracingHandler
extends CombinedChannelDuplexHandler<
HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> {
public HttpServerTracingHandler(Instrumenter<HttpRequestAndChannel, HttpResponse> instrumenter) {
super(
new HttpServerRequestTracingHandler(instrumenter),
new HttpServerResponseTracingHandler(instrumenter));
}
}

View File

@ -14,6 +14,7 @@ dependencies {
library("io.ratpack:ratpack-core:1.4.0")
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
implementation(project(":instrumentation:netty:netty-4.1:library"))
testImplementation(project(":instrumentation:ratpack:ratpack-1.4:testing"))

View File

@ -11,8 +11,8 @@ import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackSingleto
import io.netty.util.Attribute;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import ratpack.handling.Context;
import ratpack.handling.Handler;

View File

@ -21,6 +21,7 @@ muzzle {
dependencies {
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
implementation(project(":instrumentation:netty:netty-4.1:library"))
library("io.projectreactor.netty:reactor-netty:0.9.0.RELEASE")
testInstrumentation(project(":instrumentation:reactor:reactor-netty:reactor-netty-1.0:javaagent"))

View File

@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9;
import io.netty.channel.Channel;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import reactor.netty.Connection;

View File

@ -6,7 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9;
import io.opentelemetry.context.Context;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import java.util.function.BiConsumer;
import reactor.netty.Connection;
import reactor.netty.http.client.HttpClientRequest;

View File

@ -24,6 +24,7 @@ dependencies {
annotationProcessor("com.google.auto.value:auto-value")
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
implementation(project(":instrumentation:netty:netty-4.1:library"))
implementation(project(":instrumentation:netty:netty-4-common:library"))
implementation(project(":instrumentation:netty:netty-common:library"))
implementation(project(":instrumentation:reactor:reactor-3.1:library"))

View File

@ -11,8 +11,8 @@ import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.React
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
import io.opentelemetry.instrumentation.reactor.ContextPropagationOperator;
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
import java.util.function.BiConsumer;
import java.util.function.Function;
import javax.annotation.Nullable;

View File

@ -72,11 +72,10 @@ public final class ReactorNettySingletons {
NettyClientInstrumenterFactory instrumenterFactory =
new NettyClientInstrumenterFactory(
GlobalOpenTelemetry.get(),
INSTRUMENTATION_NAME,
connectionTelemetryEnabled,
false,
CommonConfig.get().getClientRequestHeaders(),
CommonConfig.get().getClientResponseHeaders(),
CommonConfig.get().getPeerServiceMapping());
CONNECTION_INSTRUMENTER = instrumenterFactory.createConnectionInstrumenter();
}

View File

@ -351,6 +351,7 @@ include(":instrumentation:mongo:mongo-common:testing")
include(":instrumentation:netty:netty-3.8:javaagent")
include(":instrumentation:netty:netty-4.0:javaagent")
include(":instrumentation:netty:netty-4.1:javaagent")
include(":instrumentation:netty:netty-4.1:library")
include(":instrumentation:netty:netty-4-common:javaagent")
include(":instrumentation:netty:netty-4-common:library")
include(":instrumentation:netty:netty-common:library")