diff --git a/.travis.yml b/.travis.yml index 69492c506..9b51e7983 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ install: - mvn install:install-file -Dfile=jmxri-1.2.1.jar -DgroupId=com.sun.jmx -DartifactId=jmxri -Dversion=1.2.1 -Dpackaging=jar - mvn install:install-file -Dfile=dubbox-2.8.4.jar -DgroupId=com.alibaba -DartifactId=dubbox -Dversion=2.8.4 -Dpackaging=jar - mvn install:install-file -Dfile=ojdbc14-10.2.0.4.0.jar -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.2.0.4.0 -Dpackaging=jar + - mvn install:install-file -Dfile=resin-4.0.41.jar -DgroupId=com.caucho -DartifactId=resin -Dversion=4.0.41 -Dpackaging=jar - cd .. script: diff --git a/README.md b/README.md index 6ec21c3ce..fff3fae3e 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,13 @@ ___ # Contributors _In chronological order_ -* 吴晟 [@wu-sheng](https://github.com/wu-sheng) -* 张鑫 [@ascrutae](https://github.com/ascrutae) -* 谭真 [@mircoteam](https://github.com/mircoteam) +* 吴晟 [@wu-sheng](https://github.com/wu-sheng) Principle Engineer, 2012 Lab, Huawei. +* 张鑫 [@ascrutae](https://github.com/ascrutae) +* 谭真 [@mircoteam](https://github.com/mircoteam) Advanced R&D Engineers, Creative & Interactive Group. * 徐妍 [@TastySummer](https://github.com/TastySummer) -* 彭勇升 [@pengys5](https://github.com/pengys5) +* 彭勇升 [@pengys5](https://github.com/pengys5) Technical Specialist, OneAPM. * 戴文 -* 柏杨 [@bai-yang](https://github.com/bai-yang) +* 柏杨 [@bai-yang](https://github.com/bai-yang) Senior Engineer, Alibaba Group. # Screenshots - Topological graph of application clusters. diff --git a/apm-commons/apm-util/src/main/java/org/skywalking/apm/util/ConfigInitializer.java b/apm-commons/apm-util/src/main/java/org/skywalking/apm/util/ConfigInitializer.java index a210636ec..3a1dea446 100644 --- a/apm-commons/apm-util/src/main/java/org/skywalking/apm/util/ConfigInitializer.java +++ b/apm-commons/apm-util/src/main/java/org/skywalking/apm/util/ConfigInitializer.java @@ -3,6 +3,7 @@ package org.skywalking.apm.util; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.LinkedList; +import java.util.List; import java.util.Properties; import java.util.logging.Logger; @@ -20,7 +21,7 @@ public class ConfigInitializer { } private static void initNextLevel(Properties properties, Class recentConfigType, - ConfigDesc parentDesc) throws IllegalArgumentException, IllegalAccessException { + ConfigDesc parentDesc) throws IllegalArgumentException, IllegalAccessException { for (Field field : recentConfigType.getFields()) { if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) { String configKey = (parentDesc + "." + field.getName()).toLowerCase(); @@ -35,8 +36,10 @@ public class ConfigInitializer { field.set(null, Long.valueOf(value)); else if (type.equals(boolean.class)) field.set(null, Boolean.valueOf(value)); + else if (type.equals(List.class)) + field.set(null, convert2List(value)); else if (type.isEnum()) - field.set(null, Enum.valueOf((Class) type, value.toUpperCase())); + field.set(null, Enum.valueOf((Class)type, value.toUpperCase())); } } } @@ -46,6 +49,22 @@ public class ConfigInitializer { parentDesc.removeLastDesc(); } } + + private static List convert2List(String value) { + List result = new LinkedList(); + if (StringUtil.isEmpty(value)) { + return result; + } + + String[] segments = value.split(","); + for (String segment : segments) { + String trimmedSegment = segment.trim(); + if (!StringUtil.isEmpty(trimmedSegment)) { + result.add(trimmedSegment); + } + } + return result; + } } class ConfigDesc { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java index c4ac43f4d..a8789cda3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/conf/Config.java @@ -1,5 +1,7 @@ package org.skywalking.apm.agent.core.conf; +import java.util.LinkedList; +import java.util.List; import org.skywalking.apm.agent.core.logging.LogLevel; import org.skywalking.apm.agent.core.logging.WriterFactory; @@ -83,6 +85,16 @@ public class Config { } public static class Plugin { + + /** + * Name of disabled plugin, The value spilt by , + * if you have multiple plugins need to disable. + * + * Here are the plugin names : + * tomcat-7.x/8.x, dubbo, jedis-2.x, motan, httpclient-4.x, jdbc, mongodb-3.x. + */ + public static List DISABLED_PLUGINS = new LinkedList(); + public static class MongoDB { /** * If true, trace all the parameters, default is false. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index 2c16b2866..f4cda7556 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -24,7 +24,7 @@ public abstract class AbstractClassEnhancePluginDefine { * * @param transformClassName target class. * @param builder byte-buddy's builder to manipulate target class's bytecode. - * @return be defined builder. + * @return the new builder, or null if not be enhanced. * @throws PluginException, when set builder failure. */ public DynamicType.Builder define(String transformClassName, @@ -33,7 +33,7 @@ public abstract class AbstractClassEnhancePluginDefine { if (StringUtil.isEmpty(transformClassName)) { logger.warn("classname of being intercepted is not defined by {}.", interceptorDefineClassName); - return builder; + return null; } logger.debug("prepare to enhance class {} by {}.", transformClassName, interceptorDefineClassName); @@ -48,7 +48,7 @@ public abstract class AbstractClassEnhancePluginDefine { if (!witnessClassResolution.isResolved()) { logger.warn("enhance class {} by plugin {} is not working. Because witness class {} is not existed.", transformClassName, interceptorDefineClassName, witnessClass); - return builder; + return null; } } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java index 41bd8f261..cad9fa8a1 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginBootstrap.java @@ -42,18 +42,18 @@ public class PluginBootstrap { } } - List pluginClassList = PluginCfg.INSTANCE.getPluginClassList(); + List pluginClassList = PluginCfg.INSTANCE.getPluginClassList(); List plugins = new ArrayList(); - for (String pluginClassName : pluginClassList) { + for (PluginDefine pluginDefine : pluginClassList) { try { - logger.debug("loading plugin class {}.", pluginClassName); + logger.debug("loading plugin class {}.", pluginDefine.getDefineClass()); AbstractClassEnhancePluginDefine plugin = - (AbstractClassEnhancePluginDefine) Class.forName(pluginClassName).newInstance(); + (AbstractClassEnhancePluginDefine) Class.forName(pluginDefine.getDefineClass()).newInstance(); plugin.setClassTypePool(classTypePool); plugins.add(plugin); } catch (Throwable t) { - logger.error(t, "loade plugin [{}] failure.", pluginClassName); + logger.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass()); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginCfg.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginCfg.java index 151478d0d..ce7eeed84 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginCfg.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginCfg.java @@ -1,26 +1,34 @@ package org.skywalking.apm.agent.core.plugin; -import org.skywalking.apm.util.StringUtil; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; +import org.skywalking.apm.agent.core.plugin.exception.IllegalPluginDefineException; +import org.skywalking.apm.logging.ILog; +import org.skywalking.apm.logging.LogManager; public enum PluginCfg { INSTANCE; - private List pluginClassList = new ArrayList(); + private static final ILog logger = LogManager.getLogger(PluginCfg.class); + + private List pluginClassList = new ArrayList(); void load(InputStream input) throws IOException { try { BufferedReader reader = new BufferedReader(new InputStreamReader(input)); - String pluginDefineClassName = null; - while ((pluginDefineClassName = reader.readLine()) != null) { - if (!StringUtil.isEmpty(pluginDefineClassName)) { - pluginClassList.add(pluginDefineClassName.trim()); + String pluginDefine = null; + while ((pluginDefine = reader.readLine()) != null) { + try { + PluginDefine plugin = PluginDefine.build(pluginDefine); + if (plugin.enable()) { + pluginClassList.add(plugin); + } + } catch (IllegalPluginDefineException e) { + logger.error("Failed to format plugin define.", e); } } } finally { @@ -28,7 +36,8 @@ public enum PluginCfg { } } - public List getPluginClassList() { + public List getPluginClassList() { return pluginClassList; } + } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginDefine.java new file mode 100644 index 000000000..96a82f896 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginDefine.java @@ -0,0 +1,45 @@ +package org.skywalking.apm.agent.core.plugin; + +import org.skywalking.apm.agent.core.conf.Config; +import org.skywalking.apm.agent.core.plugin.exception.IllegalPluginDefineException; +import org.skywalking.apm.util.StringUtil; + +public class PluginDefine { + /** + * Plugin name. + */ + private String name; + + /** + * The class name of plugin defined. + */ + private String defineClass; + + private PluginDefine(String name, String defineClass) { + this.name = name; + this.defineClass = defineClass; + } + + public static PluginDefine build(String define) throws IllegalPluginDefineException { + if (StringUtil.isEmpty(define)) { + throw new IllegalPluginDefineException(define); + } + + String[] pluginDefine = define.split("="); + if (pluginDefine.length != 2) { + throw new IllegalPluginDefineException(define); + } + + return new PluginDefine(pluginDefine[0], pluginDefine[1]); + } + + public boolean enable() { + return !Config.Plugin.DISABLED_PLUGINS.contains(name); + } + + public String getDefineClass() { + return defineClass; + } +} + + diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java index 2caa7214b..45ce1d5b5 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/PluginFinder.java @@ -1,6 +1,7 @@ package org.skywalking.apm.agent.core.plugin; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -11,7 +12,7 @@ import java.util.Map; * @author wusheng */ public class PluginFinder { - private final Map pluginDefineMap = new HashMap(); + private final Map> pluginDefineMap = new HashMap>(); public PluginFinder(List plugins) { for (AbstractClassEnhancePluginDefine plugin : plugins) { @@ -21,11 +22,17 @@ public class PluginFinder { continue; } - pluginDefineMap.put(enhanceClassName, plugin); + LinkedList pluginDefinesWithSameTarget = pluginDefineMap.get(enhanceClassName); + if (pluginDefinesWithSameTarget == null) { + pluginDefinesWithSameTarget = new LinkedList(); + pluginDefineMap.put(enhanceClassName, pluginDefinesWithSameTarget); + } + + pluginDefinesWithSameTarget.add(plugin); } } - public AbstractClassEnhancePluginDefine find(String enhanceClassName) { + public List find(String enhanceClassName) { if (pluginDefineMap.containsKey(enhanceClassName)) { return pluginDefineMap.get(enhanceClassName); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/exception/IllegalPluginDefineException.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/exception/IllegalPluginDefineException.java new file mode 100644 index 000000000..41fb13b7b --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/exception/IllegalPluginDefineException.java @@ -0,0 +1,10 @@ +package org.skywalking.apm.agent.core.plugin.exception; + +/** + * Thrown to indicate that a illegal format plugin definition has been defined in skywalking-plugin.define. + */ +public class IllegalPluginDefineException extends Exception { + public IllegalPluginDefineException(String define) { + super("Illegal plugin define : " + define); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.skywalking.apm.agent.core.boot.BootService b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.skywalking.apm.agent.core.boot.BootService index 45405000c..0b8021650 100644 --- a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.skywalking.apm.agent.core.boot.BootService +++ b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.skywalking.apm.agent.core.boot.BootService @@ -1,4 +1,4 @@ org.skywalking.apm.agent.core.queue.TraceSegmentProcessQueue org.skywalking.apm.agent.core.context.ContextManager org.skywalking.apm.agent.core.client.CollectorClientService -org.skywalking.apm.agent.core.sampling.SamplingService +org.skywalking.apm.agent.core.sampling.SamplingService \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/PluginCfgTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/PluginCfgTest.java index 7853f3616..3806698c1 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/PluginCfgTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/skywalking/apm/agent/core/plugin/PluginCfgTest.java @@ -17,7 +17,7 @@ import java.util.List; public class PluginCfgTest { @Test public void testLoad() throws IOException { - String data = "com.test.classA\r\ncom.test.ClassB"; + String data = "TestA=com.test.classA\r\nTestB=com.test.ClassB"; final byte[] dataBytes = data.getBytes(); PluginCfg.INSTANCE.load(new InputStream() { int index = 0; @@ -31,10 +31,10 @@ public class PluginCfgTest { } }); - List list = PluginCfg.INSTANCE.getPluginClassList(); + List list = PluginCfg.INSTANCE.getPluginClassList(); Assert.assertEquals(2, list.size()); - Assert.assertEquals("com.test.classA", list.get(0)); - Assert.assertEquals("com.test.ClassB", list.get(1)); + Assert.assertEquals("com.test.classA", list.get(0).getDefineClass()); + Assert.assertEquals("com.test.ClassB", list.get(1).getDefineClass()); } @Before diff --git a/apm-sniffer/apm-agent-core/src/test/resources/skywalking-plugin.def b/apm-sniffer/apm-agent-core/src/test/resources/skywalking-plugin.def index 32e8cdffb..2b07edf84 100644 --- a/apm-sniffer/apm-agent-core/src/test/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-agent-core/src/test/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.agent.core.plugin.MockAbstractClassEnhancePluginDefine +MOCKPLUGIN=org.skywalking.apm.agent.core.plugin.MockAbstractClassEnhancePluginDefine diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 351656ed7..4299ac757 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -60,6 +60,16 @@ apm-mongodb-3.x-plugin ${project.version} + + org.skywalking + apm-resin-3.x-plugin + ${project.version} + + + org.skywalking + apm-resin-4.x-plugin + ${project.version} + org.skywalking apm-okhttp-3.x-plugin diff --git a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java index e8afb5d11..2fe77d5ba 100644 --- a/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java +++ b/apm-sniffer/apm-agent/src/main/java/org/skywalking/apm/agent/SkyWalkingAgent.java @@ -1,5 +1,6 @@ package org.skywalking.apm.agent; +import java.util.List; import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.NamedElement; import net.bytebuddy.description.type.TypeDescription; @@ -53,14 +54,22 @@ public class SkyWalkingAgent { new AgentBuilder.Default().type(enhanceClassMatcher(pluginFinder).and(not(isInterface()))).transform(new AgentBuilder.Transformer() { public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription, - ClassLoader classLoader) { - AbstractClassEnhancePluginDefine pluginDefine = pluginFinder.find(typeDescription.getTypeName()); - return pluginDefine.define(typeDescription.getTypeName(), builder); + ClassLoader classLoader) { + List pluginDefines = pluginFinder.find(typeDescription.getTypeName()); + for (AbstractClassEnhancePluginDefine pluginDefine : pluginDefines) { + DynamicType.Builder newBuilder = pluginDefine.define(typeDescription.getTypeName(), builder); + if (newBuilder != null) { + return newBuilder; + } + } + + logger.warn("Matched class {}, but enhancement fail.", typeDescription.getTypeName()); + return builder; } }).with(new AgentBuilder.Listener() { @Override public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, - DynamicType dynamicType) { + DynamicType dynamicType) { } diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def index c19910e0d..8d1917a6d 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.plugin.dubbo.DubboInstrumentation +dubbo=org.skywalking.apm.plugin.dubbo.DubboInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/http-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/http-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def index 4f89b3cb3..8ee8f54ce 100644 --- a/apm-sniffer/apm-sdk-plugin/http-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/http-plugin/okhttp-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.plugin.okhttp.v3.define.RealCallInstrumentation \ No newline at end of file +okhttp-3.x=org.skywalking.apm.plugin.okhttp.v3.define.RealCallInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def index 4452346e2..bea7bc146 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,4 +1,4 @@ -org.skywalking.apm.plugin.httpClient.v4.define.AbstractHttpClientInstrumentation -org.skywalking.apm.plugin.httpClient.v4.define.InternalHttpClientInstrumentation -org.skywalking.apm.plugin.httpClient.v4.define.MinimalHttpClientInstrumentation -org.skywalking.apm.plugin.httpClient.v4.define.DefaultRequestDirectorInstrumentation +httpclient-4.x=org.skywalking.apm.plugin.httpClient.v4.define.AbstractHttpClientInstrumentation +httpclient-4.x=org.skywalking.apm.plugin.httpClient.v4.define.InternalHttpClientInstrumentation +httpclient-4.x=org.skywalking.apm.plugin.httpClient.v4.define.MinimalHttpClientInstrumentation +httpclient-4.x=org.skywalking.apm.plugin.httpClient.v4.define.DefaultRequestDirectorInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def index ac9bd33b2..c946b2924 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def @@ -1,3 +1,3 @@ -org.skywalking.apm.plugin.jdbc.define.H2Instrumentation -org.skywalking.apm.plugin.jdbc.define.MysqlInstrumentation -org.skywalking.apm.plugin.jdbc.define.OracleInstrumentation +jdbc=org.skywalking.apm.plugin.jdbc.define.H2Instrumentation +jdbc=org.skywalking.apm.plugin.jdbc.define.MysqlInstrumentation +jdbc=org.skywalking.apm.plugin.jdbc.define.OracleInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def index 354b4fd02..d2b37ef8c 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1,2 @@ -org.skywalking.apm.plugin.jedis.v2.define.JedisClusterInstrumentation -org.skywalking.apm.plugin.jedis.v2.define.JedisInstrumentation +jedis-2.x=org.skywalking.apm.plugin.jedis.v2.define.JedisClusterInstrumentation +jedis-2.x=org.skywalking.apm.plugin.jedis.v2.define.JedisInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def index 27d8a38ad..cdb37e558 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.plugin.mongodb.v3.define.MongoDBInstrumentation \ No newline at end of file +mongodb-3.x=org.skywalking.apm.plugin.mongodb.v3.define.MongoDBInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def index 21d172385..b653df3bd 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1,2 @@ -org.skywalking.apm.plugin.motan.define.MotanConsumerInstrumentation -org.skywalking.apm.plugin.motan.define.MotanProviderInstrumentation +motan-0.x=org.skywalking.apm.plugin.motan.define.MotanConsumerInstrumentation +motan-0.x=org.skywalking.apm.plugin.motan.define.MotanProviderInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 3b4d1f610..2795f85f0 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -19,6 +19,8 @@ motan-plugin mongodb-3.x-plugin http-plugin + resin-3.x-plugin + resin-4.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/pom.xml new file mode 100644 index 000000000..2ae8dc3db --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + + apm-sdk-plugin + org.skywalking + 3.1-2017 + + + apm-resin-3.x-plugin + jar + + resin-3.x-plugin + http://maven.apache.org + + + UTF-8 + + + + + com.caucho + resin + 3.0.9 + provided + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + attach-sources + + jar + + + + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/ResinV3Interceptor.java b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/ResinV3Interceptor.java new file mode 100644 index 000000000..e5246864b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/ResinV3Interceptor.java @@ -0,0 +1,90 @@ +package org.skywalking.apm.plugin.resin.v3; + +import com.caucho.server.connection.CauchoRequest; +import com.caucho.server.http.HttpRequest; +import com.caucho.server.http.HttpResponse; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.trace.Span; +import org.skywalking.apm.trace.tag.Tags; +import org.skywalking.apm.util.StringUtil; + +/** + * {@link ResinV3Interceptor} intercept method of{@link com.caucho.server.dispatch.ServletInvocation#service(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse)} record the resin host, port ,url. + * + * @author baiyang + */ +public class ResinV3Interceptor implements InstanceMethodsAroundInterceptor { + /** + * Header name that the serialized context data stored in + * {@link HttpRequest#getHeader(String)}. + */ + public static final String HEADER_NAME_OF_CONTEXT_DATA = "SWTraceContext"; + /** + * Resin component. + */ + public static final String RESIN_COMPONENT = "Resin"; + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + Object[] args = interceptorContext.allArguments(); + CauchoRequest request = (CauchoRequest)args[0]; + Span span = ContextManager.createSpan(request.getPageURI()); + Tags.COMPONENT.set(span, RESIN_COMPONENT); + Tags.PEER_HOST.set(span, request.getServerName()); + Tags.PEER_PORT.set(span, request.getServerPort()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER); + Tags.URL.set(span, appendRequestURL(request)); + Tags.SPAN_LAYER.asHttp(span); + + String tracingHeaderValue = request.getHeader(HEADER_NAME_OF_CONTEXT_DATA); + if (!StringUtil.isEmpty(tracingHeaderValue)) { + ContextManager.extract(new ContextCarrier().deserialize(tracingHeaderValue)); + } + } + + /** + * Append request URL. + * + * @param request + * @return + */ + private String appendRequestURL(CauchoRequest request) { + StringBuffer sb = new StringBuffer(); + sb.append(request.getScheme()); + sb.append("://"); + sb.append(request.getServerName()); + sb.append(":"); + sb.append(request.getServerPort()); + sb.append(request.getPageURI()); + return sb.toString(); + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + HttpResponse response = (HttpResponse)interceptorContext.allArguments()[1]; + Span span = ContextManager.activeSpan(); + Tags.STATUS_CODE.set(span, response.getStatusCode()); + + if (response.getStatusCode() != 200) { + Tags.ERROR.set(span, true); + } + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + Span span = ContextManager.activeSpan(); + span.log(t); + Tags.ERROR.set(span, true); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/define/ResinV3Instrumentation.java b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/define/ResinV3Instrumentation.java new file mode 100644 index 000000000..7b1369ef1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v3/define/ResinV3Instrumentation.java @@ -0,0 +1,55 @@ +package org.skywalking.apm.plugin.resin.v3.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.plugin.resin.v3.ResinV3Interceptor; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link ResinV3Instrumentation} presents that skywalking intercepts {@link com.caucho.server.dispatch.ServletInvocation#service(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse)} by using {@link ResinV3Interceptor}. + * + * @author baiyang + */ +public class ResinV3Instrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.caucho.server.dispatch.ServletInvocation"; + + private static final String METHOD_INTERCET_CLASS = "org.skywalking.apm.plugin.resin.v3.ResinV3Interceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("service"); + } + + @Override + public String getMethodsInterceptor() { + return METHOD_INTERCET_CLASS; + } + } + }; + } + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected String[] witnessClasses() { + return new String[] {"com.caucho.server.connection.AbstractHttpResponse"}; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..86586edb8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1 @@ +resin-3.x=org.skywalking.apm.plugin.resin.v3.define.ResinV3Instrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v3/ResinV3InterceptorTest.java b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v3/ResinV3InterceptorTest.java new file mode 100644 index 000000000..74eac3668 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-3.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v3/ResinV3InterceptorTest.java @@ -0,0 +1,150 @@ +package org.skywalking.apm.plugin.resin.v3; + +import com.caucho.server.connection.CauchoRequest; +import com.caucho.server.http.HttpResponse; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.boot.ServiceManager; +import org.skywalking.apm.agent.core.context.TracerContext; +import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.sniffer.mock.context.MockTracerContextListener; +import org.skywalking.apm.sniffer.mock.context.SegmentAssert; +import org.skywalking.apm.trace.LogData; +import org.skywalking.apm.trace.Span; +import org.skywalking.apm.trace.TraceSegment; +import org.skywalking.apm.trace.TraceSegmentRef; +import org.skywalking.apm.trace.tag.Tags; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +/** + * ResinInterceptorTest + * + * @author baiyang + */ +@RunWith(MockitoJUnitRunner.class) +public class ResinV3InterceptorTest { + private ResinV3Interceptor interceptor; + private MockTracerContextListener contextListener; + + @Mock + private CauchoRequest request; + @Mock + private HttpResponse response; + @Mock + private EnhancedClassInstanceContext classInstanceContext; + @Mock + private InstanceMethodInvokeContext methodInvokeContext; + @Mock + private MethodInterceptResult methodInterceptResult; + + @Before + public void setUp() throws Exception { + + ServiceManager.INSTANCE.boot(); + + interceptor = new ResinV3Interceptor(); + contextListener = new MockTracerContextListener(); + + TracerContext.ListenerManager.add(contextListener); + + when(request.getPageURI()).thenReturn("/test/testRequestURL"); + when(request.getScheme()).thenReturn("http"); + when(request.getServerName()).thenReturn("localhost"); + when(request.getServerPort()).thenReturn(8080); + when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL")); + when(response.getStatusCode()).thenReturn(200); + when(methodInvokeContext.allArguments()).thenReturn(new Object[] {request, response}); + } + + @Test + public void testWithoutSerializedContextData() { + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + } + }); + } + + @Test + public void testWithSerializedContextData() { + when(request.getHeader(ResinV3Interceptor.HEADER_NAME_OF_CONTEXT_DATA)).thenReturn("302017.1487666919810.624424584.17332.1.1|1|REMOTE_APP|127.0.0.1|Trace.globalId.123|1"); + + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertTraceSegmentRef(traceSegment.getRefs().get(0)); + } + }); + } + + @Test + public void testWithOccurException() { + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.handleMethodException(new RuntimeException(), classInstanceContext, methodInvokeContext); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertThat(span.getLogs().size(), is(1)); + assertSpanLog(span.getLogs().get(0)); + } + }); + } + + private void assertSpanLog(LogData logData) { + assertThat(logData.getFields().size(), is(4)); + assertThat(logData.getFields().get("event"), CoreMatchers.is("error")); + assertThat(logData.getFields().get("error.kind"), CoreMatchers.is(RuntimeException.class.getName())); + assertNull(logData.getFields().get("message")); + } + + private void assertTraceSegmentRef(TraceSegmentRef ref) { + assertThat(ref.getSpanId(), is(1)); + assertThat(ref.getTraceSegmentId(), is("302017.1487666919810.624424584.17332.1.1")); + } + + private void assertHttpSpan(Span span) { + assertThat(span.getOperationName(), is("/test/testRequestURL")); + assertThat(Tags.COMPONENT.get(span), is("Resin")); + assertThat(Tags.URL.get(span), is("http://localhost:8080/test/testRequestURL")); + assertThat(Tags.STATUS_CODE.get(span), is(200)); + assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_SERVER)); + assertTrue(Tags.SPAN_LAYER.isHttp(span)); + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(new MockTracerContextListener()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/pom.xml new file mode 100644 index 000000000..0e137b7fa --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + + apm-sdk-plugin + org.skywalking + 3.1-2017 + + + apm-resin-4.x-plugin + jar + + resin-4.x-plugin + http://maven.apache.org + + + UTF-8 + + + + + com.caucho + resin + 4.0.41 + provided + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + + attach-sources + + jar + + + + + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/ResinV4Interceptor.java b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/ResinV4Interceptor.java new file mode 100644 index 000000000..de04a3837 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/ResinV4Interceptor.java @@ -0,0 +1,87 @@ +package org.skywalking.apm.plugin.resin.v4; + +import com.caucho.server.http.CauchoRequest; +import com.caucho.server.http.HttpRequest; +import javax.servlet.http.HttpServletResponse; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.trace.Span; +import org.skywalking.apm.trace.tag.Tags; +import org.skywalking.apm.util.StringUtil; + +/** + * Created by Baiyang on 2017/5/2. + */ +public class ResinV4Interceptor implements InstanceMethodsAroundInterceptor { + /** + * Header name that the serialized context data stored in + * {@link HttpRequest#getHeader(String)}. + */ + public static final String HEADER_NAME_OF_CONTEXT_DATA = "SWTraceContext"; + /** + * Resin component. + */ + public static final String RESIN_COMPONENT = "Resin"; + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + Object[] args = interceptorContext.allArguments(); + CauchoRequest request = (CauchoRequest)args[0]; + Span span = ContextManager.createSpan(request.getPageURI()); + Tags.COMPONENT.set(span, RESIN_COMPONENT); + Tags.PEER_HOST.set(span, request.getServerName()); + Tags.PEER_PORT.set(span, request.getServerPort()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER); + Tags.URL.set(span, appendRequestURL(request)); + Tags.SPAN_LAYER.asHttp(span); + + String tracingHeaderValue = request.getHeader(HEADER_NAME_OF_CONTEXT_DATA); + if (!StringUtil.isEmpty(tracingHeaderValue)) { + ContextManager.extract(new ContextCarrier().deserialize(tracingHeaderValue)); + } + } + + /** + * Append request URL. + * + * @param request + * @return + */ + private String appendRequestURL(CauchoRequest request) { + StringBuffer sb = new StringBuffer(); + sb.append(request.getScheme()); + sb.append("://"); + sb.append(request.getServerName()); + sb.append(":"); + sb.append(request.getServerPort()); + sb.append(request.getPageURI()); + return sb.toString(); + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + HttpServletResponse response = (HttpServletResponse)interceptorContext.allArguments()[1]; + Span span = ContextManager.activeSpan(); + Tags.STATUS_CODE.set(span, response.getStatus()); + + if (response.getStatus() != 200) { + Tags.ERROR.set(span, true); + } + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + Span span = ContextManager.activeSpan(); + span.log(t); + Tags.ERROR.set(span, true); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/define/ResinV4Instrumentation.java b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/define/ResinV4Instrumentation.java new file mode 100644 index 000000000..8f130247e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/java/org/skywalking/apm/plugin/resin/v4/define/ResinV4Instrumentation.java @@ -0,0 +1,54 @@ +package org.skywalking.apm.plugin.resin.v4.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.plugin.resin.v4.ResinV4Interceptor; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link ResinV4Instrumentation} presents that skywalking intercepts {@link com.caucho.server.dispatch.ServletInvocation#service(javax.servlet.ServletRequest, + * javax.servlet.ServletResponse)} by using {@link ResinV4Interceptor}. + * + * @author baiyang + */ +public class ResinV4Instrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.caucho.server.dispatch.ServletInvocation"; + + private static final String METHOD_INTERCET_CLASS = "org.skywalking.apm.plugin.resin.v4.ResinV4Interceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("service"); + } + + @Override + public String getMethodsInterceptor() { + return METHOD_INTERCET_CLASS; + } + } + }; + } + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected String[] witnessClasses() { + return new String[] {"com.caucho.server.http.HttpServletResponseImpl"}; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..3bab53d03 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1 @@ +resin-4.x=org.skywalking.apm.plugin.resin.v4.define.ResinV4Instrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v4/ResinV4InterceptorTest.java b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v4/ResinV4InterceptorTest.java new file mode 100644 index 000000000..c1dd0c026 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/resin-4.x-plugin/src/test/java/org/skywalking/apm/plugin/resin/v4/ResinV4InterceptorTest.java @@ -0,0 +1,149 @@ +package org.skywalking.apm.plugin.resin.v4; + +import com.caucho.server.http.CauchoRequest; +import javax.servlet.http.HttpServletResponse; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.boot.ServiceManager; +import org.skywalking.apm.agent.core.context.TracerContext; +import org.skywalking.apm.agent.core.plugin.interceptor.EnhancedClassInstanceContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.sniffer.mock.context.MockTracerContextListener; +import org.skywalking.apm.sniffer.mock.context.SegmentAssert; +import org.skywalking.apm.trace.LogData; +import org.skywalking.apm.trace.Span; +import org.skywalking.apm.trace.TraceSegment; +import org.skywalking.apm.trace.TraceSegmentRef; +import org.skywalking.apm.trace.tag.Tags; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +/** + * Created by Baiyang on 2017/5/6. + */ +@RunWith(MockitoJUnitRunner.class) +public class ResinV4InterceptorTest { + private ResinV4Interceptor interceptor; + private MockTracerContextListener contextListener; + + @Mock + private CauchoRequest request; + @Mock + private HttpServletResponse response; + @Mock + private EnhancedClassInstanceContext classInstanceContext; + @Mock + private InstanceMethodInvokeContext methodInvokeContext; + @Mock + private MethodInterceptResult methodInterceptResult; + + @Before + public void setUp() throws Exception { + + ServiceManager.INSTANCE.boot(); + + interceptor = new ResinV4Interceptor(); + contextListener = new MockTracerContextListener(); + + TracerContext.ListenerManager.add(contextListener); + + when(request.getPageURI()).thenReturn("/test/testRequestURL"); + when(request.getScheme()).thenReturn("http"); + when(request.getServerName()).thenReturn("localhost"); + when(request.getServerPort()).thenReturn(8080); + when(request.getRequestURI()).thenReturn("/test/testRequestURL"); + when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL")); + when(response.getStatus()).thenReturn(200); + when(methodInvokeContext.allArguments()).thenReturn(new Object[] {request, response}); + } + + @Test + public void testWithoutSerializedContextData() { + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + } + }); + } + + @Test + public void testWithSerializedContextData() { + when(request.getHeader(ResinV4Interceptor.HEADER_NAME_OF_CONTEXT_DATA)).thenReturn("302017.1487666919810.624424584.17332.1.1|1|REMOTE_APP|127.0.0.1|Trace.globalId.123|1"); + + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertTraceSegmentRef(traceSegment.getRefs().get(0)); + } + }); + } + + @Test + public void testWithOccurException() { + interceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + interceptor.handleMethodException(new RuntimeException(), classInstanceContext, methodInvokeContext); + interceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertThat(span.getLogs().size(), is(1)); + assertSpanLog(span.getLogs().get(0)); + } + }); + } + + private void assertSpanLog(LogData logData) { + assertThat(logData.getFields().size(), is(4)); + assertThat(logData.getFields().get("event"), CoreMatchers.is("error")); + assertThat(logData.getFields().get("error.kind"), CoreMatchers.is(RuntimeException.class.getName())); + assertNull(logData.getFields().get("message")); + } + + private void assertTraceSegmentRef(TraceSegmentRef ref) { + assertThat(ref.getSpanId(), is(1)); + assertThat(ref.getTraceSegmentId(), is("302017.1487666919810.624424584.17332.1.1")); + } + + private void assertHttpSpan(Span span) { + assertThat(span.getOperationName(), is("/test/testRequestURL")); + assertThat(Tags.COMPONENT.get(span), is("Resin")); + assertThat(Tags.URL.get(span), is("http://localhost:8080/test/testRequestURL")); + assertThat(Tags.STATUS_CODE.get(span), is(200)); + assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_SERVER)); + assertTrue(Tags.SPAN_LAYER.isHttp(span)); + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(new MockTracerContextListener()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def index b22c5d050..fb17b3092 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.plugin.tomcat78x.define.TomcatInstrumentation +tomcat-7.x/8.x=org.skywalking.apm.plugin.tomcat78x.define.TomcatInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/src/main/resources/skywalking-plugin.def index 9672c714e..f6a48831a 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.toolkit.activation.log.log4j.v1.x.TraceIdPatternConverterActivation +log4j=org.skywalking.apm.toolkit.activation.log.log4j.v1.x.TraceIdPatternConverterActivation \ No newline at end of file diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/src/main/resources/skywalking-plugin.def index 75f99a788..c68759c26 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.toolkit.activation.log.log4j.v2.x.Log4j2OutputAppenderActivation +log4j2=org.skywalking.apm.toolkit.activation.log.log4j.v2.x.Log4j2OutputAppenderActivation \ No newline at end of file diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/src/main/resources/skywalking-plugin.def index 53a49b181..2f1f02528 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.toolkit.activation.log.logback.v1.x.LogbackPatternConverterActivation +logback=org.skywalking.apm.toolkit.activation.log.logback.v1.x.LogbackPatternConverterActivation \ No newline at end of file diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/resources/skywalking-plugin.def index 65afa78cd..96fa9e537 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/resources/skywalking-plugin.def @@ -1,2 +1,2 @@ -org.skywalking.apm.toolkit.activation.opentracing.span.SkyWalkingSpanActivation -org.skywalking.apm.toolkit.activation.opentracing.tracer.SkyWalkingTracerActivation +opentracing=org.skywalking.apm.toolkit.activation.opentracing.span.SkyWalkingSpanActivation +opentracing=org.skywalking.apm.toolkit.activation.opentracing.tracer.SkyWalkingTracerActivation \ No newline at end of file diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-context-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-context-activation/src/main/resources/skywalking-plugin.def index 2f3b1a6d7..0284210fd 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-context-activation/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-context-activation/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -org.skywalking.apm.toolkit.activation.trace.TraceContextActivation \ No newline at end of file +tracecontext=org.skywalking.apm.toolkit.activation.trace.TraceContextActivation \ No newline at end of file diff --git a/ci-dependencies/resin-4.0.41.jar b/ci-dependencies/resin-4.0.41.jar new file mode 100644 index 000000000..9e04f4ce7 Binary files /dev/null and b/ci-dependencies/resin-4.0.41.jar differ