Split out :instrumentation:netty:netty-4.1 library (#6820)
Resolves #6734. Builds on #6811.
This commit is contained in:
parent
77035fc88c
commit
d5aadbab04
|
@ -153,6 +153,11 @@ public abstract class AbstractNettyChannelPipelineInstrumentation implements Typ
|
||||||
.getName()
|
.getName()
|
||||||
.startsWith("io.opentelemetry.javaagent.instrumentation.netty.")) {
|
.startsWith("io.opentelemetry.javaagent.instrumentation.netty.")) {
|
||||||
pipeline.removeLast();
|
pipeline.removeLast();
|
||||||
|
} else if (handler
|
||||||
|
.getClass()
|
||||||
|
.getName()
|
||||||
|
.startsWith("io.opentelemetry.instrumentation.netty.")) {
|
||||||
|
pipeline.removeLast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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 com.google.auto.value.AutoValue;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
|
@ -11,23 +11,29 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/** A tuple of an {@link HttpRequest} and a {@link Channel}. */
|
||||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
|
||||||
* any time.
|
|
||||||
*/
|
|
||||||
@AutoValue
|
@AutoValue
|
||||||
public abstract class HttpRequestAndChannel {
|
public abstract class HttpRequestAndChannel {
|
||||||
|
|
||||||
|
/** Create a new {@link HttpRequestAndChannel}. */
|
||||||
public static HttpRequestAndChannel create(HttpRequest request, Channel channel) {
|
public static HttpRequestAndChannel create(HttpRequest request, Channel channel) {
|
||||||
return new AutoValue_HttpRequestAndChannel(request, channel, channel.remoteAddress());
|
return new AutoValue_HttpRequestAndChannel(request, channel, channel.remoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the {@link HttpRequest}. */
|
||||||
public abstract HttpRequest request();
|
public abstract HttpRequest request();
|
||||||
|
|
||||||
|
/** Returns the {@link Channel}. */
|
||||||
public abstract Channel 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
|
@Nullable
|
||||||
public abstract SocketAddress remoteAddress();
|
public abstract SocketAddress remoteAddress();
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
package io.opentelemetry.instrumentation.netty.v4.common.internal;
|
package io.opentelemetry.instrumentation.netty.v4.common.internal;
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandler;
|
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
|
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package io.opentelemetry.instrumentation.netty.v4.common.internal.client;
|
package io.opentelemetry.instrumentation.netty.v4.common.internal.client;
|
||||||
|
|
||||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
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> {
|
enum HttpRequestHeadersSetter implements TextMapSetter<HttpRequestAndChannel> {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
|
|
@ -7,7 +7,8 @@ package io.opentelemetry.instrumentation.netty.v4.common.internal.client;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
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.Instrumenter;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
|
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.api.instrumenter.net.PeerServiceAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.HttpClientSpanKeyAttributesExtractor;
|
import io.opentelemetry.instrumentation.netty.common.internal.HttpClientSpanKeyAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.NettyConnectionRequest;
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -29,35 +30,36 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public final class NettyClientInstrumenterFactory {
|
public final class NettyClientInstrumenterFactory {
|
||||||
|
|
||||||
|
private final OpenTelemetry openTelemetry;
|
||||||
private final String instrumentationName;
|
private final String instrumentationName;
|
||||||
private final boolean connectionTelemetryEnabled;
|
private final boolean connectionTelemetryEnabled;
|
||||||
private final boolean sslTelemetryEnabled;
|
private final boolean sslTelemetryEnabled;
|
||||||
private final List<String> capturedRequestHeaders;
|
|
||||||
private final List<String> capturedResponseHeaders;
|
|
||||||
private final Map<String, String> peerServiceMapping;
|
private final Map<String, String> peerServiceMapping;
|
||||||
|
|
||||||
public NettyClientInstrumenterFactory(
|
public NettyClientInstrumenterFactory(
|
||||||
|
OpenTelemetry openTelemetry,
|
||||||
String instrumentationName,
|
String instrumentationName,
|
||||||
boolean connectionTelemetryEnabled,
|
boolean connectionTelemetryEnabled,
|
||||||
boolean sslTelemetryEnabled,
|
boolean sslTelemetryEnabled,
|
||||||
List<String> capturedRequestHeaders,
|
|
||||||
List<String> capturedResponseHeaders,
|
|
||||||
Map<String, String> peerServiceMapping) {
|
Map<String, String> peerServiceMapping) {
|
||||||
|
this.openTelemetry = openTelemetry;
|
||||||
this.instrumentationName = instrumentationName;
|
this.instrumentationName = instrumentationName;
|
||||||
this.connectionTelemetryEnabled = connectionTelemetryEnabled;
|
this.connectionTelemetryEnabled = connectionTelemetryEnabled;
|
||||||
this.sslTelemetryEnabled = sslTelemetryEnabled;
|
this.sslTelemetryEnabled = sslTelemetryEnabled;
|
||||||
this.capturedRequestHeaders = capturedRequestHeaders;
|
|
||||||
this.capturedResponseHeaders = capturedResponseHeaders;
|
|
||||||
this.peerServiceMapping = peerServiceMapping;
|
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 =
|
NettyHttpClientAttributesGetter httpClientAttributesGetter =
|
||||||
new NettyHttpClientAttributesGetter();
|
new NettyHttpClientAttributesGetter();
|
||||||
NettyNetClientAttributesGetter netAttributesGetter = new NettyNetClientAttributesGetter();
|
NettyNetClientAttributesGetter netAttributesGetter = new NettyNetClientAttributesGetter();
|
||||||
|
|
||||||
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
|
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
|
||||||
GlobalOpenTelemetry.get(),
|
openTelemetry,
|
||||||
instrumentationName,
|
instrumentationName,
|
||||||
HttpSpanNameExtractor.create(httpClientAttributesGetter))
|
HttpSpanNameExtractor.create(httpClientAttributesGetter))
|
||||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpClientAttributesGetter))
|
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpClientAttributesGetter))
|
||||||
|
@ -69,6 +71,7 @@ public final class NettyClientInstrumenterFactory {
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))
|
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))
|
||||||
|
.addAttributesExtractors(additionalHttpAttributeExtractors)
|
||||||
.addOperationMetrics(HttpClientMetrics.get())
|
.addOperationMetrics(HttpClientMetrics.get())
|
||||||
.buildClientInstrumenter(HttpRequestHeadersSetter.INSTANCE);
|
.buildClientInstrumenter(HttpRequestHeadersSetter.INSTANCE);
|
||||||
}
|
}
|
||||||
|
@ -78,7 +81,7 @@ public final class NettyClientInstrumenterFactory {
|
||||||
|
|
||||||
InstrumenterBuilder<NettyConnectionRequest, Channel> instrumenterBuilder =
|
InstrumenterBuilder<NettyConnectionRequest, Channel> instrumenterBuilder =
|
||||||
Instrumenter.<NettyConnectionRequest, Channel>builder(
|
Instrumenter.<NettyConnectionRequest, Channel>builder(
|
||||||
GlobalOpenTelemetry.get(), instrumentationName, NettyConnectionRequest::spanName)
|
openTelemetry, instrumentationName, NettyConnectionRequest::spanName)
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping));
|
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping));
|
||||||
|
@ -108,7 +111,7 @@ public final class NettyClientInstrumenterFactory {
|
||||||
NettySslNetAttributesGetter netAttributesGetter = new NettySslNetAttributesGetter();
|
NettySslNetAttributesGetter netAttributesGetter = new NettySslNetAttributesGetter();
|
||||||
Instrumenter<NettySslRequest, Void> instrumenter =
|
Instrumenter<NettySslRequest, Void> instrumenter =
|
||||||
Instrumenter.<NettySslRequest, Void>builder(
|
Instrumenter.<NettySslRequest, Void>builder(
|
||||||
GlobalOpenTelemetry.get(), instrumentationName, NettySslRequest::spanName)
|
openTelemetry, instrumentationName, NettySslRequest::spanName)
|
||||||
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
.addAttributesExtractor(NetClientAttributesExtractor.create(netAttributesGetter))
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))
|
PeerServiceAttributesExtractor.create(netAttributesGetter, peerServiceMapping))
|
||||||
|
|
|
@ -9,7 +9,7 @@ import static io.opentelemetry.instrumentation.netty.v4.common.internal.HttpSche
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesGetter;
|
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.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTr
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetClientAttributesGetter;
|
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.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
|
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
|
||||||
|
|
||||||
import io.opentelemetry.context.propagation.TextMapGetter;
|
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;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
enum HttpRequestHeadersGetter implements TextMapGetter<HttpRequestAndChannel> {
|
enum HttpRequestHeadersGetter implements TextMapGetter<HttpRequestAndChannel> {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import static io.opentelemetry.instrumentation.netty.v4.common.internal.HttpSche
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesGetter;
|
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 java.util.List;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTr
|
||||||
|
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.InetSocketAddressNetServerAttributesGetter;
|
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.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
|
package io.opentelemetry.instrumentation.netty.v4.common.internal.server;
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
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.Instrumenter;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteHolder;
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteHolder;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
|
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.http.HttpSpanStatusExtractor;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor;
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetServerAttributesExtractor;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +25,7 @@ import java.util.List;
|
||||||
public final class NettyServerInstrumenterFactory {
|
public final class NettyServerInstrumenterFactory {
|
||||||
|
|
||||||
public static Instrumenter<HttpRequestAndChannel, HttpResponse> create(
|
public static Instrumenter<HttpRequestAndChannel, HttpResponse> create(
|
||||||
|
OpenTelemetry openTelemetry,
|
||||||
String instrumentationName,
|
String instrumentationName,
|
||||||
List<String> capturedRequestHeaders,
|
List<String> capturedRequestHeaders,
|
||||||
List<String> capturedResponseHeaders) {
|
List<String> capturedResponseHeaders) {
|
||||||
|
@ -32,9 +33,7 @@ public final class NettyServerInstrumenterFactory {
|
||||||
NettyHttpServerAttributesGetter httpAttributesGetter = new NettyHttpServerAttributesGetter();
|
NettyHttpServerAttributesGetter httpAttributesGetter = new NettyHttpServerAttributesGetter();
|
||||||
|
|
||||||
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
|
return Instrumenter.<HttpRequestAndChannel, HttpResponse>builder(
|
||||||
GlobalOpenTelemetry.get(),
|
openTelemetry, instrumentationName, HttpSpanNameExtractor.create(httpAttributesGetter))
|
||||||
instrumentationName,
|
|
||||||
HttpSpanNameExtractor.create(httpAttributesGetter))
|
|
||||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
||||||
.addAttributesExtractor(
|
.addAttributesExtractor(
|
||||||
HttpServerAttributesExtractor.builder(httpAttributesGetter)
|
HttpServerAttributesExtractor.builder(httpAttributesGetter)
|
||||||
|
|
|
@ -15,7 +15,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
|
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.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
|
@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.netty.v4_0;
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.util.AttributeKey;
|
import io.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
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.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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;
|
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
|
||||||
|
|
||||||
public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {
|
public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import io.netty.handler.codec.http.LastHttpContent;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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;
|
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
|
||||||
|
|
||||||
public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter {
|
public class HttpClientResponseTracingHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
|
@ -6,14 +6,16 @@
|
||||||
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client;
|
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.client;
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
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.NettyClientInstrumenterFactory;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
|
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
|
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
|
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public final class NettyClientSingletons {
|
public final class NettyClientSingletons {
|
||||||
|
|
||||||
|
@ -42,13 +44,16 @@ public final class NettyClientSingletons {
|
||||||
static {
|
static {
|
||||||
NettyClientInstrumenterFactory factory =
|
NettyClientInstrumenterFactory factory =
|
||||||
new NettyClientInstrumenterFactory(
|
new NettyClientInstrumenterFactory(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
"io.opentelemetry.netty-4.0",
|
"io.opentelemetry.netty-4.0",
|
||||||
connectionTelemetryEnabled,
|
connectionTelemetryEnabled,
|
||||||
sslTelemetryEnabled,
|
sslTelemetryEnabled,
|
||||||
|
CommonConfig.get().getPeerServiceMapping());
|
||||||
|
INSTRUMENTER =
|
||||||
|
factory.createHttpInstrumenter(
|
||||||
CommonConfig.get().getClientRequestHeaders(),
|
CommonConfig.get().getClientRequestHeaders(),
|
||||||
CommonConfig.get().getClientResponseHeaders(),
|
CommonConfig.get().getClientResponseHeaders(),
|
||||||
CommonConfig.get().getPeerServiceMapping());
|
Collections.emptyList());
|
||||||
INSTRUMENTER = factory.createHttpInstrumenter();
|
|
||||||
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
|
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
|
||||||
SSL_INSTRUMENTER = factory.createSslInstrumenter();
|
SSL_INSTRUMENTER = factory.createSslInstrumenter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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;
|
import io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
|
||||||
|
|
||||||
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
|
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 io.opentelemetry.javaagent.instrumentation.netty.v4_0.AttributeKeys;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server;
|
package io.opentelemetry.javaagent.instrumentation.netty.v4_0.server;
|
||||||
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
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.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ public final class NettyServerSingletons {
|
||||||
|
|
||||||
private static final Instrumenter<HttpRequestAndChannel, HttpResponse> INSTRUMENTER =
|
private static final Instrumenter<HttpRequestAndChannel, HttpResponse> INSTRUMENTER =
|
||||||
NettyServerInstrumenterFactory.create(
|
NettyServerInstrumenterFactory.create(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
"io.opentelemetry.netty-4.0",
|
"io.opentelemetry.netty-4.0",
|
||||||
CommonConfig.get().getServerRequestHeaders(),
|
CommonConfig.get().getServerRequestHeaders(),
|
||||||
CommonConfig.get().getServerResponseHeaders());
|
CommonConfig.get().getServerResponseHeaders());
|
||||||
|
|
|
@ -25,6 +25,7 @@ muzzle {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
library("io.netty:netty-codec-http:4.1.0.Final")
|
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:javaagent"))
|
||||||
implementation(project(":instrumentation:netty:netty-4-common:library"))
|
implementation(project(":instrumentation:netty:netty-4-common:library"))
|
||||||
implementation(project(":instrumentation:netty:netty-common:library"))
|
implementation(project(":instrumentation:netty:netty-common:library"))
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
|
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.isMethod;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
@ -14,10 +15,10 @@ import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
|
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.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
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.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
@ -51,8 +52,7 @@ public class AbstractChannelHandlerContextInstrumentation implements TypeInstrum
|
||||||
if (clientContext != null) {
|
if (clientContext != null) {
|
||||||
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).remove();
|
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT).remove();
|
||||||
contextAttr.remove();
|
contextAttr.remove();
|
||||||
HttpRequestAndChannel request =
|
HttpRequestAndChannel request = ctx.channel().attr(HTTP_REQUEST).getAndRemove();
|
||||||
ctx.channel().attr(NettyClientSingletons.HTTP_REQUEST).getAndRemove();
|
|
||||||
instrumenter().end(clientContext, request, null, throwable);
|
instrumenter().end(clientContext, request, null, throwable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
|
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.isConstructor;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
|
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
|
||||||
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
|
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.netty.v4_1;
|
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.isMethod;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
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.netty.handler.codec.http.HttpServerCodec;
|
||||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
|
import io.opentelemetry.instrumentation.api.util.VirtualField;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumentationHandler;
|
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.bootstrap.CallDepth;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
import io.opentelemetry.javaagent.instrumentation.netty.v4.common.AbstractNettyChannelPipelineInstrumentation;
|
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;
|
import net.bytebuddy.asm.Advice;
|
||||||
|
|
||||||
public class NettyChannelPipelineInstrumentation
|
public class NettyChannelPipelineInstrumentation
|
||||||
|
@ -105,18 +105,18 @@ public class NettyChannelPipelineInstrumentation
|
||||||
ChannelHandler ourHandler = null;
|
ChannelHandler ourHandler = null;
|
||||||
// Server pipeline handlers
|
// Server pipeline handlers
|
||||||
if (handler instanceof HttpServerCodec) {
|
if (handler instanceof HttpServerCodec) {
|
||||||
ourHandler = new HttpServerTracingHandler();
|
ourHandler = new HttpServerTracingHandler(NettyServerSingletons.instrumenter());
|
||||||
} else if (handler instanceof HttpRequestDecoder) {
|
} else if (handler instanceof HttpRequestDecoder) {
|
||||||
ourHandler = new HttpServerRequestTracingHandler();
|
ourHandler = new HttpServerRequestTracingHandler(NettyServerSingletons.instrumenter());
|
||||||
} else if (handler instanceof HttpResponseEncoder) {
|
} else if (handler instanceof HttpResponseEncoder) {
|
||||||
ourHandler = new HttpServerResponseTracingHandler();
|
ourHandler = new HttpServerResponseTracingHandler(NettyServerSingletons.instrumenter());
|
||||||
// Client pipeline handlers
|
// Client pipeline handlers
|
||||||
} else if (handler instanceof HttpClientCodec) {
|
} else if (handler instanceof HttpClientCodec) {
|
||||||
ourHandler = new HttpClientTracingHandler();
|
ourHandler = new HttpClientTracingHandler(NettyClientSingletons.instrumenter());
|
||||||
} else if (handler instanceof HttpRequestEncoder) {
|
} else if (handler instanceof HttpRequestEncoder) {
|
||||||
ourHandler = new HttpClientRequestTracingHandler();
|
ourHandler = new HttpClientRequestTracingHandler(NettyClientSingletons.instrumenter());
|
||||||
} else if (handler instanceof HttpResponseDecoder) {
|
} 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
|
// the SslHandler lives in the netty-handler module, using class name comparison to avoid
|
||||||
// adding a dependency
|
// adding a dependency
|
||||||
} else if (handler.getClass().getName().equals("io.netty.handler.ssl.SslHandler")) {
|
} else if (handler.getClass().getName().equals("io.netty.handler.ssl.SslHandler")) {
|
||||||
|
|
|
@ -3,26 +3,22 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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.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.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.NettyClientInstrumenterFactory;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
|
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettyConnectionInstrumenter;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
|
import io.opentelemetry.instrumentation.netty.v4.common.internal.client.NettySslInstrumenter;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
|
import io.opentelemetry.javaagent.bootstrap.internal.DeprecatedConfigPropertyWarning;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.InstrumentationConfig;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public final class NettyClientSingletons {
|
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 connectionTelemetryEnabled;
|
||||||
private static final boolean sslTelemetryEnabled;
|
private static final boolean sslTelemetryEnabled;
|
||||||
|
|
||||||
|
@ -48,13 +44,16 @@ public final class NettyClientSingletons {
|
||||||
static {
|
static {
|
||||||
NettyClientInstrumenterFactory factory =
|
NettyClientInstrumenterFactory factory =
|
||||||
new NettyClientInstrumenterFactory(
|
new NettyClientInstrumenterFactory(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
"io.opentelemetry.netty-4.1",
|
"io.opentelemetry.netty-4.1",
|
||||||
connectionTelemetryEnabled,
|
connectionTelemetryEnabled,
|
||||||
sslTelemetryEnabled,
|
sslTelemetryEnabled,
|
||||||
|
CommonConfig.get().getPeerServiceMapping());
|
||||||
|
INSTRUMENTER =
|
||||||
|
factory.createHttpInstrumenter(
|
||||||
CommonConfig.get().getClientRequestHeaders(),
|
CommonConfig.get().getClientRequestHeaders(),
|
||||||
CommonConfig.get().getClientResponseHeaders(),
|
CommonConfig.get().getClientResponseHeaders(),
|
||||||
CommonConfig.get().getPeerServiceMapping());
|
Collections.emptyList());
|
||||||
INSTRUMENTER = factory.createHttpInstrumenter();
|
|
||||||
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
|
CONNECTION_INSTRUMENTER = factory.createConnectionInstrumenter();
|
||||||
SSL_INSTRUMENTER = factory.createSslInstrumenter();
|
SSL_INSTRUMENTER = factory.createSslInstrumenter();
|
||||||
}
|
}
|
|
@ -3,24 +3,20 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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.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.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.instrumentation.netty.v4.common.internal.server.NettyServerInstrumenterFactory;
|
||||||
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||||
|
|
||||||
public final class NettyServerSingletons {
|
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 =
|
private static final Instrumenter<HttpRequestAndChannel, HttpResponse> INSTRUMENTER =
|
||||||
NettyServerInstrumenterFactory.create(
|
NettyServerInstrumenterFactory.create(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
"io.opentelemetry.netty-4.1",
|
"io.opentelemetry.netty-4.1",
|
||||||
CommonConfig.get().getServerRequestHeaders(),
|
CommonConfig.get().getServerRequestHeaders(),
|
||||||
CommonConfig.get().getServerResponseHeaders());
|
CommonConfig.get().getServerResponseHeaders());
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@ import io.netty.channel.DefaultChannelPipeline
|
||||||
import io.netty.channel.embedded.EmbeddedChannel
|
import io.netty.channel.embedded.EmbeddedChannel
|
||||||
import io.netty.handler.codec.http.HttpClientCodec
|
import io.netty.handler.codec.http.HttpClientCodec
|
||||||
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
|
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
|
import spock.lang.Unroll
|
||||||
|
|
||||||
@Unroll
|
@Unroll
|
||||||
|
@ -31,7 +31,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
|
||||||
channelPipeline.addLast("http", handler)
|
channelPipeline.addLast("http", handler)
|
||||||
channelPipeline.first() == handler
|
channelPipeline.first() == handler
|
||||||
// our handler was also added
|
// our handler was also added
|
||||||
channelPipeline.last().getClass() == HttpClientTracingHandler
|
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
|
||||||
|
|
||||||
and:
|
and:
|
||||||
removeMethod.call(channelPipeline, handler)
|
removeMethod.call(channelPipeline, handler)
|
||||||
|
@ -70,7 +70,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
|
||||||
then: "noop handler was removed; http and instrumentation handlers were added"
|
then: "noop handler was removed; http and instrumentation handlers were added"
|
||||||
channelPipeline.size() == 2
|
channelPipeline.size() == 2
|
||||||
channelPipeline.first() == httpHandler
|
channelPipeline.first() == httpHandler
|
||||||
channelPipeline.last().getClass() == HttpClientTracingHandler
|
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def anotherNoopHandler = new NoopChannelHandler()
|
def anotherNoopHandler = new NoopChannelHandler()
|
||||||
|
@ -103,7 +103,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
|
||||||
then: "add http and instrumentation handlers"
|
then: "add http and instrumentation handlers"
|
||||||
channelPipeline.size() == 2
|
channelPipeline.size() == 2
|
||||||
channelPipeline.first() == httpHandler
|
channelPipeline.first() == httpHandler
|
||||||
channelPipeline.last().getClass() == HttpClientTracingHandler
|
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def noopHandler = new NoopChannelHandler()
|
def noopHandler = new NoopChannelHandler()
|
||||||
|
@ -120,7 +120,7 @@ class ChannelPipelineTest extends AgentInstrumentationSpecification {
|
||||||
then: "http and instrumentation handlers will be remained"
|
then: "http and instrumentation handlers will be remained"
|
||||||
channelPipeline.size() == 2
|
channelPipeline.size() == 2
|
||||||
channelPipeline.first() == httpHandler
|
channelPipeline.first() == httpHandler
|
||||||
channelPipeline.last().getClass() == HttpClientTracingHandler
|
channelPipeline.last().getClass().simpleName == "HttpClientTracingHandler"
|
||||||
|
|
||||||
when:
|
when:
|
||||||
channelPipeline.removeLast()
|
channelPipeline.removeLast()
|
||||||
|
|
|
@ -30,7 +30,6 @@ import io.opentelemetry.instrumentation.test.AgentTestTrait
|
||||||
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
||||||
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
|
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
|
||||||
import io.opentelemetry.instrumentation.testing.junit.http.SingleConnection
|
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 io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||||
import spock.lang.Shared
|
import spock.lang.Shared
|
||||||
import spock.lang.Unroll
|
import spock.lang.Unroll
|
||||||
|
@ -253,7 +252,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
|
||||||
|
|
||||||
then:
|
then:
|
||||||
// The first one returns the removed tracing handler
|
// 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"() {
|
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:
|
when:
|
||||||
pipeline.addLast("name", new HttpClientCodec())
|
pipeline.addLast("name", new HttpClientCodec())
|
||||||
// The first one returns the removed tracing handler
|
// 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
|
// There is only one
|
||||||
pipeline.remove(HttpClientTracingHandler.getName()) == null
|
pipeline.remove("io.opentelemetry.javaagent.shaded.instrumentation.netty.v4_1.internal.client.HttpClientTracingHandler") == null
|
||||||
|
|
||||||
then:
|
then:
|
||||||
thrown NoSuchElementException
|
thrown NoSuchElementException
|
||||||
|
@ -283,7 +282,7 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
|
||||||
|
|
||||||
then:
|
then:
|
||||||
// The first one returns the removed tracing handler
|
// 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("some_handler")
|
||||||
null != pipeline.remove("a_traced_handler")
|
null != pipeline.remove("a_traced_handler")
|
||||||
}
|
}
|
||||||
|
@ -311,9 +310,9 @@ class Netty41ClientTest extends HttpClientTest<DefaultFullHttpRequest> implement
|
||||||
channel.pipeline().addLast(new TracedHandlerFromInitializerHandler())
|
channel.pipeline().addLast(new TracedHandlerFromInitializerHandler())
|
||||||
|
|
||||||
then:
|
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().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"() {
|
def "request with trace annotated method #method"() {
|
||||||
|
|
|
@ -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"))
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,15 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
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 final class AttributeKeys {
|
||||||
|
|
||||||
public static final AttributeKey<Context> WRITE_CONTEXT =
|
public static final AttributeKey<Context> WRITE_CONTEXT =
|
|
@ -3,23 +3,37 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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_REQUEST;
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.instrumenter;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPromise;
|
import io.netty.channel.ChannelPromise;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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
|
@Override
|
||||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
|
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
|
||||||
if (!(msg instanceof HttpRequest)) {
|
if (!(msg instanceof HttpRequest)) {
|
||||||
|
@ -27,13 +41,13 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context parentContext = ctx.channel().attr(AttributeKeys.WRITE_CONTEXT).getAndRemove();
|
Context parentContext = ctx.channel().attr(AttributeKeys.WRITE_CONTEXT).getAndSet(null);
|
||||||
if (parentContext == null) {
|
if (parentContext == null) {
|
||||||
parentContext = Context.current();
|
parentContext = Context.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpRequestAndChannel request = HttpRequestAndChannel.create((HttpRequest) msg, ctx.channel());
|
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);
|
ctx.write(msg, prm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +56,7 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
|
||||||
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
|
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
|
||||||
Attribute<HttpRequestAndChannel> requestAttr = ctx.channel().attr(HTTP_REQUEST);
|
Attribute<HttpRequestAndChannel> requestAttr = ctx.channel().attr(HTTP_REQUEST);
|
||||||
|
|
||||||
Context context = instrumenter().start(parentContext, request);
|
Context context = instrumenter.start(parentContext, request);
|
||||||
parentContextAttr.set(parentContext);
|
parentContextAttr.set(parentContext);
|
||||||
contextAttr.set(context);
|
contextAttr.set(context);
|
||||||
requestAttr.set(request);
|
requestAttr.set(request);
|
||||||
|
@ -51,8 +65,8 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
|
||||||
ctx.write(msg, prm);
|
ctx.write(msg, prm);
|
||||||
// span is ended normally in HttpClientResponseTracingHandler
|
// span is ended normally in HttpClientResponseTracingHandler
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
instrumenter().end(contextAttr.getAndRemove(), requestAttr.getAndRemove(), null, throwable);
|
instrumenter.end(contextAttr.getAndSet(null), requestAttr.getAndSet(null), null, throwable);
|
||||||
parentContextAttr.remove();
|
parentContextAttr.set(null);
|
||||||
throw throwable;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,10 +3,9 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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.instrumentation.netty.v4_1.internal.client.HttpClientRequestTracingHandler.HTTP_REQUEST;
|
||||||
import static io.opentelemetry.javaagent.instrumentation.netty.v4_1.client.NettyClientSingletons.instrumenter;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
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.HttpResponse;
|
||||||
import io.netty.handler.codec.http.LastHttpContent;
|
import io.netty.handler.codec.http.LastHttpContent;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
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
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.CLIENT_CONTEXT);
|
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<Context> parentContextAttr = ctx.channel().attr(AttributeKeys.CLIENT_PARENT_CONTEXT);
|
||||||
Attribute<HttpRequestAndChannel> requestAttr =
|
Attribute<HttpRequestAndChannel> requestAttr = ctx.channel().attr(HTTP_REQUEST);
|
||||||
ctx.channel().attr(NettyClientSingletons.HTTP_REQUEST);
|
|
||||||
|
|
||||||
Context parentContext = parentContextAttr.get();
|
Context parentContext = parentContextAttr.get();
|
||||||
HttpRequestAndChannel request = requestAttr.get();
|
HttpRequestAndChannel request = requestAttr.get();
|
||||||
|
|
||||||
if (msg instanceof FullHttpResponse) {
|
if (msg instanceof FullHttpResponse) {
|
||||||
parentContextAttr.remove();
|
parentContextAttr.set(null);
|
||||||
contextAttr.remove();
|
contextAttr.set(null);
|
||||||
requestAttr.remove();
|
requestAttr.set(null);
|
||||||
} else if (msg instanceof HttpResponse) {
|
} else if (msg instanceof HttpResponse) {
|
||||||
// Headers before body have been received, store them to use when finishing the span.
|
// Headers before body have been received, store them to use when finishing the span.
|
||||||
ctx.channel().attr(HTTP_RESPONSE).set((HttpResponse) msg);
|
ctx.channel().attr(HTTP_RESPONSE).set((HttpResponse) msg);
|
||||||
} else if (msg instanceof LastHttpContent) {
|
} else if (msg instanceof LastHttpContent) {
|
||||||
// Not a FullHttpResponse so this is content that has been received after headers. Finish the
|
// Not a FullHttpResponse so this is content that has been received after headers. Finish the
|
||||||
// span using what we stored in attrs.
|
// span using what we stored in attrs.
|
||||||
parentContextAttr.remove();
|
parentContextAttr.set(null);
|
||||||
contextAttr.remove();
|
contextAttr.set(null);
|
||||||
requestAttr.remove();
|
requestAttr.set(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want the callback in the scope of the parent, not the client span
|
// 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) {
|
if (msg instanceof FullHttpResponse) {
|
||||||
instrumenter().end(context, request, (HttpResponse) msg, null);
|
instrumenter.end(context, request, (HttpResponse) msg, null);
|
||||||
} else if (msg instanceof LastHttpContent) {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,27 +3,42 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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 io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.instrumentation.netty.v4.common.internal.HttpRequestAndChannel;
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
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
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) {
|
||||||
Channel channel = ctx.channel();
|
Channel channel = ctx.channel();
|
||||||
Attribute<Context> contextAttr = channel.attr(AttributeKeys.SERVER_CONTEXT);
|
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)) {
|
if (!(msg instanceof HttpRequest)) {
|
||||||
Context serverContext = contextAttr.get();
|
Context serverContext = contextAttr.get();
|
||||||
|
@ -43,12 +58,12 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
|
||||||
}
|
}
|
||||||
HttpRequestAndChannel request = HttpRequestAndChannel.create((HttpRequest) msg, channel);
|
HttpRequestAndChannel request = HttpRequestAndChannel.create((HttpRequest) msg, channel);
|
||||||
|
|
||||||
if (!instrumenter().shouldStart(parentContext, request)) {
|
if (!instrumenter.shouldStart(parentContext, request)) {
|
||||||
ctx.fireChannelRead(msg);
|
ctx.fireChannelRead(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context context = instrumenter().start(parentContext, request);
|
Context context = instrumenter.start(parentContext, request);
|
||||||
contextAttr.set(context);
|
contextAttr.set(context);
|
||||||
requestAttr.set(request);
|
requestAttr.set(request);
|
||||||
|
|
||||||
|
@ -57,7 +72,7 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
|
||||||
// the span is ended normally in HttpServerResponseTracingHandler
|
// the span is ended normally in HttpServerResponseTracingHandler
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
// make sure to remove the server context on end() call
|
// 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;
|
throw throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,9 +3,9 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* 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.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
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.HttpResponse;
|
||||||
import io.netty.handler.codec.http.LastHttpContent;
|
import io.netty.handler.codec.http.LastHttpContent;
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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.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_1.AttributeKeys;
|
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
|
||||||
import javax.annotation.Nullable;
|
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 {
|
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
|
@Override
|
||||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
|
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise prm) {
|
||||||
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.SERVER_CONTEXT);
|
Attribute<Context> contextAttr = ctx.channel().attr(AttributeKeys.SERVER_CONTEXT);
|
||||||
|
@ -59,14 +75,14 @@ public class HttpServerResponseTracingHandler extends ChannelOutboundHandlerAdap
|
||||||
future ->
|
future ->
|
||||||
end(
|
end(
|
||||||
ctx.channel(),
|
ctx.channel(),
|
||||||
ctx.channel().attr(NettyServerSingletons.HTTP_RESPONSE).getAndRemove(),
|
ctx.channel().attr(HTTP_RESPONSE).getAndSet(null),
|
||||||
writePromise));
|
writePromise));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writePromise = prm;
|
writePromise = prm;
|
||||||
if (msg instanceof HttpResponse) {
|
if (msg instanceof HttpResponse) {
|
||||||
// Headers before body has been sent, store them to use when finishing the span.
|
// 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();
|
Throwable error = future.isSuccess() ? null : future.cause();
|
||||||
end(channel, response, error);
|
end(channel, response, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure to remove the server context on end() call
|
// make sure to remove the server context on end() call
|
||||||
private static void end(
|
private void end(Channel channel, @Nullable HttpResponse response, @Nullable Throwable error) {
|
||||||
Channel channel, @Nullable HttpResponse response, @Nullable Throwable error) {
|
Context context = channel.attr(AttributeKeys.SERVER_CONTEXT).getAndSet(null);
|
||||||
Context context = channel.attr(AttributeKeys.SERVER_CONTEXT).getAndRemove();
|
HttpRequestAndChannel request = channel.attr(HTTP_REQUEST).getAndSet(null);
|
||||||
HttpRequestAndChannel request = channel.attr(NettyServerSingletons.HTTP_REQUEST).getAndRemove();
|
|
||||||
error = NettyErrorHolder.getOrDefault(context, error);
|
error = NettyErrorHolder.getOrDefault(context, error);
|
||||||
instrumenter().end(context, request, response, error);
|
instrumenter.end(context, request, response, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ dependencies {
|
||||||
library("io.ratpack:ratpack-core:1.4.0")
|
library("io.ratpack:ratpack-core:1.4.0")
|
||||||
|
|
||||||
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
|
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
|
||||||
|
implementation(project(":instrumentation:netty:netty-4.1:library"))
|
||||||
|
|
||||||
testImplementation(project(":instrumentation:ratpack:ratpack-1.4:testing"))
|
testImplementation(project(":instrumentation:ratpack:ratpack-1.4:testing"))
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import static io.opentelemetry.javaagent.instrumentation.ratpack.RatpackSingleto
|
||||||
|
|
||||||
import io.netty.util.Attribute;
|
import io.netty.util.Attribute;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
|
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
|
||||||
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
|
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
|
||||||
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
|
|
||||||
import ratpack.handling.Context;
|
import ratpack.handling.Context;
|
||||||
import ratpack.handling.Handler;
|
import ratpack.handling.Handler;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ muzzle {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
|
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")
|
library("io.projectreactor.netty:reactor-netty:0.9.0.RELEASE")
|
||||||
|
|
||||||
testInstrumentation(project(":instrumentation:reactor:reactor-netty:reactor-netty-1.0:javaagent"))
|
testInstrumentation(project(":instrumentation:reactor:reactor-netty:reactor-netty-1.0:javaagent"))
|
||||||
|
|
|
@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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 java.util.function.BiConsumer;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import reactor.netty.Connection;
|
import reactor.netty.Connection;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9;
|
package io.opentelemetry.javaagent.instrumentation.reactornetty.v0_9;
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
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 java.util.function.BiConsumer;
|
||||||
import reactor.netty.Connection;
|
import reactor.netty.Connection;
|
||||||
import reactor.netty.http.client.HttpClientRequest;
|
import reactor.netty.http.client.HttpClientRequest;
|
||||||
|
|
|
@ -24,6 +24,7 @@ dependencies {
|
||||||
annotationProcessor("com.google.auto.value:auto-value")
|
annotationProcessor("com.google.auto.value:auto-value")
|
||||||
|
|
||||||
implementation(project(":instrumentation:netty:netty-4.1:javaagent"))
|
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-4-common:library"))
|
||||||
implementation(project(":instrumentation:netty:netty-common:library"))
|
implementation(project(":instrumentation:netty:netty-common:library"))
|
||||||
implementation(project(":instrumentation:reactor:reactor-3.1:library"))
|
implementation(project(":instrumentation:reactor:reactor-3.1:library"))
|
||||||
|
|
|
@ -11,8 +11,8 @@ import static io.opentelemetry.javaagent.instrumentation.reactornetty.v1_0.React
|
||||||
|
|
||||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
|
import io.opentelemetry.instrumentation.netty.v4_1.internal.AttributeKeys;
|
||||||
import io.opentelemetry.instrumentation.reactor.ContextPropagationOperator;
|
import io.opentelemetry.instrumentation.reactor.ContextPropagationOperator;
|
||||||
import io.opentelemetry.javaagent.instrumentation.netty.v4_1.AttributeKeys;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
|
@ -72,11 +72,10 @@ public final class ReactorNettySingletons {
|
||||||
|
|
||||||
NettyClientInstrumenterFactory instrumenterFactory =
|
NettyClientInstrumenterFactory instrumenterFactory =
|
||||||
new NettyClientInstrumenterFactory(
|
new NettyClientInstrumenterFactory(
|
||||||
|
GlobalOpenTelemetry.get(),
|
||||||
INSTRUMENTATION_NAME,
|
INSTRUMENTATION_NAME,
|
||||||
connectionTelemetryEnabled,
|
connectionTelemetryEnabled,
|
||||||
false,
|
false,
|
||||||
CommonConfig.get().getClientRequestHeaders(),
|
|
||||||
CommonConfig.get().getClientResponseHeaders(),
|
|
||||||
CommonConfig.get().getPeerServiceMapping());
|
CommonConfig.get().getPeerServiceMapping());
|
||||||
CONNECTION_INSTRUMENTER = instrumenterFactory.createConnectionInstrumenter();
|
CONNECTION_INSTRUMENTER = instrumenterFactory.createConnectionInstrumenter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -351,6 +351,7 @@ include(":instrumentation:mongo:mongo-common:testing")
|
||||||
include(":instrumentation:netty:netty-3.8:javaagent")
|
include(":instrumentation:netty:netty-3.8:javaagent")
|
||||||
include(":instrumentation:netty:netty-4.0:javaagent")
|
include(":instrumentation:netty:netty-4.0:javaagent")
|
||||||
include(":instrumentation:netty:netty-4.1: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:javaagent")
|
||||||
include(":instrumentation:netty:netty-4-common:library")
|
include(":instrumentation:netty:netty-4-common:library")
|
||||||
include(":instrumentation:netty:netty-common:library")
|
include(":instrumentation:netty:netty-common:library")
|
||||||
|
|
Loading…
Reference in New Issue