2

我正在尝试构建一个查询日志分析器,它计算每个查询的执行时间,并记录查询是否需要更多时间。与 Wrapper 相比,使用 AspectJ 需要更多时间。因此,如果有性能改进的余地,我想使用 byte buddy 或其他一些库。

这是我当前使用 AspectJ 的实现。

@Aspect
public class QueryLoggerProfiler {
    private static final Logger LOGGER = Logger.getLogger(QueryLoggerProfiler.class.getName());

    public static final String QUERY_LOGGING_POINTCUT = "execution(* com.abc.PreparedStatement.execute*(..))";

    @
    Pointcut(QUERY_LOGGING_POINTCUT)
    private void queryPointcut() {}

    @
    Around("queryPointcut()")
    public Object profile(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        long start = System.currentTimeMillis();
        Object output = joinPoint.proceed();
        long elapsedTime = System.currentTimeMillis() - start;
        if (elapsedTime >= 5) {
            LOGGER.info(">>>>>>>>>>>>>>>>>>>... Going to call the method ... " + method.getName());
            LOGGER.info(">>>>>>>>>>>>>>>>>>>... With parameter ... " + method.getParameters());
            LOGGER.info(">>>>>>>>>>>>>>>>>>>... Method execution time: " + elapsedTime + " milliseconds.");
        }
        return output;
    }
}

有没有办法记录以及没有性能瓶颈?

4

2 回答 2

0

实际上我的代码如下。

public static void premain(String agentArgument, Instrumentation instrumentation) {
    System.out.println(">>>>>>>>>>>>>>>>>> Entered premain");
    try {
        new AgentBuilder.Default()
                .type(ElementMatchers.nameStartsWith("com.mycomp.hikari.LoggingPreparedStatement"))
                .transform((builder, typeDescription, classLoader) -> builder
                        .method(ElementMatchers.any())
                        .intercept(MethodDelegation.to(new Interceptor())))
                .installOn(instrumentation);
    } catch (RuntimeException e) {
        System.out.println(">>>>>>>>>>>>>>>>>> Exception instrumenting code : " + e);
        e.printStackTrace();
    }
}

然后将拦截器类作为....

public class Interceptor {
@RuntimeType
public Object intercept(@SuperCall Callable<?> callable, @AllArguments Object[] allArguments, @Origin Method method, @Origin Class clazz) throws Exception {
    long startTime = System.currentTimeMillis();
    Object response;
    try {
        response = callable.call();
    } catch (Exception e) {
        System.out.println(">>>>>>>>>>>>>>>>>>>> .... Exception occurred in method call: " + methodName(clazz, method, allArguments) + " Exception = " + e);
        throw e;
    } finally {
        long elapsedTime = System.currentTimeMillis() - startTime;
        if (elapsedTime > 3)
        System.out.println(">>>>>>>>>>>>>>>>>>>> .... Method " + methodName(clazz, method, allArguments) + " completed in " + elapsedTime + " milliseconds");
    }
    return response;
}

private String methodName(Class clazz, Method method, Object[] allArguments) {
    StringBuilder builder = new StringBuilder();
    builder.append(clazz.getName());
    builder.append(".");
    builder.append(method.getName());
    builder.append("(");
    for (int i = 0; i < method.getParameters().length; i++) {

        builder.append(method.getParameters()[i].getName());
        if (allArguments != null) {
            Object arg = allArguments[i];
            builder.append("=");
            builder.append(arg != null ? arg.toString() : "null");
        }

        if (i < method.getParameters().length - 1) {
            builder.append(", ");
        }
    }
    builder.append(")");
    return builder.toString();
  }
}
于 2016-09-05T08:47:40.403 回答
0

最简单的方法是将Advice组件与AgentBuilder. 这将允许您定义类似于以下内容的代理:

public static void premain(String arg, Instrumentation inst) {
  new AgentBuilder.Default()
    .type(named("com.abc.PreparedStatement"))
    .transform(new Transformer() {
      public DynamicType.Builder transform(DynamicType.Builder builder) {
       return builder.visit(Advice.to(MyAdvice.class).on(nameStartsWith("execute")));
     } 
    }).installOn(inst);
}

这将为MyAdvice指定的类型和名称应用类中定义的方法。查看 javadocAdvice以了解如何获取参数或如何指定要调用的方法。

有关如何使用 Byte Buddy 和 Javaagents 检测代码的一般信息,请参阅这篇文章

于 2016-08-09T20:55:16.350 回答