top.fullj.chase.internal.Chase Maven / Gradle / Ivy
package top.fullj.chase.internal;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.aspectj.lang.reflect.MethodSignature;
import java.util.Iterator;
import java.util.ServiceLoader;
import top.fullj.chase.spi.VirtLog;
@Aspect
public class Chase {
private static final VirtLog LOG;
static {
Iterator it = ServiceLoader.load(VirtLog.class).iterator();
LOG = it.hasNext() ? it.next() : new ConsoleLog();
}
private static volatile boolean enabled = true;
public static void setEnabled(boolean enabled) {
Chase.enabled = enabled;
}
@Pointcut("within(@top.fullj.chase.annotation.DebugLog *)")
public void withinAnnotatedClass() {}
@Pointcut("execution(!synthetic * *(..)) && withinAnnotatedClass()")
public void methodInsideAnnotatedType() {}
@Pointcut("execution(!synthetic *.new(..)) && withinAnnotatedClass()")
public void constructorInsideAnnotatedType() {}
@Pointcut("execution(@top.fullj.chase.annotation.DebugLog * *(..)) || methodInsideAnnotatedType()")
public void method() {}
@Pointcut("execution(@top.fullj.chase.annotation.DebugLog *.new(..)) || constructorInsideAnnotatedType()")
public void constructor() {}
@Around("method() || constructor()")
public Object intercept(ProceedingJoinPoint pjp) throws Throwable {
if (!enabled) {
return pjp.proceed();
}
methodEnter(pjp);
Timer timer = new Timer();
try {
Object result = pjp.proceed();
methodReturn(pjp, result, timer.millis());
return result;
} catch (Throwable tr) {
methodThrown(pjp, tr, timer.millis());
throw tr;
}
}
private static void methodEnter(JoinPoint pjp) {
CodeSignature codeSignature = (CodeSignature) pjp.getSignature();
String[] parameterNames = codeSignature.getParameterNames();
Object[] parameterValues = pjp.getArgs();
StringBuilder sb = new StringBuilder("==> ");
sb.append(asMethodQualifier(codeSignature)).append('(');
for (int i = 0; i < parameterValues.length; i++) {
if (i > 0) {
sb.append(", ");
}
sb.append(parameterNames[i]).append('=');
sb.append(Strings.toString(parameterValues[i]));
}
sb.append(')');
LOG.enter(sb.toString());
}
private static void methodReturn(JoinPoint pjp, Object result, long millis) {
Signature signature = pjp.getSignature();
boolean hasReturnType = signature instanceof MethodSignature
&& ((MethodSignature) signature).getReturnType() != void.class;
StringBuilder sb = new StringBuilder("<== ")
.append(asMethodQualifier(signature))
.append(" [").append(millis).append("ms]");
if (hasReturnType) {
sb.append(" = ");
sb.append(Strings.toString(result));
}
LOG.ret(sb.toString());
}
@SuppressWarnings("StringBufferReplaceableByString")
private static void methodThrown(JoinPoint pjp, Throwable tr, long millis) {
StringBuilder sb = new StringBuilder("X== ")
.append(asMethodQualifier(pjp.getSignature()))
.append(" [").append(millis).append("ms] ")
.append("THROWN");
LOG.thrown(sb.toString(), tr);
}
private static String asMethodQualifier(Signature signature) {
Class> cls = signature.getDeclaringType();
return asTypeName(cls) + "." + signature.getName();
}
private static String asTypeName(Class> cls) {
Class> enclosingCls = cls.getEnclosingClass();
if (enclosingCls == null) {
return cls.getSimpleName();
}
return asTypeName(enclosingCls) + "$" + cls.getSimpleName();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy