@Override
 public void after(Object target, Object[] args, Object result, Throwable throwable) {
   if (isDebug) {
     logger.afterInterceptor(target, args, result, throwable);
   }
   // Unset server markers
   if (args[0] instanceof AsyncFrameBuffer) {
     AsyncFrameBuffer frameBuffer = (AsyncFrameBuffer) args[0];
     attachMarkersToInputProtocol(frameBuffer.getInputProtocol(), false);
   }
   final Trace trace = this.traceContext.currentRawTraceObject();
   if (trace == null) {
     return;
   }
   this.traceContext.removeTraceObject();
   if (trace.canSampled()) {
     try {
       processTraceObject(trace, target, args, throwable);
     } catch (Throwable t) {
       logger.warn("Error processing trace object. Cause:{}", t.getMessage(), t);
     } finally {
       trace.close();
     }
   }
 }
  @Override
  public void after(Object target, Object result, Throwable throwable, Object[] args) {
    if (isDebug) {
      logger.afterInterceptor(
          target,
          methodDescriptor.getClassName(),
          methodDescriptor.getMethodName(),
          "",
          args,
          result,
          throwable);
    }

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

    InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
    if (invocation != null && invocation.getAttachment() != null) {
      HttpCallContext callContext = (HttpCallContext) invocation.getAttachment();
      if (methodDescriptor.getMethodName().equals("doSendRequest")) {
        callContext.setWriteEndTime(System.currentTimeMillis());
        callContext.setWriteFail(throwable != null);
      } else {
        callContext.setReadEndTime(System.currentTimeMillis());
        callContext.setReadFail(throwable != null);
      }
      logger.debug("Set call context {}", callContext);
    }
  }
  @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);
    }
  }
示例#5
0
 private void bindPLoggerFactory(PLoggerBinder binder) {
   final String binderClassName = binder.getClass().getName();
   PLogger pLogger = binder.getLogger(binder.getClass().getName());
   pLogger.info(
       "PLoggerFactory.initialize() bind:{} cl:{}",
       binderClassName,
       binder.getClass().getClassLoader());
   // Set binder to static LoggerFactory
   // Should we unset binder at shutdown hook or stop()?
   PLoggerFactory.initialize(binder);
 }
示例#6
0
  @Override
  public void setup(ProfilerPluginSetupContext context) {
    final OkHttpPluginConfig config = new OkHttpPluginConfig(context.getConfig());
    logger.debug("[OkHttp] Initialized config={}", config);

    logger.debug("[OkHttp] Add Call class.");
    addCall(context, config);
    logger.debug("[OkHttp] Add Dispatcher class.");
    addDispatcher(context, config);
    logger.debug("[OkHttp] Add AsyncCall class.");
    addAsyncCall(context, config);
    addHttpEngine(context, config);
    addRequestBuilder(context, config);
  }
/** @author harebox */
@TargetConstructor("net.sf.ehcache.Element")
public class FrontCacheGetFutureConstructInterceptor implements AroundInterceptor, ArcusConstants {

  // TODO This should be extracted from FrontCacheMemcachedClient.
  private static final String DEFAULT_FRONTCACHE_NAME = "front";

  private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
  private final boolean isDebug = logger.isDebugEnabled();

  @Override
  public void before(Object target, Object[] args) {
    // do nothing
  }

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

    try {
      ((CacheNameAccessor) target)._$PINPOINT$_setCacheName(DEFAULT_FRONTCACHE_NAME);

      if (args[0] instanceof Element) {
        Element element = (Element) args[0];
        ((CacheKeyAccessor) target)._$PINPOINT$_setCacheKey(element.getObjectKey());
      }
    } catch (Exception e) {
      logger.error("failed to add metadata: {}", e);
    }
  }
}
示例#8
0
  @Override
  public void setup(ProfilerPluginSetupContext context) {
    final UserPluginConfig config = new UserPluginConfig(context.getConfig());

    // add user include methods
    for (String fullQualifiedMethodName : config.getIncludeList()) {
      try {
        addUserIncludeClass(context, fullQualifiedMethodName);
        if (logger.isDebugEnabled()) {
          logger.debug("Add user include class interceptor {}", fullQualifiedMethodName);
        }
      } catch (Exception e) {
        logger.warn("Failed to add user include class(" + fullQualifiedMethodName + ").", e);
      }
    }
  }
示例#9
0
/**
 * @author netspider
 * @author emeroad
 */
@TargetMethod(
    name = "addOp",
    paramTypes = {"java.lang.String", "net.spy.memcached.ops.Operation"})
public class AddOpInterceptor implements AroundInterceptor {

  private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
  private final boolean isDebug = logger.isDebugEnabled();

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

    String serviceCode = ((ServiceCodeAccessor) target)._$PINPOINT$_getServiceCode();
    ((ServiceCodeAccessor) args[1])._$PINPOINT$_setServiceCode(serviceCode);
  }

  @Override
  public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
      logger.afterInterceptor(target, args, result, throwable);
    }
  }
}
 private void deleteUserIncludeTrace(final Trace trace) {
   if (isDebug) {
     logger.debug("Delete user include trace={}, sampled={}", trace, trace.canSampled());
   }
   traceContext.removeTraceObject();
   trace.close();
 }
  @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 result, Throwable throwable, Object[] args) {
    if (isDebug) {
      logger.afterInterceptor(target, args);
    }

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

    try {
      SpanEventRecorder recorder = trace.currentSpanEventRecorder();
      recorder.recordApi(methodDescriptor);
      recorder.recordServiceType(HttpClientConstants.HTTP_CLIENT_INTERNAL);
      recorder.recordException(throwable);

      // remove async id.
      InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation();
      if (transaction != null) {
        // clear
        transaction.removeAttachment();
      }
    } finally {
      trace.traceBlockEnd();
    }
  }
  @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);
    }

    ((OperationAccessor) target)._$PINPOINT$_setOperation((Operation) args[0]);
  }
  @Override
  public void after(Object target, Object result, Throwable throwable, Object[] args) {
    if (isDebug) {
      logger.afterInterceptor(target, args, result, throwable);
    }

    try {
      ((CacheNameAccessor) target)._$PINPOINT$_setCacheName(DEFAULT_FRONTCACHE_NAME);

      if (args[0] instanceof Element) {
        Element element = (Element) args[0];
        ((CacheKeyAccessor) target)._$PINPOINT$_setCacheKey(element.getObjectKey());
      }
    } catch (Exception e) {
      logger.error("failed to add metadata: {}", e);
    }
  }
  private boolean validate(Object target) {
    if (!(target instanceof UserRequestGetter)) {
      logger.debug("Invalid target object. Need field accessor({}).", FIELD_USER_REQUEST);
      return false;
    }

    if (!(target instanceof UserResponseGetter)) {
      logger.debug("Invalid target object. Need field accessor({}).", FIELD_USER_RESPONSE);
      return false;
    }

    if (!(target instanceof ConnectionGetter)) {
      logger.debug("Invalid target object. Need field accessor({}).", FIELD_CONNECTION);
      return false;
    }

    return true;
  }
示例#17
0
  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }

    String serviceCode = ((ServiceCodeAccessor) target)._$PINPOINT$_getServiceCode();
    ((ServiceCodeAccessor) args[1])._$PINPOINT$_setServiceCode(serviceCode);
  }
 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;
 }
示例#19
0
/** @author emeroad */
public class GroupedInterceptor implements AroundInterceptor {
  private final PLogger logger = PLoggerFactory.getLogger(getClass());
  private final boolean debugEnabled = logger.isDebugEnabled();

  private final BeforeInterceptor before;
  private final AfterInterceptor after;
  private final InterceptorGroup group;
  private final ExecutionPolicy policy;

  public GroupedInterceptor(
      BeforeInterceptor before,
      AfterInterceptor after,
      InterceptorGroup group,
      ExecutionPolicy policy) {
    this.before = before;
    this.after = after;
    this.group = group;
    this.policy = policy;
  }

  @Override
  public void before(Object target, Object[] args) {
    InterceptorGroupInvocation transaction = group.getCurrentInvocation();

    if (transaction.tryEnter(policy)) {
      if (before != null) {
        before.before(target, args);
      }
    } else {
      if (debugEnabled) {
        logger.debug(
            "tryBefore() returns false: interceptorGroupTransaction: {}, executionPoint: {}. Skip interceptor {}",
            new Object[] {transaction, policy, before == null ? null : before.getClass()});
      }
    }
  }

  @Override
  public void after(Object target, Object[] args, Object result, Throwable throwable) {
    InterceptorGroupInvocation transaction = group.getCurrentInvocation();

    if (transaction.canLeave(policy)) {
      if (after != null) {
        after.after(target, args, result, throwable);
      }
      transaction.leave(policy);
    } else {
      if (debugEnabled) {
        logger.debug(
            "tryAfter() returns false: interceptorGroupTransaction: {}, executionPoint: {}. Skip interceptor {}",
            new Object[] {transaction, policy, after == null ? null : after.getClass()});
      }
    }
  }
}
 private boolean validate(Object target) {
   if (!(target instanceof AsyncMarkerFlagFieldAccessor)) {
     if (isDebug) {
       logger.debug(
           "Invalid target object. Need field accessor({}).",
           AsyncMarkerFlagFieldAccessor.class.getName());
     }
     return false;
   }
   return true;
 }
  /* (non-Javadoc)
   * @see com.navercorp.pinpoint.bootstrap.plugin.transformer.PinpointClassFileTransformer#transform(com.navercorp.pinpoint.bootstrap.plugin.PinpointInstrument, java.lang.ClassLoader, java.lang.String, java.lang.Class, java.security.ProtectionDomain, byte[])
   */
  @Override
  public byte[] transform(
      Instrumentor instrumentContext,
      ClassLoader loader,
      String className,
      Class<?> classBeingRedefined,
      ProtectionDomain protectionDomain,
      byte[] classfileBuffer)
      throws InstrumentException {
    if (logger.isInfoEnabled()) {
      logger.info("Modify {}", className);
    }

    try {
      InstrumentClass target =
          instrumentContext.getInstrumentClass(loader, className, classfileBuffer);

      if (!target.isInterceptable()) {
        return null;
      }

      List<InstrumentMethod> methodList = target.getDeclaredMethods(METHOD_FILTER);
      for (InstrumentMethod method : methodList) {
        if (logger.isTraceEnabled()) {
          logger.trace(
              "### c={}, m={}, params={}",
              new Object[] {
                className, method.getName(), Arrays.toString(method.getParameterTypes())
              });
        }

        method.addInterceptor(
            BasicMethodInterceptor.class.getName(), va(SpringBeansConstants.SERVICE_TYPE));
      }

      return target.toBytecode();
    } catch (Exception e) {
      logger.warn("modify fail. Cause:{}", e.getMessage(), e);
      return null;
    }
  }
  @Override
  public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
      logger.afterInterceptor(target, args, result, throwable);
    }

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

    try {
      SpanEventRecorder recorder = trace.currentSpanEventRecorder();
      recorder.recordApi(this.descriptor);
      recorder.recordException(throwable);
    } catch (Throwable t) {
      logger.warn("after error. Caused:{}", t.getMessage(), t);
    } finally {
      trace.traceBlockEnd();
    }
  }
  private Trace createUserIncludeTrace() {
    final Trace trace = traceContext.newTraceObject();
    if (isDebug) {
      logger.debug("New user include trace {} and sampled {}", trace, trace.canSampled());
    }
    // add user scope.
    TraceScope oldScope = trace.addScope(SCOPE_NAME);
    if (oldScope != null) {
      // delete corrupted trace.
      logger.warn("Duplicated user include trace scope={}.", oldScope.getName());
      deleteUserIncludeTrace(trace);
      return null;
    }

    if (trace.canSampled()) {
      // record root span.
      final SpanRecorder recorder = trace.getSpanRecorder();
      recorder.recordServiceType(ServiceType.STAND_ALONE);
      recorder.recordApi(USER_INCLUDE_METHOD_DESCRIPTOR);
    }
    return trace;
  }
 private boolean validateInputProtocol(Object iprot) {
   if (iprot instanceof TProtocol) {
     if (!(iprot instanceof ServerMarkerFlagFieldAccessor)) {
       if (isDebug) {
         logger.debug(
             "Invalid target object. Need field accessor({}).",
             ServerMarkerFlagFieldAccessor.class.getName());
       }
       return false;
     }
     if (!(iprot instanceof AsyncMarkerFlagFieldAccessor)) {
       if (isDebug) {
         logger.debug(
             "Invalid target object. Need field accessor({}).",
             AsyncMarkerFlagFieldAccessor.class.getName());
       }
       return false;
     }
     return true;
   }
   return false;
 }
  @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);
    }
  }
  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }
    Trace trace = traceContext.currentTraceObject();
    if (trace == null) {
      return;
    }

    SpanEventRecorder recorder = trace.traceBlockBegin();
    recorder.recordServiceType(JacksonConstants.SERVICE_TYPE);
  }
  private boolean validate(final Object target, final Object[] args) {
    if (args.length != 1) {
      return false;
    }

    Object asyncMethodCallObj = args[0];
    if (asyncMethodCallObj == null) {
      if (isDebug) {
        logger.debug("Metadata injection target object is null.");
      }
      return false;
    }

    if (!this.asyncTraceIdAccessor.isApplicable(asyncMethodCallObj)) {
      if (isDebug) {
        logger.debug("Invalid target object. Need metadata accessor({})", METADATA_ASYNC_TRACE_ID);
      }
      return false;
    }

    if (!this.asyncNextSpanIdAccessor.isApplicable(asyncMethodCallObj)) {
      if (isDebug) {
        logger.debug(
            "Invalid target object. Need metadata accessor({})", METADATA_ASYNC_NEXT_SPAN_ID);
      }
      return false;
    }

    if (!this.asyncCallRemoteAddressAccessor.isApplicable(asyncMethodCallObj)) {
      if (isDebug) {
        logger.debug(
            "Invalid target object. Need metadata accessor({})",
            METADATA_ASYNC_CALL_REMOTE_ADDRESS);
      }
      return false;
    }

    return true;
  }
/**
 * This interceptor retrieves the method name called by the client and stores it for other
 * interceptors in the chain to use.
 *
 * <p><tt>TBaseAsyncProcessorProcessInterceptor</tt> ->
 * <b><tt>TProtocolReadMessageBeginInterceptor</tt></b> ->
 * <tt>TProtocolReadFieldBeginInterceptor</tt> <-> <tt>TProtocolReadTTypeInterceptor</tt> ->
 * <tt>TProtocolReadMessageEndInterceptor</tt>
 *
 * <p>Based on Thrift 0.8.0+
 *
 * @author HyunGil Jeong
 * @see
 *     com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadMessageBeginInterceptor
 *     TProtocolReadMessageBeginInterceptor
 * @see
 *     com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadFieldBeginInterceptor
 *     TProtocolReadFieldBeginInterceptor
 * @see
 *     com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadTTypeInterceptor
 *     TProtocolReadTTypeInterceptor
 * @see
 *     com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadMessageEndInterceptor
 *     TProtocolReadMessageEndInterceptor
 */
@Scope(value = THRIFT_SERVER_SCOPE, executionPolicy = ExecutionPolicy.INTERNAL)
public class TProtocolReadMessageBeginInterceptor implements AroundInterceptor {

  private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
  private final boolean isDebug = logger.isDebugEnabled();

  private final InterceptorScope scope;

  public TProtocolReadMessageBeginInterceptor(@Name(THRIFT_SERVER_SCOPE) InterceptorScope scope) {
    this.scope = scope;
  }

  @Override
  public void before(Object target, Object[] args) {
    // Do nothing
  }

  @Override
  public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
      logger.afterInterceptor(target, args, result, throwable);
    }
    if (!validate(target)) {
      return;
    }
    final boolean shouldTrace =
        ((AsyncMarkerFlagFieldAccessor) target)._$PINPOINT$_getAsyncMarkerFlag();
    if (shouldTrace) {
      String methodName = ThriftConstants.UNKNOWN_METHOD_NAME;
      if (result instanceof TMessage) {
        TMessage message = (TMessage) result;
        methodName = message.name;
      }
      ThriftClientCallContext clientCallContext = new ThriftClientCallContext(methodName);
      InterceptorScopeInvocation currentTransaction = this.scope.getCurrentInvocation();
      currentTransaction.setAttachment(clientCallContext);
    }
  }

  private boolean validate(Object target) {
    if (!(target instanceof AsyncMarkerFlagFieldAccessor)) {
      if (isDebug) {
        logger.debug(
            "Invalid target object. Need field accessor({}).",
            AsyncMarkerFlagFieldAccessor.class.getName());
      }
      return false;
    }
    return true;
  }
}
/**
 * @see
 *     JacksonPlugin#intercept_ObjectMapper(com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext)
 * @author Sungkook Kim
 */
public class WriteValueAsStringInterceptor implements AroundInterceptor {
  private final PLogger logger = PLoggerFactory.getLogger(getClass());
  private final boolean isDebug = logger.isDebugEnabled();

  private final MethodDescriptor descriptor;
  private final TraceContext traceContext;

  public WriteValueAsStringInterceptor(TraceContext traceContext, MethodDescriptor descriptor) {
    this.descriptor = descriptor;
    this.traceContext = traceContext;
  }

  @Override
  public void before(Object target, Object[] args) {
    if (isDebug) {
      logger.beforeInterceptor(target, args);
    }
    Trace trace = traceContext.currentTraceObject();
    if (trace == null) {
      return;
    }

    SpanEventRecorder recorder = trace.traceBlockBegin();
    recorder.recordServiceType(JacksonConstants.SERVICE_TYPE);
  }

  @Override
  public void after(Object target, Object result, Throwable throwable, Object[] args) {
    if (isDebug) {
      logger.afterInterceptor(target, args);
    }
    Trace trace = traceContext.currentTraceObject();
    if (trace == null) {
      return;
    }

    try {
      SpanEventRecorder recorder = trace.currentSpanEventRecorder();
      recorder.recordApi(descriptor);
      recorder.recordException(throwable);

      if (result != null) {
        recorder.recordAttribute(
            JacksonConstants.ANNOTATION_KEY_LENGTH_VALUE, ((String) result).length());
      }
    } finally {
      trace.traceBlockEnd();
    }
  }
}
 @Override
 public void after(Object target, Object[] args, Object result, Throwable throwable) {
   final Trace trace = this.traceContext.currentRawTraceObject();
   if (trace == null) {
     return;
   }
   // logging here as some Thrift servers depend on TTransportException being thrown for normal
   // operations.
   // log only when current transaction is being traced.
   if (isDebug) {
     logger.afterInterceptor(target, args, result, throwable);
   }
   this.traceContext.removeTraceObject();
   if (trace.canSampled()) {
     try {
       processTraceObject(trace, target, args, throwable);
     } catch (Throwable t) {
       logger.warn("Error processing trace object. Cause:{}", t.getMessage(), t);
     } finally {
       trace.close();
     }
   }
 }