From 29f6f6e50ecc01b4f04241742c1961e8527badf2 Mon Sep 17 00:00:00 2001 From: SevenPointOld Date: Thu, 24 May 2018 08:49:19 +0800 Subject: [PATCH] provides a optional-plugin for tracking ignores enhancement(#1203) (#1213) * provides a optional-plugin for tracking ignores enhancement(#1203) * trace ignore plugin config support override by system.env * optimize the trace ignore plugin and make normalization of pom * add AntPathMatcher and an junit test for it * No longer rely on the spring framework * add license at file header * rebuild pom and rewrite README * rebuild optional-plugins pom * clean up useless code * modify junit * rewrite the ant path match logic * rename the matcher class --- .../optional-spring-plugins/pom.xml | 7 +- apm-sniffer/optional-plugins/pom.xml | 11 +- .../trace-ignore-plugin/README.md | 6 + .../apm-trace-ignore-plugin.config | 23 ++ .../trace-ignore-plugin/pom.xml | 62 +++++ .../ignore/TraceIgnoreExtendService.java | 80 ++++++ .../trace/ignore/conf/IgnoreConfig.java | 37 +++ .../ignore/conf/IgnoreConfigInitializer.java | 107 ++++++++ .../trace/ignore/matcher/AntPathMatcher.java | 251 ++++++++++++++++++ .../ignore/matcher/TracePathMatcher.java | 29 ++ ...skywalking.apm.agent.core.boot.BootService | 19 ++ .../plugin/trace/ignore/TraceIgnoreTest.java | 57 ++++ .../trace/ignore/TracePathMatcherTest.java | 78 ++++++ ...skywalking.apm.agent.core.boot.BootService | 19 ++ 14 files changed, 779 insertions(+), 7 deletions(-) create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/README.md create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/apm-trace-ignore-plugin.config create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreExtendService.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfig.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfigInitializer.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/AntPathMatcher.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/TracePathMatcher.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreTest.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java create mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/resources/org.apache.skywalking.apm.agent.core.boot.BootService diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index b6129a640..bf573e83b 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -27,12 +27,13 @@ pom optional-spring-plugins - - ${project.build.directory}/../../../../../skywalking-agent/optional-plugins - spring-annotation-plugin + + /.. + + \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 9e7c01054..bd56ad773 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -30,12 +30,16 @@ net.bytebuddy ${shade.package}.${shade.net.bytebuddy.source} + UTF-8 - ${project.build.directory}/../../../../skywalking-agent/optional-plugins + + ${project.build.directory}${sdk.plugin.related.dir}/../../../../skywalking-agent + ${agent.package.dest.dir}/optional-plugins optional-spring-plugins + trace-ignore-plugin @@ -101,11 +105,10 @@ - - + + - diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md b/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md new file mode 100644 index 000000000..b6950a9ea --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md @@ -0,0 +1,6 @@ +#How to use trace ignore plugin +Please copy the apm-trace-ignore-plugin-x.jar to `agent/plugins` + +## How to set config + 1. This plugin support reading config from environment variables(The env key must start with `skywalking.`, the reuslt should be as same as in `apm-trace-ignore-plugin.config`) + 2. Or you can copy the `apm-trace-ignore-plugin.config` to `agent/config` then you'll set you need ignore paths in `apm-trace-ignore-plugin.config` diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/apm-trace-ignore-plugin.config b/apm-sniffer/optional-plugins/trace-ignore-plugin/apm-trace-ignore-plugin.config new file mode 100644 index 000000000..acb31c74d --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/apm-trace-ignore-plugin.config @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# If the operation name of the first span is matching, this segment should be ignored +# ant path match style +# /path/? Match any single character +# /path/* Match any number of characters +# /path/** Match any number of characters and support multilevel directories +# Multiple path comma separation, like trace.ignore_path=/eureka/**,/consul/** +#trace.ignore_path=/eureka/** diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml new file mode 100644 index 000000000..d348501ca --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -0,0 +1,62 @@ + + + + + optional-plugins + org.apache.skywalking + 5.0.0-beta2-SNAPSHOT + + 4.0.0 + + apm-trace-ignore-plugin + jar + + apm-trace-ignore-plugin + http://maven.apache.org + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + package + + run + + + + + + + + + + + + + + + + + + + diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreExtendService.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreExtendService.java new file mode 100644 index 000000000..2c88a1d1d --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreExtendService.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore; + +import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; +import org.apache.skywalking.apm.agent.core.boot.OverrideImplementor; +import org.apache.skywalking.apm.agent.core.conf.ConfigNotFoundException; +import org.apache.skywalking.apm.agent.core.context.AbstractTracerContext; +import org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService; +import org.apache.skywalking.apm.agent.core.context.IgnoredTracerContext; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.plugin.trace.ignore.conf.IgnoreConfig; +import org.apache.skywalking.apm.plugin.trace.ignore.conf.IgnoreConfigInitializer; +import org.apache.skywalking.apm.plugin.trace.ignore.matcher.AntPathMatcher; +import org.apache.skywalking.apm.plugin.trace.ignore.matcher.TracePathMatcher; +import org.apache.skywalking.apm.util.StringUtil; + +/** + * + * @author liujc [liujunc1993@163.com] + * + */ +@OverrideImplementor(ContextManagerExtendService.class) +public class TraceIgnoreExtendService extends ContextManagerExtendService { + + private static final ILog LOGGER = LogManager.getLogger(TraceIgnoreExtendService.class); + + private static final String DEFAULT_PATH_SEPARATOR = "/"; + + private static final String PATTERN_SEPARATOR = ","; + + private TracePathMatcher pathMatcher = new AntPathMatcher(); + + @Override + public void boot() { + try { + IgnoreConfigInitializer.initialize(); + } catch (ConfigNotFoundException e) { + LOGGER.error("trace ignore config init error", e); + } catch (AgentPackageNotFoundException e) { + LOGGER.error("trace ignore config init error", e); + } + } + + @Override + public AbstractTracerContext createTraceContext(String operationName, boolean forceSampling) { + String pattens = IgnoreConfig.Trace.IGNORE_PATH; + if (!StringUtil.isEmpty(pattens) && !forceSampling) { + String path = operationName; + if (!StringUtil.isEmpty(path) && path.length() > 1 && path.endsWith(DEFAULT_PATH_SEPARATOR)) { + path = path.substring(0, path.length() - 1); + } + + for (String pattern : pattens.split(PATTERN_SEPARATOR)) { + if (pathMatcher.match(pattern, path)) { + LOGGER.debug("operationName : " + operationName + " Ignore tracking"); + return new IgnoredTracerContext(); + } + } + } + return super.createTraceContext(operationName, forceSampling); + } +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfig.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfig.java new file mode 100644 index 000000000..f317ac2b4 --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfig.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore.conf; + +/** + * + * @author liujc [liujunc1993@163.com] + * + */ +public class IgnoreConfig { + + public static class Trace { + /** + * If the operation name of the first span is matching, this segment should be ignored + * /path/? Match any single character + * /path/* Match any number of characters + * /path/** Match any number of characters and support multilevel directories + */ + public static String IGNORE_PATH = ""; + } +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfigInitializer.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfigInitializer.java new file mode 100644 index 000000000..af8f599ea --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/conf/IgnoreConfigInitializer.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore.conf; + +import org.apache.skywalking.apm.agent.core.boot.AgentPackageNotFoundException; +import org.apache.skywalking.apm.agent.core.boot.AgentPackagePath; +import org.apache.skywalking.apm.agent.core.conf.ConfigNotFoundException; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.util.ConfigInitializer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +/** + * + * @author liujc [liujunc1993@163.com] + * + */ +public class IgnoreConfigInitializer { + private static final ILog LOGGER = LogManager.getLogger(IgnoreConfigInitializer.class); + private static String CONFIG_FILE_NAME = "/config/apm-trace-ignore-plugin.config"; + private static String ENV_KEY_PREFIX = "skywalking."; + + /** + * Try to locate `apm-trace-ignore-plugin.config`, which should be in the /optional-plugins/apm-trace-ignore-plugin/ dictionary of agent package. + *

+ * Also try to override the config by system.env and system.properties. All the keys in these two places should + * start with {@link #ENV_KEY_PREFIX}. e.g. in env `skywalking.trace.ignore_path=your_path` to override + * `trace.ignore_path` in apm-trace-ignore-plugin.config file. + *

+ */ + public static void initialize() throws ConfigNotFoundException, AgentPackageNotFoundException { + InputStream configFileStream; + try { + configFileStream = loadConfigFromAgentFolder(); + Properties properties = new Properties(); + properties.load(configFileStream); + ConfigInitializer.initialize(properties, IgnoreConfig.class); + } catch (Exception e) { + LOGGER.error(e, "Failed to read the config file, skywalking is going to run in default config."); + } + + try { + overrideConfigBySystemEnv(); + } catch (Exception e) { + LOGGER.error(e, "Failed to read the system env."); + } + } + + private static void overrideConfigBySystemEnv() throws IllegalAccessException { + Properties properties = new Properties(); + Properties systemProperties = System.getProperties(); + Iterator> entryIterator = systemProperties.entrySet().iterator(); + while (entryIterator.hasNext()) { + Map.Entry prop = entryIterator.next(); + if (prop.getKey().toString().startsWith(ENV_KEY_PREFIX)) { + String realKey = prop.getKey().toString().substring(ENV_KEY_PREFIX.length()); + properties.put(realKey, prop.getValue()); + } + } + + if (!properties.isEmpty()) { + ConfigInitializer.initialize(properties, IgnoreConfig.class); + } + } + + + /** + * Load the config file, where the agent jar is. + * + * @return the config file {@link InputStream}, or null if not needEnhance. + */ + private static InputStream loadConfigFromAgentFolder() throws AgentPackageNotFoundException, ConfigNotFoundException { + File configFile = new File(AgentPackagePath.getPath(), CONFIG_FILE_NAME); + if (configFile.exists() && configFile.isFile()) { + try { + LOGGER.info("Ignore config file found in {}.", configFile); + return new FileInputStream(configFile); + } catch (FileNotFoundException e) { + throw new ConfigNotFoundException("Fail to load apm-trace-ignore-plugin.config", e); + } + } + throw new ConfigNotFoundException("Fail to load ignore config file."); + } +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/AntPathMatcher.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/AntPathMatcher.java new file mode 100644 index 000000000..49f80cf2c --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/AntPathMatcher.java @@ -0,0 +1,251 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore.matcher; + +import org.apache.skywalking.apm.util.StringUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author liujc [liujunc1993@163.com] + * + */ +public class AntPathMatcher implements TracePathMatcher { + + private static final String DEFAULT_PATH_SEPARATOR = "/"; + + private static final String ANY_ONE_MATCHING_CHAR = "?"; + + private static final String ANY_MATCHING_CHAR = "*"; + + private static final String MULTILEVEL_DIRECTORIES_ANY_MATCHING_CHAR = ANY_MATCHING_CHAR.concat(ANY_MATCHING_CHAR); + + @Override + public boolean match(String pattern, String path) { + if (!MatchAssist.checkPatternAndPath(pattern, path)) { + return false; + } + + // resolve pattern and path by default path separator + String[] resolvedPatterns = MatchAssist.resolvePath(pattern); + String[] resolvedPaths = MatchAssist.resolvePath(path); + + int patternIdxStart = 0; + int patternIdxEnd = resolvedPatterns.length - 1; + int pathIdxStart = 0; + int pathIdxEnd = resolvedPaths.length - 1; + + + // try to match first '**' + while (true) { + if (patternIdxStart > patternIdxEnd || pathIdxStart > pathIdxEnd) { + break; + } + String resolvedPattern = resolvedPatterns[patternIdxStart]; + if (MULTILEVEL_DIRECTORIES_ANY_MATCHING_CHAR.equals(resolvedPattern)) { + break; + } + if (!MatchAssist.matchStrings(resolvedPattern, resolvedPaths[pathIdxStart])) { + return false; + } + patternIdxStart++; + pathIdxStart++; + } + + if (pathIdxStart > pathIdxEnd) { + if (patternIdxStart > patternIdxEnd) { + return pattern.endsWith(DEFAULT_PATH_SEPARATOR) == path.endsWith(DEFAULT_PATH_SEPARATOR); + } + return patternIdxStart == patternIdxEnd && resolvedPatterns[patternIdxStart].equals(ANY_MATCHING_CHAR) && path.endsWith(DEFAULT_PATH_SEPARATOR) + || MatchAssist.checkPatternIdx(patternIdxStart, patternIdxEnd, resolvedPatterns); + } + else if (patternIdxStart > patternIdxEnd) { + return false; + } + + // try to match last '**' + while (true) { + if (patternIdxStart > patternIdxEnd || pathIdxStart > pathIdxEnd) { + break; + } + String resolvedPattern = resolvedPatterns[patternIdxEnd]; + if (resolvedPattern.equals(MULTILEVEL_DIRECTORIES_ANY_MATCHING_CHAR)) { + break; + } + if (!MatchAssist.matchStrings(resolvedPattern, resolvedPaths[pathIdxEnd])) { + return false; + } + patternIdxEnd--; + pathIdxEnd--; + } + if (pathIdxStart > pathIdxEnd) { + return MatchAssist.checkPatternIdx(patternIdxStart, patternIdxEnd, resolvedPatterns); + } + + while (patternIdxStart != patternIdxEnd && pathIdxStart <= pathIdxEnd) { + int patIdxTmp = -1; + for (int i = patternIdxStart + 1; i <= patternIdxEnd; i++) { + if (resolvedPatterns[i].equals(MULTILEVEL_DIRECTORIES_ANY_MATCHING_CHAR)) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patternIdxStart + 1) { + // '**/**' situation, so skip one + patternIdxStart++; + continue; + } + // Find the pattern between patternIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = patIdxTmp - patternIdxStart - 1; + int strLength = pathIdxEnd - pathIdxStart + 1; + int foundIdx = -1; + + strLoop: + for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = resolvedPatterns[patternIdxStart + j + 1]; + String subStr = resolvedPatterns[pathIdxStart + i + j]; + if (!MatchAssist.matchStrings(subPat, subStr)) { + continue strLoop; + } + } + foundIdx = pathIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + patternIdxStart = patIdxTmp; + pathIdxStart = foundIdx + patLength; + } + + return MatchAssist.checkPatternIdx(patternIdxStart, patternIdxEnd, resolvedPatterns); + } + + + + + private static class MatchAssist { + + private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}"); + + private static final String DEFAULT_VARIABLE_PATTERN = "(.*)"; + + private static final ConcurrentMap GLOBAL_COMPILED_PATTERN_CACHE = new ConcurrentHashMap(); + + + private static boolean checkPatternIdx(int patternIdxStart, int patternIdxEnd, String[] resolvedPatterns) { + for (int i = patternIdxStart; i <= patternIdxEnd; i++) { + if (!resolvedPatterns[i].equals(MULTILEVEL_DIRECTORIES_ANY_MATCHING_CHAR)) { + return false; + } + } + return true; + } + + /** + * make sure of the pattern and path is validate + */ + private static boolean checkPatternAndPath(String pattern, String path) { + return !StringUtil.isEmpty(pattern) && !StringUtil.isEmpty(path) && + path.startsWith(DEFAULT_PATH_SEPARATOR) == pattern.startsWith(DEFAULT_PATH_SEPARATOR); + } + + /** + * resolve path by default path separator + */ + private static String[] resolvePath(String path) { + if (path == null) { + return null; + } + StringTokenizer st = new StringTokenizer(path, DEFAULT_PATH_SEPARATOR); + List tokens = new ArrayList(); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + token = token.trim(); + if (token.length() > 0) { + tokens.add(token); + } + } + return tokens.toArray(new String[tokens.size()]); + } + + /** + * use pattern match path + */ + private static boolean matchStrings(String pattern, String path) { + if (StringUtil.isEmpty(pattern) || StringUtil.isEmpty(pattern)) { + return false; + } + // if this pattern has been compiled + Pattern compliedPattern = GLOBAL_COMPILED_PATTERN_CACHE.get(pattern); + if (compliedPattern == null) { + // build new pattern + StringBuilder patternBuilder = new StringBuilder(); + Matcher matcher = GLOB_PATTERN.matcher(pattern); + int end = 0; + while (matcher.find()) { + patternBuilder.append(quote(pattern, end, matcher.start())); + String match = matcher.group(); + if (ANY_ONE_MATCHING_CHAR.equals(match)) { + patternBuilder.append('.'); + } + else if (ANY_MATCHING_CHAR.equals(match)) { + patternBuilder.append(".".concat(ANY_MATCHING_CHAR)); + } + else if (match.startsWith("{") && match.endsWith("}")) { + int colonIdx = match.indexOf(':'); + if (colonIdx == -1) { + patternBuilder.append(DEFAULT_VARIABLE_PATTERN); + } + else { + String variablePattern = match.substring(colonIdx + 1, match.length() - 1); + patternBuilder.append('('); + patternBuilder.append(variablePattern); + patternBuilder.append(')'); + } + } + end = matcher.end(); + } + patternBuilder.append(quote(pattern, end, pattern.length())); + compliedPattern = Pattern.compile(patternBuilder.toString()); + GLOBAL_COMPILED_PATTERN_CACHE.putIfAbsent(pattern, compliedPattern); + } + + return compliedPattern.matcher(path).matches(); + } + + private static String quote(String s, int start, int end) { + if (start == end) { + return ""; + } + return Pattern.quote(s.substring(start, end)); + } + } +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/TracePathMatcher.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/TracePathMatcher.java new file mode 100644 index 000000000..bd98dfda8 --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/java/org/apache/skywalking/apm/plugin/trace/ignore/matcher/TracePathMatcher.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore.matcher; + +/** + * + * @author liujc [liujunc1993@163.com] + * + */ +public interface TracePathMatcher { + + boolean match(String pattern, String path); +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService new file mode 100644 index 000000000..3a1396bdb --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +org.apache.skywalking.apm.plugin.trace.ignore.TraceIgnoreExtendService diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreTest.java b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreTest.java new file mode 100644 index 000000000..3c4444c2b --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TraceIgnoreTest.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore; + +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.context.AbstractTracerContext; +import org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService; +import org.apache.skywalking.apm.agent.core.context.IgnoredTracerContext; +import org.apache.skywalking.apm.agent.core.context.TracingContext; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.plugin.trace.ignore.conf.IgnoreConfig; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; + +/** + * @author liujc [liujunc1993@163.com] + */ +public class TraceIgnoreTest { + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Test + public void testServiceOverrideFromPlugin() { + ContextManagerExtendService service = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class); + Assert.assertEquals(TraceIgnoreExtendService.class, service.getClass()); + } + + @Test + public void testTraceIgnore() { + ContextManagerExtendService service = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class); + IgnoreConfig.Trace.IGNORE_PATH = "/eureka/**"; + AbstractTracerContext ignoredTracerContext = service.createTraceContext("/eureka/apps", false); + Assert.assertEquals(IgnoredTracerContext.class, ignoredTracerContext.getClass()); + + AbstractTracerContext traceContext = service.createTraceContext("/consul/apps", false); + Assert.assertEquals(TracingContext.class, traceContext.getClass()); + } + +} 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 new file mode 100644 index 000000000..8b3871d81 --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/java/org/apache/skywalking/apm/plugin/trace/ignore/TracePathMatcherTest.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.trace.ignore; + +import org.apache.skywalking.apm.plugin.trace.ignore.matcher.AntPathMatcher; +import org.apache.skywalking.apm.plugin.trace.ignore.matcher.TracePathMatcher; +import org.junit.Assert; +import org.junit.Test; + +public class TracePathMatcherTest { + + @Test + public void testAntPathMatcher() { + TracePathMatcher pathMatcher = new AntPathMatcher(); + String patten = "/eureka/*"; + String path = "/eureka/app"; + + boolean match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + path = "/eureka/apps/list"; + match = pathMatcher.match(patten, path); + Assert.assertFalse(match); + + patten = "/eureka/**"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + patten = "/eureka/apps/lis?"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + path = "eureka/apps/lists"; + match = pathMatcher.match(patten, path); + Assert.assertFalse(match); + + patten = "eureka/**/lists"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + path = "eureka/apps/a/b/c/lists"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + path = "eureka/apps/a/b/c/"; + match = pathMatcher.match(patten, path); + Assert.assertFalse(match); + + patten = "eureka/**/b/**"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + patten = "/eureka/**/b/**/*.txt"; + path = "/eureka/a/aa/aaa/b/bb/bbb/xxxxxx.txt"; + match = pathMatcher.match(patten, path); + Assert.assertTrue(match); + + path = "/eureka/a/aa/aaa/b/bb/bbb/xxxxxx"; + match = pathMatcher.match(patten, path); + Assert.assertFalse(match); + } +} diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/resources/org.apache.skywalking.apm.agent.core.boot.BootService b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/resources/org.apache.skywalking.apm.agent.core.boot.BootService new file mode 100644 index 000000000..3a1396bdb --- /dev/null +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/src/test/resources/org.apache.skywalking.apm.agent.core.boot.BootService @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +org.apache.skywalking.apm.plugin.trace.ignore.TraceIgnoreExtendService