diff --git a/CHANGES.md b/CHANGES.md index 7ce0a1215..186467bb5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Release Notes. * Increase `ProfileTaskChannelService.snapshotQueue` default size from 50 to 4500 * Support 2.8 and 2.9 of pulsar client. * Add dubbo 3.x plugin. +* Fix TracePathMatcher should match pattern "**" with paths end by "/" #### Documentation diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/FastPathMatcher.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/FastPathMatcher.java index 4e9154208..eb79e5dd0 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/FastPathMatcher.java +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/FastPathMatcher.java @@ -84,6 +84,22 @@ public class FastPathMatcher implements TracePathMatcher { private boolean wildcardMatch(String pat, int p, String str, int s) { char pc = safeCharAt(pat, p); + // End of pattern, check string only has zero or one '/' at end. + // ↓ ↓ + // pattern: a/* a/* + // ↓ ↓ + // string: a/bc/ a/bc + if (pc == 0) { + while (true) { + char sc = safeCharAt(str, s); + // No '/' found + if (sc == 0) return true; + // Check '/' is the last char of string + if (sc == '/') return s == str.length() - 1; + s++; + } + } + while (true) { char sc = safeCharAt(str, s); @@ -122,9 +138,11 @@ public class FastPathMatcher implements TracePathMatcher { } private boolean multiWildcardMatch(String pat, int p, String str, int s) { - // End of pattern, just check the end of string is '/' quickly. - if (p >= pat.length() && s < str.length()) { - return str.charAt(str.length() - 1) != '/'; + switch (safeCharAt(pat, p)) { + // End of pattern, just return true quickly. + case 0: return true; + // Skip next '/' for pattern to match zero path part. + case '/': p++; } while (true) { diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java index 7a8cc5e0b..ed4439193 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java @@ -28,87 +28,100 @@ public class TracePathMatcherTest { @Test public void testAntPathMatcher() { TracePathMatcher pathMatcher = new FastPathMatcher(); - String patten = "/eureka/*"; + String pattern = "/eureka/*"; String path = "/eureka/apps"; - boolean match = pathMatcher.match(patten, path); + boolean match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/apps/"; - match = pathMatcher.match(patten, path); - Assert.assertFalse(match); + match = pathMatcher.match(pattern, path); + Assert.assertTrue(match); - patten = "/eureka/*/"; + pattern = "/eureka/**"; path = "/eureka/apps/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); + Assert.assertTrue(match); + + pattern = "/eureka/*/"; + path = "/eureka/apps/"; + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); path = "/eureka/apps/list"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); + Assert.assertFalse(match); + path = "/eureka/test"; + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); - patten = "/eureka/**"; + pattern = "/eureka/**"; path = "/eureka/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/apps/test"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/apps/test/"; - match = pathMatcher.match(patten, path); - Assert.assertFalse(match); + match = pathMatcher.match(pattern, path); + Assert.assertTrue(match); - patten = "eureka/apps/?"; + pattern = "eureka/apps/?"; path = "eureka/apps/list"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); path = "eureka/apps/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); path = "eureka/apps/a"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); - patten = "eureka/**/lists"; + pattern = "eureka/**/lists"; path = "eureka/apps/lists"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "eureka/apps/test/lists"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "eureka/apps/test/"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); path = "eureka/apps/test"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); - patten = "eureka/**/test/**"; + pattern = "eureka/**/test/**"; path = "eureka/apps/test/list"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "eureka/apps/foo/test/list/bar"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "eureka/apps/foo/test/list/bar/"; - match = pathMatcher.match(patten, path); - Assert.assertFalse(match); + match = pathMatcher.match(pattern, path); + Assert.assertTrue(match); path = "eureka/apps/test/list"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "eureka/test/list"; - match = pathMatcher.match(patten, path); - Assert.assertFalse(match); + match = pathMatcher.match(pattern, path); + Assert.assertTrue(match); - patten = "/eureka/**/b/**/*.txt"; + pattern = "/eureka/**/b/**/*.txt"; path = "/eureka/a/aa/aaa/b/bb/bbb/xxxxxx.txt"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); Assert.assertTrue(match); path = "/eureka/a/aa/aaa/b/bb/bbb/xxxxxx"; - match = pathMatcher.match(patten, path); + match = pathMatcher.match(pattern, path); + Assert.assertFalse(match); + + pattern = "abc/*"; + path = "abc/foo/bar"; + match = pathMatcher.match(pattern, path); Assert.assertFalse(match); } }