public @Bean CustomizableTraceInterceptor interceptor() { CustomizableTraceInterceptor interceptor = new CustomizableTraceInterceptor(); interceptor.setEnterMessage("Entering $[methodName]($[arguments])."); interceptor.setExitMessage("Leaving $[methodName](..) with return value $[returnValue], took $[invocationTime]ms."); return interceptor; }
String className = getClassForLogging(methodInvocation.getThis()).getName(); matcher.appendReplacement(output, Matcher.quoteReplacement(className)); String shortName = ClassUtils.getShortName(getClassForLogging(methodInvocation.getThis())); matcher.appendReplacement(output, Matcher.quoteReplacement(shortName)); appendArgumentTypes(methodInvocation, matcher, output); appendReturnValue(methodInvocation, matcher, output, returnValue);
/** * Set the template used for method exit log messages. * This template can contain any of the following placeholders: * <ul> * <li>{@code $[targetClassName]}</li> * <li>{@code $[targetClassShortName]}</li> * <li>{@code $[argumentTypes]}</li> * <li>{@code $[arguments]}</li> * <li>{@code $[returnValue]}</li> * <li>{@code $[invocationTime]}</li> * </ul> */ public void setExitMessage(String exitMessage) { Assert.hasText(exitMessage, "exitMessage must not be empty"); checkForInvalidPlaceholders(exitMessage); Assert.doesNotContain(exitMessage, PLACEHOLDER_EXCEPTION, "exitMessage cannot contain placeholder" + PLACEHOLDER_EXCEPTION); this.exitMessage = exitMessage; }
@Test(expected = IllegalArgumentException.class) public void testSetEmptyEnterMessage() { // Must not be able to set empty enter message new CustomizableTraceInterceptor().setEnterMessage(""); }
@Test(expected = IllegalArgumentException.class) public void testSetExitMessageWithExceptionPlaceholder() { // Must not be able to set exit message with exception placeholder new CustomizableTraceInterceptor().setExitMessage(CustomizableTraceInterceptor.PLACEHOLDER_EXCEPTION); }
@Bean @Role(ROLE_INFRASTRUCTURE) public Advice traceInterceptor() { CustomizableTraceInterceptor traceInterceptor = new CustomizableTraceInterceptor(); traceInterceptor.setUseDynamicLogger(true); traceInterceptor.setEnterMessage("$[methodName]($[arguments])"); traceInterceptor.setExitMessage("~$[methodName]=$[returnValue] ($[invocationTime])"); traceInterceptor.setExceptionMessage("!$[methodName]"); return traceInterceptor; }
@Configuration @EnableAspectJAutoProxy public class SpringDataExecutionLoggingConfiguration { @Bean public CustomizableTraceInterceptor customizableTraceInterceptor() { CustomizableTraceInterceptor customizableTraceInterceptor = new CustomizableTraceInterceptor(); customizableTraceInterceptor.setUseDynamicLogger(true); customizableTraceInterceptor.setExitMessage("Executed $[methodName] in $[invocationTime]"); return customizableTraceInterceptor; } @Bean public Advisor advisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression("execution(public * org.springframework.data.jpa.repository.CrudRepository+.*(..))"); return new DefaultPointcutAdvisor(pointcut, customizableTraceInterceptor()); } }
@Test public void testSunnyDayPathLogsCorrectlyWithPrettyMuchAllPlaceholdersMatching() throws Throwable { MethodInvocation methodInvocation = mock(MethodInvocation.class); given(methodInvocation.getMethod()).willReturn(String.class.getMethod("toString", new Class[0])); given(methodInvocation.getThis()).willReturn(this); given(methodInvocation.getArguments()).willReturn(new Object[]{"$ One \\$", new Long(2)}); given(methodInvocation.proceed()).willReturn("Hello!"); Log log = mock(Log.class); given(log.isTraceEnabled()).willReturn(true); CustomizableTraceInterceptor interceptor = new StubCustomizableTraceInterceptor(log); interceptor.setEnterMessage(new StringBuffer() .append("Entering the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME) .append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_NAME) .append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS) .append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES) .append(").").toString()); interceptor.setExitMessage(new StringBuffer() .append("Exiting the '").append(CustomizableTraceInterceptor.PLACEHOLDER_METHOD_NAME) .append("' method of the [").append(CustomizableTraceInterceptor.PLACEHOLDER_TARGET_CLASS_SHORT_NAME) .append("] class with the following args (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENTS) .append(") and arg types (").append(CustomizableTraceInterceptor.PLACEHOLDER_ARGUMENT_TYPES) .append("), returning '").append(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE) .append("' and taking '").append(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME) .append("' this long.").toString()); interceptor.invoke(methodInvocation); verify(log, times(2)).trace(anyString()); }
@Test(expected = IllegalArgumentException.class) public void testSetEmptyExceptionMessage() { // Must not be able to set empty exception message new CustomizableTraceInterceptor().setExceptionMessage(""); }
try { stopWatch.start(name); writeToLog(logger, replacePlaceholders(this.enterMessage, invocation, null, null, -1)); returnValue = invocation.proceed(); return returnValue; writeToLog(logger, replacePlaceholders( this.exceptionMessage, invocation, null, ex, stopWatch.getTotalTimeMillis()), ex); throw ex; stopWatch.stop(); writeToLog(logger, replacePlaceholders( this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
String targetClassName = escape(methodInvocation.getThis().getClass().getName()); matcher.appendReplacement(output, targetClassName); matcher.appendReplacement(output, escape(ClassUtils.getShortName(methodInvocation.getThis().getClass()))); matcher.appendReplacement(output, escape(StringUtils.arrayToCommaDelimitedString(methodInvocation.getArguments()))); appendArgumentTypes(methodInvocation, matcher, output); appendReturnValue(methodInvocation, matcher, output, returnValue);
public StubCustomizableTraceInterceptor(Log log) { super.setUseDynamicLogger(false); this.log = log; }
try { stopWatch.start(name); logger.trace(replacePlaceholders(this.enterMessage, invocation, null, null, -1)); returnValue = invocation.proceed(); return returnValue; logger.trace(replacePlaceholders(this.exceptionMessage, invocation, null, ex, -1), ex); throw ex; if (!exitThroughException) { logger.trace( replacePlaceholders(this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
@Test(expected = IllegalArgumentException.class) public void testSetEnterMessageWithInvocationTimePlaceholder() { // Must not be able to set enter message with invocation time placeholder new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_INVOCATION_TIME); }
@Test(expected = IllegalArgumentException.class) public void testSetEmptyExitMessage() { // Must not be able to set empty exit message new CustomizableTraceInterceptor().setExitMessage(""); }
@Test(expected = IllegalArgumentException.class) public void testSetExceptionMethodWithReturnValuePlaceholder() { // Must not be able to set exception message with return value placeholder new CustomizableTraceInterceptor().setExceptionMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE); }
try { stopWatch.start(name); writeToLog(logger, replacePlaceholders(this.enterMessage, invocation, null, null, -1)); returnValue = invocation.proceed(); return returnValue; writeToLog(logger, replacePlaceholders( this.exceptionMessage, invocation, null, ex, stopWatch.getTotalTimeMillis()), ex); throw ex; stopWatch.stop(); writeToLog(logger, replacePlaceholders( this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
@Bean public CustomizableTraceInterceptor interceptor() { CustomizableTraceInterceptor interceptor = new CustomizableTraceInterceptor(); interceptor.setEnterMessage("Entering $[methodName]($[arguments])."); interceptor.setExitMessage("Leaving $[methodName](..) with return value $[returnValue], took $[invocationTime]ms."); return interceptor; }
@Test(expected = IllegalArgumentException.class) public void testSetEnterMessageWithReturnValuePlaceholder() { // Must not be able to set enter message with return value placeholder new CustomizableTraceInterceptor().setEnterMessage(CustomizableTraceInterceptor.PLACEHOLDER_RETURN_VALUE); }
String className = getClassForLogging(methodInvocation.getThis()).getName(); matcher.appendReplacement(output, Matcher.quoteReplacement(className)); String shortName = ClassUtils.getShortName(getClassForLogging(methodInvocation.getThis())); matcher.appendReplacement(output, Matcher.quoteReplacement(shortName)); appendArgumentTypes(methodInvocation, matcher, output); appendReturnValue(methodInvocation, matcher, output, returnValue);