package io.delphiplatform.api.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.Nullable;
import org.springframework.util.StopWatch;

import java.io.Serializable;
import java.lang.reflect.Method;

import io.delphiplatform.api.util.logging.LoggingUtils;

/**
 * Simple AOP Alliance {@code MethodInterceptor} for performance monitoring. This interceptor has no effect on the intercepted method call.
 *
 * <p>Uses a {@code StopWatch} for the actual performance measuring.
 *
 * @see org.springframework.util.StopWatch
 * @see org.springframework.aop.interceptor.PerformanceMonitorInterceptor (logically based on)
 */
@SuppressWarnings("serial")
public class AppPerformanceMonitorInterceptor implements MethodInterceptor, Serializable {

    @Override
    @Nullable
    public Object invoke(MethodInvocation invocation) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        try {
            return invocation.proceed();
        } finally {
            //reflection methods here should be fast
            Method method = invocation.getMethod();
            Class<?> clazz = method.getDeclaringClass();

            String invocationTraceName = clazz.getName() + '.' + method.getName();

            LoggingUtils.stopAndLogAopPerformanceMeasurement(stopWatch, invocationTraceName);
        }
    }
}
