content: /*
   * Copyright The OpenTelemetry Authors
   * SPDX-License-Identifier: Apache-2.0
   */
  
  package io.opentelemetry.javaagent.instrumentation.netty.v3_8.client;
  
  import static io.opentelemetry.javaagent.instrumentation.netty.v3_8.client.NettyClientSingletons.instrumenter;
  
  import io.opentelemetry.context.Scope;
  import io.opentelemetry.instrumentation.api.util.VirtualField;
  import io.opentelemetry.instrumentation.netty.common.internal.NettyErrorHolder;
  import org.jboss.netty.channel.Channel;
  import org.jboss.netty.channel.ChannelHandlerContext;
  import org.jboss.netty.channel.MessageEvent;
  import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
  import org.jboss.netty.handler.codec.http.HttpResponse;
  
  public class HttpClientResponseTracingHandler extends SimpleChannelUpstreamHandler {
  
    private static final VirtualField<Channel, NettyClientRequestAndContexts> requestContextsField =
        VirtualField.find(Channel.class, NettyClientRequestAndContexts.class);
  
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent msg) throws Exception {
      NettyClientRequestAndContexts requestAndContexts = requestContextsField.get(ctx.getChannel());
  
      if (requestAndContexts == null) {
        super.messageReceived(ctx, msg);
        return;
      }
  
      if (msg.getMessage() instanceof HttpResponse) {
        instrumenter()
            .end(
                requestAndContexts.context(),
                requestAndContexts.request(),
                (HttpResponse) msg.getMessage(),
                NettyErrorHolder.getOrDefault(requestAndContexts.context(), null));
        requestContextsField.set(ctx.getChannel(), null);
      }
  
      // We want the callback in the scope of the parent, not the client span
      try (Scope ignored = requestAndContexts.parentContext().makeCurrent()) {
        super.messageReceived(ctx, msg);
      }
    }
  }
  