From 5f880f9576374bf13a96668c8b522cfb9213ea48 Mon Sep 17 00:00:00 2001 From: ascrutae Date: Wed, 27 Sep 2017 14:47:31 +0800 Subject: [PATCH] support jetty plugins --- .../trace/component/ComponentsDefine.java | 8 +- apm-sniffer/apm-agent/pom.xml | 10 ++ .../jetty-client-9.x-plugin/pom.xml | 24 ++++ .../AsyncHttpRequestSendInterceptor.java | 52 +++++++ .../client/CompleteListenerInterceptor.java | 52 +++++++ .../SyncHttpRequestSendInterceptor.java | 49 +++++++ .../CompleteListenerInstrumentation.java | 53 +++++++ .../define/HttpRequestInstrumentation.java | 70 ++++++++++ .../src/main/resources/skywalking-plugin.def | 2 + .../AsyncHttpRequestSendInterceptorTest.java | 122 ++++++++++++++++ .../CompleteListenerInterceptorTest.java | 130 +++++++++++++++++ .../SyncHttpRequestSendInterceptorTest.java | 122 ++++++++++++++++ .../jetty-server-9.x-plugin/pom.xml | 24 ++++ .../jetty/v9/server/HandleInterceptor.java | 56 ++++++++ .../define/HandlerListInstrumentation.java | 50 +++++++ .../src/main/resources/skywalking-plugin.def | 1 + .../v9/server/HandleInterceptorTest.java | 132 ++++++++++++++++++ .../apm-sdk-plugin/jetty-plugin/pom.xml | 21 +++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + 19 files changed, 978 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/define/HandlerListInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml diff --git a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java index 5c9b7c0ef..b37078faa 100644 --- a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -41,6 +41,10 @@ public class ComponentsDefine { public static final OfficialComponent NUTZ_HTTP = new OfficialComponent(17, "NutzHttp"); + public static final OfficialComponent JETTY_CLIENT = new OfficialComponent(18, "JettyClient"); + + public static final OfficialComponent JETTY_SERVER = new OfficialComponent(19, "JettyServer"); + private static ComponentsDefine instance = new ComponentsDefine(); private String[] components; @@ -50,7 +54,7 @@ public class ComponentsDefine { } public ComponentsDefine() { - components = new String[18]; + components = new String[20]; addComponent(TOMCAT); addComponent(HTTPCLIENT); addComponent(DUBBO); @@ -68,6 +72,8 @@ public class ComponentsDefine { addComponent(STRUTS2); addComponent(NUTZ_MVC_ANNOTATION); addComponent(NUTZ_HTTP); + addComponent(JETTY_CLIENT); + addComponent(JETTY_SERVER); } private void addComponent(OfficialComponent component) { diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 0aa99ea71..5dd56a766 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -115,6 +115,16 @@ apm-nutz-http-1.x-plugin ${project.version} + + org.skywalking + apm-jetty-client-9.x-plugin + ${project.version} + + + org.skywalking + apm-jetty-server-9.x-plugin + ${project.version} + diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml new file mode 100644 index 000000000..1db7c1117 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -0,0 +1,24 @@ + + + jetty-plugins + org.skywalking + 3.2.1-2017 + + 4.0.0 + + apm-jetty-client-9.x-plugin + jar + + jetty-client-9.x-plugin + http://maven.apache.org + + + + org.eclipse.jetty + jetty-client + 9.0.0.v20130308 + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java new file mode 100644 index 000000000..5993f82e7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java @@ -0,0 +1,52 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.lang.reflect.Method; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.http.HttpFields; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +public class AsyncHttpRequestSendInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + HttpRequest request = (HttpRequest)objInst; + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan(request.getURI().getPath(), contextCarrier, request.getHost() + ":" + request.getPort()); + span.setComponent(ComponentsDefine.JETTY_CLIENT); + Tags.HTTP.METHOD.set(span, request.getMethod().asString()); + Tags.URL.set(span, request.getURI().toString()); + SpanLayer.asHttp(span); + + CarrierItem next = contextCarrier.items(); + HttpFields field = request.getHeaders(); + while (next.hasNext()) { + next = next.next(); + field.add(next.getHeadKey(), next.getHeadValue()); + } + + EnhancedInstance callBackResult = (EnhancedInstance)allArguments[0]; + callBackResult.setSkyWalkingDynamicField(ContextManager.capture()); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java new file mode 100644 index 000000000..96fb0339b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptor.java @@ -0,0 +1,52 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.lang.reflect.Method; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.http.HttpFields; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.ContextSnapshot; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +public class CompleteListenerInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + ContextSnapshot contextSnapshot = (ContextSnapshot)objInst.getSkyWalkingDynamicField(); + if (contextSnapshot != null) { + Result callBackResult = (Result)allArguments[0]; + + AbstractSpan abstractSpan = ContextManager.createLocalSpan("CallBack/" + callBackResult.getRequest().getURI().getPath()); + ContextManager.continued(contextSnapshot); + + if (callBackResult.isFailed()) { + abstractSpan.errorOccurred().log(callBackResult.getFailure()); + Tags.STATUS_CODE.set(abstractSpan, Integer.toString(callBackResult.getResponse().getStatus())); + } + abstractSpan.setComponent(ComponentsDefine.JETTY_CLIENT); + abstractSpan.setLayer(SpanLayer.HTTP); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextSnapshot contextSnapshot = (ContextSnapshot)objInst.getSkyWalkingDynamicField(); + if (contextSnapshot != null) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java new file mode 100644 index 000000000..7115ee5fc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptor.java @@ -0,0 +1,49 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.lang.reflect.Method; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.http.HttpFields; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +public class SyncHttpRequestSendInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + HttpRequest request = (HttpRequest)objInst; + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan(request.getURI().getPath(), contextCarrier, request.getHost() + ":" + request.getPort()); + span.setComponent(ComponentsDefine.JETTY_CLIENT); + Tags.HTTP.METHOD.set(span, "GET"); + Tags.URL.set(span, request.getURI().toString()); + SpanLayer.asHttp(span); + + CarrierItem next = contextCarrier.items(); + HttpFields field = request.getHeaders(); + while (next.hasNext()) { + next = next.next(); + field.add(next.getHeadKey(), next.getHeadValue()); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java new file mode 100644 index 000000000..c4d01680c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/CompleteListenerInstrumentation.java @@ -0,0 +1,53 @@ +package org.skywalking.apm.plugin.jetty.v9.client.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.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; + +/** + * {@link CompleteListenerInstrumentation} enhance the onComplete method in all class of hierarchy + * org.eclipse.jetty.client.api.Response$CompleteListener by org.skywalking.apm.plugin.jetty.client.CompleteListenerInterceptor + * + * @author zhangxin + */ +public class CompleteListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.api.Response$CompleteListener"; + private static final String ENHANCE_METHOD = "onComplete"; + public static final String SEND_INTERCEPTOR = "org.skywalking.apm.plugin.jetty.client.CompleteListenerInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return SEND_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byHierarchyMatch(new String[] {ENHANCE_CLASS}); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java new file mode 100644 index 000000000..063414ca8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/client/define/HttpRequestInstrumentation.java @@ -0,0 +1,70 @@ +package org.skywalking.apm.plugin.jetty.v9.client.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.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link HttpRequestInstrumentation} enhance the send method without argument in + * org.eclipse.jetty.client.HttpRequest by org.skywalking.apm.plugin.jetty.client.SyncHttpRequestSendInterceptor + * and enhance the send with org.eclipse.jetty.client.api.Response$CompleteListener parameter + * by org.skywalking.apm.plugin.jetty.client.AsyncHttpRequestSendInterceptor + * + * @author zhangxin + */ +public class HttpRequestInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.HttpRequest"; + private static final String ENHANCE_CLASS_NAME = "send"; + public static final String ASYNC_SEND_INTERCEPTOR = "org.skywalking.apm.plugin.jetty.client.AsyncHttpRequestSendInterceptor"; + public static final String SYNC_SEND_INTERCEPTOR = "org.skywalking.apm.plugin.jetty.client.SyncHttpRequestSendInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + //sync call interceptor point + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_CLASS_NAME).and(takesArguments(0)); + } + + @Override public String getMethodsInterceptor() { + return SYNC_SEND_INTERCEPTOR; + } + + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + //async call interceptor point + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_CLASS_NAME).and(takesArgumentWithType(0, "org.eclipse.jetty.client.api.Response$CompleteListener")); + } + + @Override public String getMethodsInterceptor() { + return ASYNC_SEND_INTERCEPTOR; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..72bfb22ae --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,2 @@ +jetty-client-9.x=org.skywalking.apm.plugin.jetty.v9.client.define.CompleteListenerInstrumentation +jetty-client-9.x=org.skywalking.apm.plugin.jetty.v9.client.define.HttpRequestInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java new file mode 100644 index 000000000..aa94dcd41 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java @@ -0,0 +1,122 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.net.URI; +import java.util.List; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.http.HttpMethod; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.util.KeyValuePair; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertException; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class AsyncHttpRequestSendInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Mock + private HttpClient httpClient; + @Mock + private EnhancedInstance callBackEnhanceInstance; + + private Object[] allArguments; + private Class[] argumentTypes; + private MockHttpRequest enhancedInstance; + private AsyncHttpRequestSendInterceptor interceptor; + private URI uri = URI.create("http://localhost:8080/test"); + + @Before + public void setUp() throws Exception { + enhancedInstance = new MockHttpRequest(httpClient, uri); + allArguments = new Object[] {"OperationKey", "OperationValue"}; + argumentTypes = new Class[] {String.class, String.class}; + + interceptor = new AsyncHttpRequestSendInterceptor(); + allArguments = new Object[] {callBackEnhanceInstance}; + } + + @Test + public void testMethodsAround() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(2)); + assertThat(tags.get(0).getValue(), is("POST")); + assertThat(tags.get(1).getValue(), is(uri.toString())); + + Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); + } + + @Test + public void testMethodsAroundError() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); + interceptor.handleMethodException(enhancedInstance, null, allArguments, argumentTypes, new RuntimeException()); + interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(2)); + assertThat(tags.get(0).getValue(), is("POST")); + assertThat(tags.get(1).getValue(), is(uri.toString())); + + Assert.assertEquals(true, SpanHelper.getErrorOccurred(finishedSpan)); + assertException(SpanHelper.getLogs(finishedSpan).get(0), RuntimeException.class); + + } + + private class MockHttpRequest extends HttpRequest implements EnhancedInstance { + public MockHttpRequest(HttpClient httpClient, URI uri) { + super(httpClient, uri); + } + + @Override public Object getSkyWalkingDynamicField() { + return null; + } + + @Override public void setSkyWalkingDynamicField(Object value) { + + } + + @Override public HttpMethod getMethod() { + return HttpMethod.POST; + } + + @Override public URI getURI() { + return uri; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java new file mode 100644 index 000000000..0b5c2c5f9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/CompleteListenerInterceptorTest.java @@ -0,0 +1,130 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.net.URI; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.http.HttpFields; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.ContextSnapshot; +import org.skywalking.apm.agent.core.context.SW3CarrierItem; +import org.skywalking.apm.agent.core.context.ids.DistributedTraceId; +import org.skywalking.apm.agent.core.context.ids.ID; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentRefHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class CompleteListenerInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Mock + private Result result; + @Mock + private HttpRequest httpRequest; + @Mock + private HttpResponse httpResponse; + private Object[] allArguments; + private Class[] argumentTypes; + private CompleteListenerInterceptor interceptor; + + @Mock + private ContextSnapshot contextSnapshot; + + private EnhancedInstance objectInstanceWithoutSnapshot = new EnhancedInstance() { + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + }; + + private EnhancedInstance objectInstanceWithSnapshot = new EnhancedInstance() { + @Override + public Object getSkyWalkingDynamicField() { + return contextSnapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + }; + + @Before + public void setUp() { + interceptor = new CompleteListenerInterceptor(); + when(result.getResponse()).thenReturn(httpResponse); + when(httpRequest.getURI()).thenReturn(URI.create("http://localhost:8080/test")); + when(result.getRequest()).thenReturn(httpRequest); + allArguments = new Object[] {result}; + argumentTypes = new Class[] {result.getClass()}; + when(contextSnapshot.isValid()).thenReturn(true); + when(contextSnapshot.getEntryApplicationInstanceId()).thenReturn(1); + when(contextSnapshot.getSpanId()).thenReturn(2); + when(contextSnapshot.getTraceSegmentId()).thenReturn(mock(ID.class)); + when(contextSnapshot.getDistributedTraceId()).thenReturn(mock(DistributedTraceId.class)); + when(contextSnapshot.getEntryOperationName()).thenReturn("1"); + when(contextSnapshot.getParentOperationName()).thenReturn("2"); + } + + @Test + public void testMethodAroundWithoutSnapshot() throws Throwable { + interceptor.beforeMethod(objectInstanceWithoutSnapshot, null, allArguments, argumentTypes, null); + interceptor.afterMethod(objectInstanceWithoutSnapshot, null, allArguments, argumentTypes, null); + assertThat(segmentStorage.getTraceSegments().size(), is(0)); + } + + @Test + public void testMethodAroundWithSnapshot() throws Throwable { + HttpFields fields = new HttpFields(); + when(httpResponse.getHeaders()).thenReturn(fields); + interceptor.beforeMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); + interceptor.afterMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(traceSegment.getRefs().size(), is(1)); + } + + @Test + public void testMethodAroundWithSnapshotAndHeader() throws Throwable { + HttpFields fields = new HttpFields(); + fields.put(SW3CarrierItem.HEADER_NAME, "1.234.111|3|1|1|#192.168.1.8:18002|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*"); + when(httpResponse.getHeaders()).thenReturn(fields); + interceptor.beforeMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); + interceptor.afterMethod(objectInstanceWithSnapshot, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + assertThat(traceSegment.getRefs().size(), is(1)); + TraceSegmentRef ref = traceSegment.getRefs().get(0); + assertThat(SegmentRefHelper.getEntryApplicationInstanceId(ref), is(1)); + assertThat(SegmentRefHelper.getSpanId(ref), is(3)); + assertThat(SegmentRefHelper.getTraceSegmentId(ref).toString(), is("1.234.111")); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java new file mode 100644 index 000000000..c175b0553 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java @@ -0,0 +1,122 @@ +package org.skywalking.apm.plugin.jetty.v9.client; + +import java.net.URI; +import java.util.List; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.http.HttpMethod; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.util.KeyValuePair; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertException; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class SyncHttpRequestSendInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Mock + private HttpClient httpClient; + @Mock + private EnhancedInstance callBackEnhanceInstance; + + private Object[] allArguments; + private Class[] argumentTypes; + private MockHttpRequest enhancedInstance; + private AsyncHttpRequestSendInterceptor interceptor; + private URI uri = URI.create("http://localhost:8080/test"); + + @Before + public void setUp() throws Exception { + enhancedInstance = new MockHttpRequest(httpClient, uri); + allArguments = new Object[] {"OperationKey", "OperationValue"}; + argumentTypes = new Class[] {String.class, String.class}; + + interceptor = new AsyncHttpRequestSendInterceptor(); + allArguments = new Object[] {callBackEnhanceInstance}; + } + + @Test + public void testMethodsAround() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(2)); + assertThat(tags.get(0).getValue(), is("GET")); + assertThat(tags.get(1).getValue(), is(uri.toString())); + + Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); + } + + @Test + public void testMethodsAroundError() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, null); + interceptor.handleMethodException(enhancedInstance, null, allArguments, argumentTypes, new RuntimeException()); + interceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(2)); + assertThat(tags.get(0).getValue(), is("GET")); + assertThat(tags.get(1).getValue(), is(uri.toString())); + + Assert.assertEquals(true, SpanHelper.getErrorOccurred(finishedSpan)); + assertException(SpanHelper.getLogs(finishedSpan).get(0), RuntimeException.class); + + } + + private class MockHttpRequest extends HttpRequest implements EnhancedInstance { + public MockHttpRequest(HttpClient httpClient, URI uri) { + super(httpClient, uri); + } + + @Override public Object getSkyWalkingDynamicField() { + return null; + } + + @Override public void setSkyWalkingDynamicField(Object value) { + + } + + @Override public HttpMethod getMethod() { + return HttpMethod.GET; + } + + @Override public URI getURI() { + return uri; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml new file mode 100644 index 000000000..31aac8ce3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -0,0 +1,24 @@ + + + jetty-plugins + org.skywalking + 3.2.1-2017 + + 4.0.0 + + apm-jetty-server-9.x-plugin + jar + + jetty-server-9.x-plugin + http://maven.apache.org + + + + org.eclipse.jetty + jetty-server + 9.0.0.v20130308 + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java new file mode 100644 index 000000000..c5e941519 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java @@ -0,0 +1,56 @@ +package org.skywalking.apm.plugin.jetty.v9.server; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.skywalking.apm.agent.core.context.CarrierItem; +import org.skywalking.apm.agent.core.context.ContextCarrier; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +public class HandleInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + String requestURI = (String)allArguments[0]; + HttpServletRequest servletRequest = (HttpServletRequest)allArguments[2]; + + ContextCarrier contextCarrier = new ContextCarrier(); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(servletRequest.getHeader(next.getHeadKey())); + } + + AbstractSpan span = ContextManager.createEntrySpan(requestURI, contextCarrier); + Tags.URL.set(span, servletRequest.getRequestURL().toString()); + Tags.HTTP.METHOD.set(span, servletRequest.getMethod()); + span.setComponent(ComponentsDefine.JETTY_SERVER); + SpanLayer.asHttp(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + HttpServletResponse servletResponse = (HttpServletResponse)allArguments[3]; + AbstractSpan span = ContextManager.activeSpan(); + if (servletResponse.getStatus() >= 400) { + span.errorOccurred(); + Tags.STATUS_CODE.set(span, Integer.toString(servletResponse.getStatus())); + } + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/define/HandlerListInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/define/HandlerListInstrumentation.java new file mode 100644 index 000000000..55a2e3eb1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/skywalking/apm/plugin/jetty/v9/server/define/HandlerListInstrumentation.java @@ -0,0 +1,50 @@ +package org.skywalking.apm.plugin.jetty.v9.server.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.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link HandlerListInstrumentation} enhance the handle method in org.eclipse.jetty.server.handler.HandlerList + * by org.skywalking.apm.plugin.jetty.v9.server.HandleInterceptor + * + * @author zhangxin + */ +public class HandlerListInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.handler.HandlerList"; + private static final String ENHANCE_METHOD = "handle"; + private static final String INTERCEPTOR_CLASS = "org.skywalking.apm.plugin.jetty.v9.server.HandleInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..0c7fcd02d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1 @@ +jetty-server-9.x=org.skywalking.apm.plugin.jetty.v9.server.define.HandlerListInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java new file mode 100644 index 000000000..44c15069e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java @@ -0,0 +1,132 @@ +package org.skywalking.apm.plugin.jetty.v9.server; + +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.server.Request; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.SW3CarrierItem; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.LogDataEntity; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.trace.TraceSegmentRef; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SegmentRefHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertComponent; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertException; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertLayer; +import static org.skywalking.apm.agent.test.tools.SpanAssert.assertTag; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class HandleInterceptorTest { + + private HandleInterceptor tomcatInvokeInterceptor; + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Mock + private HttpServletRequest request; + + @Mock + private Request baseRequest; + @Mock + private HttpServletResponse response; + @Mock + private MethodInterceptResult methodInterceptResult; + + @Mock + private EnhancedInstance enhancedInstance; + + private Object[] arguments; + private Class[] argumentType; + + @Before + public void setUp() throws Exception { + tomcatInvokeInterceptor = new HandleInterceptor(); + when(request.getRequestURI()).thenReturn("/test/testRequestURL"); + when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL")); + when(response.getStatus()).thenReturn(200); + arguments = new Object[] {"/test/testRequestURL", baseRequest, request, response}; + argumentType = new Class[] {String.class, baseRequest.getClass(), request.getClass(), response.getClass()}; + + } + + @Test + public void testWithoutSerializedContextData() throws Throwable { + tomcatInvokeInterceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult); + tomcatInvokeInterceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertHttpSpan(spans.get(0)); + } + + @Test + public void testWithSerializedContextData() throws Throwable { + when(request.getHeader(SW3CarrierItem.HEADER_NAME)).thenReturn("1.234.111|3|1|1|#192.168.1.8:18002|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*"); + + tomcatInvokeInterceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult); + tomcatInvokeInterceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + + assertHttpSpan(spans.get(0)); + assertTraceSegmentRef(traceSegment.getRefs().get(0)); + } + + @Test + public void testWithOccurException() throws Throwable { + tomcatInvokeInterceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult); + tomcatInvokeInterceptor.handleMethodException(enhancedInstance, null, arguments, argumentType, new RuntimeException()); + tomcatInvokeInterceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + + assertHttpSpan(spans.get(0)); + List logDataEntities = SpanHelper.getLogs(spans.get(0)); + assertThat(logDataEntities.size(), is(1)); + assertException(logDataEntities.get(0), RuntimeException.class); + } + + private void assertTraceSegmentRef(TraceSegmentRef ref) { + assertThat(SegmentRefHelper.getEntryApplicationInstanceId(ref), is(1)); + assertThat(SegmentRefHelper.getSpanId(ref), is(3)); + assertThat(SegmentRefHelper.getTraceSegmentId(ref).toString(), is("1.234.111")); + } + + private void assertHttpSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), is("/test/testRequestURL")); + assertComponent(span, ComponentsDefine.JETTY_SERVER); + assertTag(span, 0, "http://localhost:8080/test/testRequestURL"); + assertThat(span.isEntry(), is(true)); + assertLayer(span, SpanLayer.HTTP); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml new file mode 100644 index 000000000..00c29a297 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + + org.skywalking + apm-sdk-plugin + 3.2.1-2017 + + + jetty-plugins + + jetty-client-9.x-plugin + jetty-server-9.x-plugin + + pom + + jetty-plugin + http://maven.apache.org + diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 33ce19e05..a365e6552 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -25,6 +25,7 @@ spring-plugins struts2-2.x-plugin nutz-plugins + jetty-plugin pom -- GitLab