Merge branch 'dev/3.2.1' of https://github.com/wu-sheng/sky-walking
# Conflicts: # apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java # apm-sniffer/apm-agent/pom.xml # apm-sniffer/apm-sdk-plugin/pom.xml
This commit is contained in:
commit
e68d48a6d4
|
|
@ -4,6 +4,8 @@ import java.util.Iterator;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import org.apache.zookeeper.CreateMode;
|
||||
import org.apache.zookeeper.WatchedEvent;
|
||||
import org.apache.zookeeper.Watcher;
|
||||
|
|
@ -46,22 +48,30 @@ public class ClusterZKDataMonitor implements DataMonitor, Watcher {
|
|||
List<String> paths;
|
||||
try {
|
||||
paths = client.getChildren(event.getPath(), true);
|
||||
ClusterDataListener listener = listeners.get(event.getPath());
|
||||
Set<String> remoteNodes = new HashSet<String>();
|
||||
Set<String> notifiedNodes = listener.getAddresses();
|
||||
if (CollectionUtils.isNotEmpty(paths)) {
|
||||
for (String serverPath : paths) {
|
||||
Stat stat = new Stat();
|
||||
byte[] data = client.getData(event.getPath() + "/" + serverPath, true, stat);
|
||||
String dataStr = new String(data);
|
||||
if (stat.getCzxid() == stat.getMzxid()) {
|
||||
String addressValue = serverPath + dataStr;
|
||||
remoteNodes.add(addressValue);
|
||||
if (!notifiedNodes.contains(addressValue)) {
|
||||
logger.info("path children has been created, path: {}, data: {}", event.getPath() + "/" + serverPath, dataStr);
|
||||
listeners.get(event.getPath()).addAddress(serverPath + dataStr);
|
||||
listeners.get(event.getPath()).serverJoinNotify(serverPath + dataStr);
|
||||
} else {
|
||||
logger.info("path children has been changed, path: {}, data: {}", event.getPath() + "/" + serverPath, dataStr);
|
||||
listeners.get(event.getPath()).removeAddress(serverPath + dataStr);
|
||||
listeners.get(event.getPath()).serverQuitNotify(serverPath + dataStr);
|
||||
listener.addAddress(addressValue);
|
||||
listener.serverJoinNotify(addressValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String address : notifiedNodes) {
|
||||
if (remoteNodes.isEmpty() || !remoteNodes.contains(address)) {
|
||||
logger.info("path children has been changed, path and data: {}", event.getPath() + "/" + address);
|
||||
listener.removeAddress(address);
|
||||
listener.serverQuitNotify(address);
|
||||
}
|
||||
}
|
||||
} catch (ZookeeperClientException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,11 +33,13 @@ public class ComponentsDefine {
|
|||
|
||||
public static final OfficialComponent SPRING_REST_TEMPLATE = new OfficialComponent(13, "SpringRestTemplate");
|
||||
|
||||
public static final OfficialComponent SPRING_MVC_ANNOTATION = new OfficialComponent(14, "SpringMVCAnnotation");
|
||||
public static final OfficialComponent SPRING_MVC_ANNOTATION = new OfficialComponent(14, "SpringMVC");
|
||||
|
||||
public static final OfficialComponent NUTZ_MVC_ANNOTATION = new OfficialComponent(15, "NutzMVCAnnotation");
|
||||
public static final OfficialComponent STRUTS2 = new OfficialComponent(15, "Struts2");
|
||||
|
||||
public static final OfficialComponent NUTZ_HTTP = new OfficialComponent(16, "NutzHttp");
|
||||
public static final OfficialComponent NUTZ_MVC_ANNOTATION = new OfficialComponent(16, "NutzMVCAnnotation");
|
||||
|
||||
public static final OfficialComponent NUTZ_HTTP = new OfficialComponent(17, "NutzHttp");
|
||||
|
||||
private static ComponentsDefine instance = new ComponentsDefine();
|
||||
|
||||
|
|
@ -48,7 +50,7 @@ public class ComponentsDefine {
|
|||
}
|
||||
|
||||
public ComponentsDefine() {
|
||||
components = new String[17];
|
||||
components = new String[18];
|
||||
addComponent(TOMCAT);
|
||||
addComponent(HTTPCLIENT);
|
||||
addComponent(DUBBO);
|
||||
|
|
@ -63,6 +65,7 @@ public class ComponentsDefine {
|
|||
addComponent(OKHTTP);
|
||||
addComponent(SPRING_REST_TEMPLATE);
|
||||
addComponent(SPRING_MVC_ANNOTATION);
|
||||
addComponent(STRUTS2);
|
||||
addComponent(NUTZ_MVC_ANNOTATION);
|
||||
addComponent(NUTZ_HTTP);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@
|
|||
<artifactId>apm-spring-cloud-feign-1.x-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<artifactId>apm-struts2-2.x-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<artifactId>apm-nutz-mvc-annotation-1.x-plugin</artifactId>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
<module>resin-3.x-plugin</module>
|
||||
<module>resin-4.x-plugin</module>
|
||||
<module>spring-plugins</module>
|
||||
<module>struts2-2.x-plugin</module>
|
||||
<module>nutz-plugins</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>apm-sdk-plugin</artifactId>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<version>3.2.1-2017</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-struts2-2.x-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>struts2-2.x-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jsp-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- 源码插件 -->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<!-- 发布时自动将源码同时发布的配置 -->
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package org.skywalking.apm.plugin.struts2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
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 Struts2Interceptor implements InstanceMethodsAroundInterceptor {
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
HttpServletRequest request = ServletActionContext.getRequest();
|
||||
ContextCarrier contextCarrier = new ContextCarrier();
|
||||
|
||||
CarrierItem next = contextCarrier.items();
|
||||
while (next.hasNext()) {
|
||||
next = next.next();
|
||||
next.setHeadValue(request.getHeader(next.getHeadKey()));
|
||||
}
|
||||
|
||||
AbstractSpan span = ContextManager.createEntrySpan(request.getRequestURI(), contextCarrier);
|
||||
Tags.URL.set(span, request.getRequestURL().toString());
|
||||
Tags.HTTP.METHOD.set(span, request.getMethod());
|
||||
span.setComponent(ComponentsDefine.STRUTS2);
|
||||
SpanLayer.asHttp(span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
HttpServletResponse response = ServletActionContext.getResponse();
|
||||
|
||||
AbstractSpan span = ContextManager.activeSpan();
|
||||
if (response.getStatus() >= 400) {
|
||||
span.errorOccurred();
|
||||
Tags.STATUS_CODE.set(span, Integer.toString(response.getStatus()));
|
||||
}
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package org.skywalking.apm.plugin.struts2.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 Struts2Instrumentation} enhance the <code>invokeAction</code> method
|
||||
* in <code>com.opensymphony.xwork2.DefaultActionInvocation</code> class by
|
||||
* <code>org.skywalking.apm.plugin.struts2.Struts2Interceptor</code> class
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class Struts2Instrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ENHANCE_CLASS = "com.opensymphony.xwork2.DefaultActionInvocation";
|
||||
private static final String ENHANCE_METHOD = "invokeAction";
|
||||
private static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.struts2.Struts2Interceptor";
|
||||
|
||||
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[]{
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(ENHANCE_METHOD);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return INTERCEPT_CLASS;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
struts2-2.x=org.skywalking.apm.plugin.struts2.define.Struts2Instrumentation
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package org.skywalking.apm.plugin.struts2;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
|
||||
import org.skywalking.apm.agent.core.conf.Config;
|
||||
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.powermock.api.mockito.PowerMockito.mock;
|
||||
import static org.powermock.api.mockito.PowerMockito.mockStatic;
|
||||
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)
|
||||
@PrepareForTest({ActionContext.class})
|
||||
public class Struts2InterceptorTest {
|
||||
|
||||
private Struts2Interceptor struts2Interceptor;
|
||||
|
||||
@SegmentStoragePoint
|
||||
private SegmentStorage segmentStorage;
|
||||
|
||||
private ActionContext actionContext;
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule serviceRule = new AgentServiceRule();
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
@Mock
|
||||
private HttpServletResponse response;
|
||||
@Mock
|
||||
private MethodInterceptResult methodInterceptResult;
|
||||
|
||||
@Mock
|
||||
private EnhancedInstance enhancedInstance;
|
||||
|
||||
private Object[] arguments;
|
||||
private Class[] argumentType;
|
||||
|
||||
private Object[] exceptionArguments;
|
||||
private Class[] exceptionArgumentType;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
struts2Interceptor = new Struts2Interceptor();
|
||||
when(request.getRequestURI()).thenReturn("/test/testRequestURL");
|
||||
when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL"));
|
||||
when(response.getStatus()).thenReturn(200);
|
||||
|
||||
mockStatic(ActionContext.class);
|
||||
actionContext = mock(ActionContext.class);
|
||||
when(actionContext.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE)).thenReturn(response);
|
||||
when(actionContext.get(StrutsStatics.HTTP_REQUEST)).thenReturn(request);
|
||||
when(ActionContext.getContext()).thenReturn(actionContext);
|
||||
|
||||
arguments = new Object[] {request, response};
|
||||
argumentType = new Class[] {request.getClass(), response.getClass()};
|
||||
|
||||
exceptionArguments = new Object[] {request, response, new RuntimeException()};
|
||||
exceptionArgumentType = new Class[] {request.getClass(), response.getClass(), new RuntimeException().getClass()};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithoutSerializedContextData() throws Throwable {
|
||||
struts2Interceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult);
|
||||
struts2Interceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null);
|
||||
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
List<AbstractTracingSpan> 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*");
|
||||
|
||||
struts2Interceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult);
|
||||
struts2Interceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null);
|
||||
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
|
||||
|
||||
assertHttpSpan(spans.get(0));
|
||||
assertTraceSegmentRef(traceSegment.getRefs().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithOccurException() throws Throwable {
|
||||
struts2Interceptor.beforeMethod(enhancedInstance, null, arguments, argumentType, methodInterceptResult);
|
||||
struts2Interceptor.handleMethodException(enhancedInstance, null, arguments, argumentType, new RuntimeException());
|
||||
struts2Interceptor.afterMethod(enhancedInstance, null, arguments, argumentType, null);
|
||||
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
|
||||
|
||||
assertHttpSpan(spans.get(0));
|
||||
List<LogDataEntity> 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.STRUTS2);
|
||||
assertTag(span, 0, "http://localhost:8080/test/testRequestURL");
|
||||
assertThat(span.isEntry(), is(true));
|
||||
assertLayer(span, SpanLayer.HTTP);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue