@Override
  public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
      logger.afterInterceptor(target, args, result, throwable);
    }

    Trace trace = this.traceContext.currentTraceObject();
    if (trace == null) {
      return;
    }

    try {
      SpanEventRecorder recorder = trace.currentSpanEventRecorder();
      if (this.traceServiceArgs) {
        if (args.length == 2 && (args[1] instanceof TBase)) {
          recorder.recordAttribute(
              ThriftConstants.THRIFT_ARGS, getMethodArgs((TBase<?, ?>) args[1]));
        }
      }
      recorder.recordApi(descriptor);
      recorder.recordException(throwable);
    } finally {
      trace.traceBlockEnd();
    }
  }
  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }
    if (target instanceof TServiceClient) {
      TServiceClient client = (TServiceClient) target;
      TProtocol oprot = client.getOutputProtocol();
      TTransport transport = oprot.getTransport();
      final Trace trace = traceContext.currentRawTraceObject();
      if (trace == null) {
        return;
      }
      ThriftRequestProperty parentTraceInfo = new ThriftRequestProperty();
      final boolean shouldSample = trace.canSampled();
      if (!shouldSample) {
        if (isDebug) {
          logger.debug("set Sampling flag=false");
        }
        parentTraceInfo.setShouldSample(shouldSample);
      } else {
        SpanEventRecorder recorder = trace.traceBlockBegin();
        recorder.recordServiceType(ThriftConstants.THRIFT_CLIENT);

        // retrieve connection information
        String remoteAddress = ThriftConstants.UNKNOWN_ADDRESS;
        if (transport instanceof SocketFieldAccessor) {
          Socket socket = ((SocketFieldAccessor) transport)._$APM$_getSocket();
          if (socket != null) {
            remoteAddress = ThriftUtils.getHostPort(socket.getRemoteSocketAddress());
          }
        } else {
          if (isDebug) {
            logger.debug(
                "Invalid target object. Need field accessor({}).",
                SocketFieldAccessor.class.getName());
          }
        }
        recorder.recordDestinationId(remoteAddress);

        String methodName = ThriftConstants.UNKNOWN_METHOD_NAME;
        if (args[0] instanceof String) {
          methodName = (String) args[0];
        }
        String serviceName = ThriftUtils.getClientServiceName(client);

        String thriftUrl = getServiceUrl(remoteAddress, serviceName, methodName);
        recorder.recordAttribute(ThriftConstants.THRIFT_URL, thriftUrl);

        TraceId nextId = trace.getTraceId().getNextTraceId();
        recorder.recordNextSpanId(nextId.getSpanId());

        parentTraceInfo.setTraceId(nextId.getTransactionId());
        parentTraceInfo.setSpanId(nextId.getSpanId());
        parentTraceInfo.setParentSpanId(nextId.getParentSpanId());

        parentTraceInfo.setFlags(nextId.getFlags());
        parentTraceInfo.setParentApplicationName(traceContext.getApplicationName());
        parentTraceInfo.setParentApplicationType(traceContext.getServerTypeCode());
        parentTraceInfo.setAcceptorHost(remoteAddress);
      }
      InterceptorGroupInvocation currentTransaction = this.group.getCurrentInvocation();
      currentTransaction.setAttachment(parentTraceInfo);
    }
  }