@Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }

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

    SpanEventRecorder recorder = trace.traceBlockBegin();
    try {
      // set asynchronous trace
      final AsyncTraceId asyncTraceId = trace.getAsyncTraceId();
      recorder.recordNextAsyncId(asyncTraceId.getAsyncId());

      // set async id.
      InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation();
      if (transaction != null) {
        transaction.setAttachment(asyncTraceId);
        if (isDebug) {
          logger.debug("Set asyncTraceId metadata {}", asyncTraceId);
        }
      }
    } catch (Throwable t) {
      logger.warn("Failed to before process. {}", t.getMessage(), t);
    }
  }
  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }

    if (!validate(target, args)) {
      return;
    }

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

    try {
      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();
        Object asyncMethodCallObj = args[0];
        // inject async trace info to AsyncMethodCall object
        final AsyncTraceId asyncTraceId = injectAsyncTraceId(asyncMethodCallObj, trace);

        recorder.recordServiceType(THRIFT_CLIENT_INTERNAL);

        // retrieve connection information
        String remoteAddress = getRemoteAddress(asyncMethodCallObj);

        final TraceId nextId = asyncTraceId.getNextTraceId();

        // Inject nextSpanId as the actual sending of data will be handled asynchronously.
        final long nextSpanId = nextId.getSpanId();
        parentTraceInfo.setSpanId(nextSpanId);

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

        parentTraceInfo.setFlags(nextId.getFlags());
        parentTraceInfo.setParentApplicationName(this.traceContext.getApplicationName());
        parentTraceInfo.setParentApplicationType(this.traceContext.getServerTypeCode());
        parentTraceInfo.setAcceptorHost(remoteAddress);

        this.asyncCallRemoteAddressAccessor.set(asyncMethodCallObj, remoteAddress);
        this.asyncNextSpanIdAccessor.set(asyncMethodCallObj, nextSpanId);
      }
      InterceptorGroupInvocation currentTransaction = this.group.getCurrentInvocation();
      currentTransaction.setAttachment(parentTraceInfo);
    } catch (Throwable t) {
      logger.warn("before error. Caused:{}", t.getMessage(), t);
    }
  }
 private AsyncTraceId injectAsyncTraceId(final Object asyncMethodCallObj, final Trace trace) {
   final AsyncTraceId asyncTraceId = trace.getAsyncTraceId();
   SpanEventRecorder recorder = trace.currentSpanEventRecorder();
   recorder.recordNextAsyncId(asyncTraceId.getAsyncId());
   this.asyncTraceIdAccessor.set(asyncMethodCallObj, asyncTraceId);
   if (isDebug) {
     logger.debug("Set asyncTraceId metadata {}", asyncTraceId);
   }
   return asyncTraceId;
 }