From 08611fae0fa6033a9b50451839fe7b5c3bb56e00 Mon Sep 17 00:00:00 2001 From: yikangfeng Date: Sun, 21 Apr 2019 15:52:09 +0800 Subject: [PATCH] Add exceptionsToIgnore configuration support in @SentinelResource annotation (#683) --- .../sentinel/annotation/SentinelResource.java | 10 ++++++ .../AbstractSentinelAspectSupport.java | 33 +++++++++++++++---- .../SentinelAnnotationIntegrationTest.java | 16 +++++++++ .../integration/service/FooService.java | 6 +++- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/annotation/SentinelResource.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/annotation/SentinelResource.java index 10631006..e4f07a66 100644 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/annotation/SentinelResource.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/annotation/SentinelResource.java @@ -65,4 +65,14 @@ public @interface SentinelResource { * @since 1.5.1 */ Class[] exceptionsToTrace() default {Throwable.class}; + + /** + * Indicates the exceptions to be ignored. Note that {@code exceptionsToTrace} should + * not appear with {@code exceptionsToIgnore} at the same time, or {@code exceptionsToIgnore} + * will be of higher precedence. + * + * @return the list of exception classes to ignore, empty by default + * @since 1.6.0 + */ + Class[] exceptionsToIgnore() default {}; } diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java index 90277736..dce92b8e 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java +++ b/sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java @@ -53,7 +53,7 @@ public abstract class AbstractSentinelAspectSupport { } protected Object handleBlockException(ProceedingJoinPoint pjp, String fallback, String blockHandler, - Class[] blockHandlerClass, BlockException ex) throws Exception { + Class[] blockHandlerClass, BlockException ex) throws Exception { // Execute fallback for degrading if configured. Object[] originArgs = pjp.getArgs(); if (isDegradeFailure(ex)) { @@ -78,6 +78,11 @@ public abstract class AbstractSentinelAspectSupport { } protected void traceException(Throwable ex, SentinelResource annotation) { + Class[] exceptionsToIgnore = annotation.exceptionsToIgnore(); + // The ignore list will be checked first. + if (exceptionsToIgnore.length > 0 && isIgnoredException(ex, exceptionsToIgnore)) { + return; + } if (isTracedException(ex, annotation.exceptionsToTrace())) { Tracer.trace(ex); } @@ -86,8 +91,10 @@ public abstract class AbstractSentinelAspectSupport { /** * Check whether the exception is in tracked list of exception classes. * - * @param ex provided throwable - * @param exceptionsToTrace list of exceptions to trace + * @param ex + * provided throwable + * @param exceptionsToTrace + * list of exceptions to trace * @return true if it should be traced, otherwise false */ private boolean isTracedException(Throwable ex, Class[] exceptionsToTrace) { @@ -102,6 +109,18 @@ public abstract class AbstractSentinelAspectSupport { return false; } + private boolean isIgnoredException(Throwable ex, Class[] exceptionsToIgnore) { + if (exceptionsToIgnore == null) { + return false; + } + for (Class exceptionToIgnore : exceptionsToIgnore) { + if (exceptionToIgnore.isAssignableFrom(ex.getClass())) { + return true; + } + } + return false; + } + private boolean isDegradeFailure(/*@NonNull*/ BlockException ex) { return ex instanceof DegradeException; } @@ -176,8 +195,8 @@ public abstract class AbstractSentinelAspectSupport { Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (name.equals(method.getName()) && checkStatic(mustStatic, method) - && returnType.isAssignableFrom(method.getReturnType()) - && Arrays.equals(parameterTypes, method.getParameterTypes())) { + && returnType.isAssignableFrom(method.getReturnType()) + && Arrays.equals(parameterTypes, method.getParameterTypes())) { RecordLog.info("Resolved method [{0}] in class [{1}]", name, clazz.getCanonicalName()); return method; @@ -190,7 +209,7 @@ public abstract class AbstractSentinelAspectSupport { } else { String methodType = mustStatic ? " static" : ""; RecordLog.warn("Cannot find{0} method [{1}] in class [{2}] with parameters {3}", - methodType, name, clazz.getCanonicalName(), Arrays.toString(parameterTypes)); + methodType, name, clazz.getCanonicalName(), Arrays.toString(parameterTypes)); return null; } } @@ -204,7 +223,7 @@ public abstract class AbstractSentinelAspectSupport { Class targetClass = joinPoint.getTarget().getClass(); Method method = getDeclaredMethodFor(targetClass, signature.getName(), - signature.getMethod().getParameterTypes()); + signature.getMethod().getParameterTypes()); if (method == null) { throw new IllegalStateException("Cannot resolve target method: " + signature.getMethod().getName()); } diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java index ed17ee28..986c064c 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/SentinelAnnotationIntegrationTest.java @@ -83,6 +83,22 @@ public class SentinelAnnotationIntegrationTest extends AbstractJUnit4SpringConte fooService.baz("Sentinel"); } + @Test + public void testAnnotationExceptionsToIgnore() { + assertThat(fooService.baz("Sentinel")).isEqualTo("cheers, Sentinel"); + String resourceName = "apiBaz"; + ClusterNode cn = ClusterBuilderSlot.getClusterNode(resourceName); + assertThat(cn).isNotNull(); + assertThat(cn.passQps()).isPositive(); + + try { + fooService.baz("fail"); + fail("should not reach here"); + } catch (IllegalMonitorStateException ex) { + assertThat(cn.exceptionQps()).isZero(); + } + } + @Test public void testNormalBlockHandlerAndFallback() throws Exception { assertThat(fooService.foo(1)).isEqualTo("Hello for 1"); diff --git a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java index f9afef49..25bb98be 100644 --- a/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java +++ b/sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/integration/service/FooService.java @@ -49,8 +49,12 @@ public class FooService { return ThreadLocalRandom.current().nextInt(0, 30000); } - @SentinelResource(value = "apiBaz", blockHandler = "bazBlockHandler") + @SentinelResource(value = "apiBaz", blockHandler = "bazBlockHandler", + exceptionsToIgnore = {IllegalMonitorStateException.class}) public String baz(String name) { + if (name.equals("fail")) { + throw new IllegalMonitorStateException("boom!"); + } return "cheers, " + name; }