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

    Trace trace = traceContext.currentRawTraceObject();
    if (trace == null) {
      // create user include trace for standalone entry point.
      trace = createUserIncludeTrace();
      if (trace == null) {
        return;
      }
    }

    // check user include trace.
    if (!isUserIncludeTrace(trace)) {
      return;
    }

    // entry scope(default & disable trace).
    entryUserIncludeTraceScope(trace);

    // check sampled.
    if (!trace.canSampled()) {
      // skip
      return;
    }

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

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

    // check user include trace.
    if (!isUserIncludeTrace(trace)) {
      return;
    }

    // leave scope(default & disable trace).
    if (!leaveUserIncludeTraceScope(trace)) {
      logger.warn(
          "Failed to leave scope of user include trace. trace={}, sampled={}",
          trace,
          trace.canSampled());
      // delete unstable trace.
      deleteUserIncludeTrace(trace);
      return;
    }

    // check sampled.
    if (!trace.canSampled()) {
      if (isUserIncludeTraceDestination(trace)) {
        deleteUserIncludeTrace(trace);
      }
      return;
    }

    try {
      final SpanEventRecorder recorder = trace.currentSpanEventRecorder();
      recorder.recordApi(descriptor);
      recorder.recordServiceType(ServiceType.INTERNAL_METHOD);
      recorder.recordException(throwable);
    } finally {
      trace.traceBlockEnd();
      if (isUserIncludeTraceDestination(trace)) {
        deleteUserIncludeTrace(trace);
      }
    }
  }
  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }

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

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

    if (!trace.canSampled()) {
      return;
    }

    SpanEventRecorder recorder = trace.traceBlockBegin();
    try {
      final TraceId nextId = trace.getTraceId().getNextTraceId();
      recorder.recordNextSpanId(nextId.getSpanId());
      recorder.recordServiceType(OK_HTTP_CLIENT);

      InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
      if (invocation != null) {
        invocation.getOrCreateAttachment(
            new AttachmentFactory() {
              @Override
              public Object createAttachment() {
                return nextId;
              }
            });
      }
    } catch (Throwable t) {
      logger.warn("Failed to BEFORE process. {}", t.getMessage(), t);
    }
  }