Remove almost all VirtualField#computeIfNull() usages (#4313)

This commit is contained in:
Mateusz Rzeszutek 2021-10-12 08:16:01 +02:00 committed by GitHub
parent 51cf64bb3f
commit 4031f9611a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 134 additions and 201 deletions

View File

@ -18,6 +18,9 @@ muzzle {
}
dependencies {
compileOnly("com.google.auto.value:auto-value-annotations")
annotationProcessor("com.google.auto.value:auto-value")
compileOnly("io.netty:netty:3.8.0.Final")
testLibrary("io.netty:netty:3.8.0.Final")

View File

@ -59,17 +59,19 @@ public class ChannelFutureListenerInstrumentation implements TypeInstrumentation
return null;
}
VirtualField<Channel, ChannelTraceContext> virtualField =
VirtualField.find(Channel.class, ChannelTraceContext.class);
VirtualField<Channel, NettyConnectionContext> virtualField =
VirtualField.find(Channel.class, NettyConnectionContext.class);
ChannelTraceContext channelTraceContext =
virtualField.computeIfNull(future.getChannel(), ChannelTraceContext.FACTORY);
Context parentContext = channelTraceContext.getConnectionContext();
NettyConnectionContext connectionContext = virtualField.get(future.getChannel());
if (connectionContext == null) {
return null;
}
Context parentContext = connectionContext.get();
if (parentContext == null) {
return null;
}
Scope parentScope = parentContext.makeCurrent();
if (channelTraceContext.createConnectionSpan()) {
if (connectionContext.createConnectionSpan()) {
tracer().connectionFailure(parentContext, future.getChannel(), cause);
}
return parentScope;

View File

@ -1,83 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v3_8;
import io.opentelemetry.context.Context;
import java.util.Objects;
import java.util.function.Supplier;
public class ChannelTraceContext {
public static final Supplier<ChannelTraceContext> FACTORY = ChannelTraceContext::new;
private Context connectionContext;
private Context clientParentContext;
private Context context;
private boolean connectionSpanCreated;
public Context getConnectionContext() {
return connectionContext;
}
public void setConnectionContext(Context connectionContext) {
this.connectionContext = connectionContext;
}
public Context getClientParentContext() {
return clientParentContext;
}
public void setClientParentContext(Context clientParentContext) {
this.clientParentContext = clientParentContext;
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public boolean createConnectionSpan() {
if (connectionSpanCreated) {
return false;
}
connectionSpanCreated = true;
return true;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof ChannelTraceContext)) {
return false;
}
ChannelTraceContext other = (ChannelTraceContext) obj;
return Objects.equals(connectionContext, other.connectionContext)
&& Objects.equals(clientParentContext, other.clientParentContext)
&& Objects.equals(context, other.context);
}
@Override
public int hashCode() {
return Objects.hash(connectionContext, clientParentContext, context);
}
@Override
public String toString() {
return "ChannelTraceContext{"
+ "connectionContext="
+ connectionContext
+ ", clientParentContext="
+ clientParentContext
+ ", context="
+ context
+ '}';
}
}

View File

@ -50,15 +50,16 @@ public class NettyChannelInstrumentation implements TypeInstrumentation {
public static void onEnter(@Advice.This Channel channel) {
Context context = Java8BytecodeBridge.currentContext();
Span span = Java8BytecodeBridge.spanFromContext(context);
if (span.getSpanContext().isValid()) {
VirtualField<Channel, ChannelTraceContext> virtualField =
VirtualField.find(Channel.class, ChannelTraceContext.class);
if (!span.getSpanContext().isValid()) {
return;
}
if (virtualField.computeIfNull(channel, ChannelTraceContext.FACTORY).getConnectionContext()
== null) {
virtualField.get(channel).setConnectionContext(context);
}
}
VirtualField<Channel, NettyConnectionContext> virtualField =
VirtualField.find(Channel.class, NettyConnectionContext.class);
if (virtualField.get(channel) != null) {
return;
}
virtualField.set(channel, new NettyConnectionContext(context));
}
}
}

View File

@ -12,7 +12,6 @@ import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.CallDepth;
@ -25,7 +24,6 @@ import io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.HttpServerTr
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.handler.codec.http.HttpClientCodec;
@ -67,35 +65,28 @@ public class NettyChannelPipelineInstrumentation implements TypeInstrumentation
* currently implemented.
*/
public static class ChannelPipelineAdviceUtil {
public static void wrapHandler(
VirtualField<Channel, ChannelTraceContext> virtualField,
ChannelPipeline pipeline,
ChannelHandler handler) {
public static void wrapHandler(ChannelPipeline pipeline, ChannelHandler handler) {
// Server pipeline handlers
if (handler instanceof HttpServerCodec) {
pipeline.addLast(
HttpServerTracingHandler.class.getName(), new HttpServerTracingHandler(virtualField));
pipeline.addLast(HttpServerTracingHandler.class.getName(), new HttpServerTracingHandler());
} else if (handler instanceof HttpRequestDecoder) {
pipeline.addLast(
HttpServerRequestTracingHandler.class.getName(),
new HttpServerRequestTracingHandler(virtualField));
HttpServerRequestTracingHandler.class.getName(), new HttpServerRequestTracingHandler());
} else if (handler instanceof HttpResponseEncoder) {
pipeline.addLast(
HttpServerResponseTracingHandler.class.getName(),
new HttpServerResponseTracingHandler(virtualField));
new HttpServerResponseTracingHandler());
} else
// Client pipeline handlers
if (handler instanceof HttpClientCodec) {
pipeline.addLast(
HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler(virtualField));
pipeline.addLast(HttpClientTracingHandler.class.getName(), new HttpClientTracingHandler());
} else if (handler instanceof HttpRequestEncoder) {
pipeline.addLast(
HttpClientRequestTracingHandler.class.getName(),
new HttpClientRequestTracingHandler(virtualField));
HttpClientRequestTracingHandler.class.getName(), new HttpClientRequestTracingHandler());
} else if (handler instanceof HttpResponseDecoder) {
pipeline.addLast(
HttpClientResponseTracingHandler.class.getName(),
new HttpClientResponseTracingHandler(virtualField));
new HttpClientResponseTracingHandler());
}
}
}
@ -127,10 +118,7 @@ public class NettyChannelPipelineInstrumentation implements TypeInstrumentation
return;
}
VirtualField<Channel, ChannelTraceContext> virtualField =
VirtualField.find(Channel.class, ChannelTraceContext.class);
ChannelPipelineAdviceUtil.wrapHandler(virtualField, pipeline, handler);
ChannelPipelineAdviceUtil.wrapHandler(pipeline, handler);
}
}
@ -161,10 +149,7 @@ public class NettyChannelPipelineInstrumentation implements TypeInstrumentation
return;
}
VirtualField<Channel, ChannelTraceContext> virtualField =
VirtualField.find(Channel.class, ChannelTraceContext.class);
ChannelPipelineAdviceUtil.wrapHandler(virtualField, pipeline, handler);
ChannelPipelineAdviceUtil.wrapHandler(pipeline, handler);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v3_8;
import io.opentelemetry.context.Context;
import org.checkerframework.checker.nullness.qual.Nullable;
public class NettyConnectionContext {
private Context connectionContext;
private boolean connectionSpanCreated;
public NettyConnectionContext(Context connectionContext) {
this.connectionContext = connectionContext;
}
@Nullable
public Context get() {
return connectionContext;
}
@Nullable
public Context remove() {
Context context = this.connectionContext;
connectionContext = null;
return context;
}
public boolean createConnectionSpan() {
if (connectionSpanCreated) {
return false;
}
connectionSpanCreated = true;
return true;
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.netty.v3_8;
import com.google.auto.value.AutoValue;
import io.opentelemetry.context.Context;
import org.checkerframework.checker.nullness.qual.Nullable;
@AutoValue
public abstract class NettyRequestContexts {
public static NettyRequestContexts create(@Nullable Context parentContext, Context context) {
return new AutoValue_NettyRequestContexts(parentContext, context);
}
@Nullable
public abstract Context parentContext();
public abstract Context context();
}

View File

@ -10,7 +10,8 @@ import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.Netty
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.NettyConnectionContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.NettyRequestContexts;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
@ -19,11 +20,10 @@ import org.jboss.netty.handler.codec.http.HttpRequest;
public class HttpClientRequestTracingHandler extends SimpleChannelDownstreamHandler {
private final VirtualField<Channel, ChannelTraceContext> virtualField;
public HttpClientRequestTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
this.virtualField = virtualField;
}
private static final VirtualField<Channel, NettyConnectionContext> connectionContextField =
VirtualField.find(Channel.class, NettyConnectionContext.class);
private static final VirtualField<Channel, NettyRequestContexts> requestContextsField =
VirtualField.find(Channel.class, NettyRequestContexts.class);
@Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent event) {
@ -33,13 +33,12 @@ public class HttpClientRequestTracingHandler extends SimpleChannelDownstreamHand
return;
}
ChannelTraceContext channelTraceContext =
virtualField.computeIfNull(ctx.getChannel(), ChannelTraceContext.FACTORY);
Context parentContext = channelTraceContext.getConnectionContext();
if (parentContext != null) {
channelTraceContext.setConnectionContext(null);
} else {
Context parentContext = null;
NettyConnectionContext connectionContext = connectionContextField.get(ctx.getChannel());
if (connectionContext != null) {
parentContext = connectionContext.remove();
}
if (parentContext == null) {
parentContext = Context.current();
}
@ -49,8 +48,7 @@ public class HttpClientRequestTracingHandler extends SimpleChannelDownstreamHand
}
Context context = tracer().startSpan(parentContext, ctx, (HttpRequest) message);
channelTraceContext.setContext(context);
channelTraceContext.setClientParentContext(parentContext);
requestContextsField.set(ctx.getChannel(), NettyRequestContexts.create(parentContext, context));
try (Scope ignored = context.makeCurrent()) {
ctx.sendDownstream(event);

View File

@ -7,10 +7,9 @@ package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client;
import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyHttpClientTracer.tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.NettyRequestContexts;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
@ -19,34 +18,24 @@ import org.jboss.netty.handler.codec.http.HttpResponse;
public class HttpClientResponseTracingHandler extends SimpleChannelUpstreamHandler {
private final VirtualField<Channel, ChannelTraceContext> virtualField;
public HttpClientResponseTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
this.virtualField = virtualField;
}
private static final VirtualField<Channel, NettyRequestContexts> requestContextsField =
VirtualField.find(Channel.class, NettyRequestContexts.class);
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) {
ChannelTraceContext channelTraceContext =
virtualField.computeIfNull(ctx.getChannel(), ChannelTraceContext.FACTORY);
NettyRequestContexts requestContexts = requestContextsField.get(ctx.getChannel());
Context context = channelTraceContext.getContext();
if (context == null) {
if (requestContexts == null || requestContexts.parentContext() == null) {
ctx.sendUpstream(msg);
return;
}
if (msg.getMessage() instanceof HttpResponse) {
tracer().end(context, (HttpResponse) msg.getMessage());
tracer().end(requestContexts.context(), (HttpResponse) msg.getMessage());
}
// We want the callback in the scope of the parent, not the client span
Context parentContext = channelTraceContext.getClientParentContext();
if (parentContext != null) {
try (Scope ignored = parentContext.makeCurrent()) {
ctx.sendUpstream(msg);
}
} else {
try (Scope ignored = requestContexts.parentContext().makeCurrent()) {
ctx.sendUpstream(msg);
}
}

View File

@ -5,18 +5,13 @@
package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.util.CombinedSimpleChannelHandler;
import org.jboss.netty.channel.Channel;
public class HttpClientTracingHandler
extends CombinedSimpleChannelHandler<
HttpClientResponseTracingHandler, HttpClientRequestTracingHandler> {
public HttpClientTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
super(
new HttpClientResponseTracingHandler(virtualField),
new HttpClientRequestTracingHandler(virtualField));
public HttpClientTracingHandler() {
super(new HttpClientResponseTracingHandler(), new HttpClientRequestTracingHandler());
}
}

View File

@ -10,7 +10,7 @@ import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.Netty
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.NettyRequestContexts;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
@ -19,24 +19,18 @@ import org.jboss.netty.handler.codec.http.HttpRequest;
public class HttpServerRequestTracingHandler extends SimpleChannelUpstreamHandler {
private final VirtualField<Channel, ChannelTraceContext> virtualField;
public HttpServerRequestTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
this.virtualField = virtualField;
}
private static final VirtualField<Channel, NettyRequestContexts> requestContextsField =
VirtualField.find(Channel.class, NettyRequestContexts.class);
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) {
ChannelTraceContext channelTraceContext =
virtualField.computeIfNull(ctx.getChannel(), ChannelTraceContext.FACTORY);
Object message = event.getMessage();
if (!(message instanceof HttpRequest)) {
Context serverContext = tracer().getServerContext(channelTraceContext);
if (serverContext == null) {
NettyRequestContexts requestContexts = requestContextsField.get(ctx.getChannel());
if (requestContexts == null) {
ctx.sendUpstream(event);
} else {
try (Scope ignored = serverContext.makeCurrent()) {
try (Scope ignored = requestContexts.context().makeCurrent()) {
ctx.sendUpstream(event);
}
}
@ -46,9 +40,9 @@ public class HttpServerRequestTracingHandler extends SimpleChannelUpstreamHandle
HttpRequest request = (HttpRequest) message;
Context context =
tracer()
.startSpan(
request, ctx.getChannel(), channelTraceContext, "HTTP " + request.getMethod());
tracer().startSpan(request, ctx.getChannel(), null, "HTTP " + request.getMethod());
requestContextsField.set(ctx.getChannel(), NettyRequestContexts.create(null, context));
try (Scope ignored = context.makeCurrent()) {
ctx.sendUpstream(event);
// the span is ended normally in HttpServerResponseTracingHandler

View File

@ -10,7 +10,7 @@ import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.server.Netty
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.NettyRequestContexts;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
@ -19,29 +19,25 @@ import org.jboss.netty.handler.codec.http.HttpResponse;
public class HttpServerResponseTracingHandler extends SimpleChannelDownstreamHandler {
private final VirtualField<Channel, ChannelTraceContext> virtualField;
public HttpServerResponseTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
this.virtualField = virtualField;
}
private static final VirtualField<Channel, NettyRequestContexts> requestContextsField =
VirtualField.find(Channel.class, NettyRequestContexts.class);
@Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent msg) {
ChannelTraceContext channelTraceContext =
virtualField.computeIfNull(ctx.getChannel(), ChannelTraceContext.FACTORY);
NettyRequestContexts requestContexts = requestContextsField.get(ctx.getChannel());
Context context = tracer().getServerContext(channelTraceContext);
if (context == null || !(msg.getMessage() instanceof HttpResponse)) {
if (requestContexts == null || !(msg.getMessage() instanceof HttpResponse)) {
ctx.sendDownstream(msg);
return;
}
Context context = requestContexts.context();
try (Scope ignored = context.makeCurrent()) {
ctx.sendDownstream(msg);
tracer().end(context, (HttpResponse) msg.getMessage());
} catch (Throwable throwable) {
tracer().endExceptionally(context, throwable);
throw throwable;
}
tracer().end(context, (HttpResponse) msg.getMessage());
}
}

View File

@ -5,18 +5,13 @@
package io.opentelemetry.javaagent.instrumentation.netty.v3_8.server;
import io.opentelemetry.instrumentation.api.field.VirtualField;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.util.CombinedSimpleChannelHandler;
import org.jboss.netty.channel.Channel;
public class HttpServerTracingHandler
extends CombinedSimpleChannelHandler<
HttpServerRequestTracingHandler, HttpServerResponseTracingHandler> {
public HttpServerTracingHandler(VirtualField<Channel, ChannelTraceContext> virtualField) {
super(
new HttpServerRequestTracingHandler(virtualField),
new HttpServerResponseTracingHandler(virtualField));
public HttpServerTracingHandler() {
super(new HttpServerRequestTracingHandler(), new HttpServerResponseTracingHandler());
}
}

View File

@ -10,7 +10,6 @@ import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.HOST;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.instrumentation.api.tracer.HttpServerTracer;
import io.opentelemetry.javaagent.instrumentation.netty.v3_8.ChannelTraceContext;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -19,7 +18,7 @@ import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
public class NettyHttpServerTracer
extends HttpServerTracer<HttpRequest, HttpResponse, Channel, ChannelTraceContext> {
extends HttpServerTracer<HttpRequest, HttpResponse, Channel, Void> {
private static final NettyHttpServerTracer TRACER = new NettyHttpServerTracer();
public static NettyHttpServerTracer tracer() {
@ -42,13 +41,11 @@ public class NettyHttpServerTracer
}
@Override
protected void attachServerContext(Context context, ChannelTraceContext channelTraceContext) {
channelTraceContext.setContext(context);
}
protected void attachServerContext(Context context, Void unused) {}
@Override
public Context getServerContext(ChannelTraceContext channelTraceContext) {
return channelTraceContext.getContext();
public Context getServerContext(Void unused) {
return null;
}
@Override