From f3e705c5f33cf9fefce8fb459d6d0bb8ccfec355 Mon Sep 17 00:00:00 2001 From: Carpenter Lee Date: Wed, 22 May 2019 10:06:03 +0800 Subject: [PATCH] Add exceptionsToTrace and exceptionsToIgnore support in Tracer (#766) Signed-off-by: Carpenter Lee --- .../java/com/alibaba/csp/sentinel/Tracer.java | 101 +++++++++++++++++- .../com/alibaba/csp/sentinel/TracerTest.java | 70 ++++++++++++ 2 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 sentinel-core/src/test/java/com/alibaba/csp/sentinel/TracerTest.java diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Tracer.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Tracer.java index c9a4e573..08df6b2c 100755 --- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Tracer.java +++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Tracer.java @@ -22,6 +22,7 @@ import com.alibaba.csp.sentinel.node.ClusterNode; import com.alibaba.csp.sentinel.node.DefaultNode; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.metric.extension.MetricExtension; +import com.alibaba.csp.sentinel.util.AssertUtil; /** * This class is used to record other exceptions except block exception. @@ -29,7 +30,12 @@ import com.alibaba.csp.sentinel.metric.extension.MetricExtension; * @author jialiang.linjl * @author Eric Zhao */ -public final class Tracer { +public class Tracer { + + protected static Class[] traceClasses; + protected static Class[] ignoreClasses; + + protected Tracer() {} /** * Trace provided {@link Throwable} and increment exception count to entry in current context. @@ -47,7 +53,7 @@ public final class Tracer { * @param count exception count to add */ public static void trace(Throwable e, int count) { - if (e == null || e instanceof BlockException) { + if (!shouldTrace(e)) { return; } @@ -68,7 +74,7 @@ public final class Tracer { * @since 1.4.2 */ public static void traceContext(Throwable e, int count, Context context) { - if (e == null || e instanceof BlockException) { + if (!shouldTrace(e)) { return; } if (context == null) { @@ -97,7 +103,7 @@ public final class Tracer { * @since 1.4.2 */ public static void traceEntry(Throwable e, int count, Entry entry) { - if (e == null || e instanceof BlockException) { + if (!shouldTrace(e)) { return; } if (entry == null || entry.getCurNode() == null) { @@ -124,5 +130,90 @@ public final class Tracer { clusterNode.trace(t, count); } - private Tracer() {} + /** + * Set exception to trace. If not set, all Exception except for {@link BlockException} will be traced. + *

+ * Note that if both {@link #setExceptionsToIgnore(Class[])} and this method is set, + * the ExceptionsToIgnore will be of higher precedence. + *

+ * + * @param traceClasses the list of exception classes to trace. + * @since 1.6.1 + */ + @SafeVarargs + public static void setExceptionsToTrace(Class... traceClasses) { + checkNotNull(traceClasses); + Tracer.traceClasses = traceClasses; + } + + /** + * Get exception classes to trace. + * + * @return an array of exception classes to trace. + * @since 1.6.1 + */ + public static Class[] getExceptionsToTrace() { + return traceClasses; + } + + /** + * Set exceptions to ignore. if not set, all Exception except for {@link BlockException} will be traced. + *

+ * Note that if both {@link #setExceptionsToTrace(Class[])} and this method is set, + * the ExceptionsToIgnore will be of higher precedence. + *

+ * + * @param ignoreClasses the list of exception classes to ignore. + * @since 1.6.1 + */ + @SafeVarargs + public static void setExceptionsToIgnore(Class... ignoreClasses) { + checkNotNull(ignoreClasses); + Tracer.ignoreClasses = ignoreClasses; + } + + /** + * Get exception classes to ignore. + * + * @return an array of exception classes to ignore. + * @since 1.6.1 + */ + public static Class[] getExceptionsToIgnore() { + return ignoreClasses; + } + + private static void checkNotNull(Class[] classes) { + AssertUtil.notNull(classes, "trace or ignore classes must not be null"); + for (Class clazz : classes) { + AssertUtil.notNull(clazz, "trace or ignore classes must not be null"); + } + } + + /** + * Check whether the throwable should be traced. + * + * @param t the throwable to check. + * @return true if the throwable should be traced, else return false. + */ + protected static boolean shouldTrace(Throwable t) { + if (t == null || t instanceof BlockException) { + return false; + } + if (ignoreClasses != null) { + for (Class clazz : ignoreClasses) { + if (clazz != null && clazz.isAssignableFrom(t.getClass())) { + return false; + } + } + } + if (traceClasses != null) { + for (Class clazz : traceClasses) { + if (clazz != null && clazz.isAssignableFrom(t.getClass())) { + return true; + } + } + return false; + } + return true; + } } diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/TracerTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/TracerTest.java new file mode 100644 index 00000000..4b2352e1 --- /dev/null +++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/TracerTest.java @@ -0,0 +1,70 @@ +package com.alibaba.csp.sentinel; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author Carpenter Lee + */ +public class TracerTest extends Tracer { + + @Test + public void setExceptionsToTrace() { + Tracer.ignoreClasses = null; + Tracer.traceClasses = null; + Tracer.setExceptionsToTrace(TraceException.class, TraceException2.class); + Assert.assertTrue(Tracer.shouldTrace(new TraceException2())); + Assert.assertTrue(Tracer.shouldTrace(new TraceExceptionSub())); + Assert.assertFalse(Tracer.shouldTrace(new Exception())); + } + + @Test + public void setExceptionsToIgnore() { + Tracer.ignoreClasses = null; + Tracer.traceClasses = null; + Tracer.setExceptionsToIgnore(IgnoreException.class, IgnoreException2.class); + Assert.assertFalse(Tracer.shouldTrace(new IgnoreException())); + Assert.assertFalse(Tracer.shouldTrace(new IgnoreExceptionSub())); + Assert.assertTrue(Tracer.shouldTrace(new Exception())); + } + + @Test + public void testBoth() { + Tracer.ignoreClasses = null; + Tracer.traceClasses = null; + Tracer.setExceptionsToTrace(TraceException.class, TraceException2.class, BothException.class); + Tracer.setExceptionsToIgnore(IgnoreException.class, IgnoreException2.class, BothException.class); + Assert.assertFalse(Tracer.shouldTrace(new IgnoreException())); + Assert.assertFalse(Tracer.shouldTrace(new BothException())); + Assert.assertTrue(Tracer.shouldTrace(new TraceException())); + } + + @Test(expected = IllegalArgumentException.class) + public void testNull() { + Tracer.setExceptionsToTrace(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testNull1() { + Tracer.setExceptionsToTrace(TraceException.class, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testNull2() { + Tracer.setExceptionsToIgnore(IgnoreException.class, null); + } + + private class TraceException extends Exception {} + + private class TraceException2 extends Exception {} + + private class TraceExceptionSub extends TraceException {} + + private class IgnoreException extends Exception {} + + private class IgnoreException2 extends Exception {} + + private class IgnoreExceptionSub extends IgnoreException {} + + private class BothException extends Exception {} +} \ No newline at end of file