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 86a684b59d8689fdb283dc8a9b892fdc1d923ae8..3689660ef7dccc2ba2f92950777a1087590f343f 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
@@ -35,6 +35,10 @@ public class ComponentsDefine {
public static final OfficialComponent SPRING_MVC_ANNOTATION = new OfficialComponent(14, "SpringMVCAnnotation");
+ public static final OfficialComponent NUTZ_MVC_ANNOTATION = new OfficialComponent(15, "NutzMVCAnnotation");
+
+ public static final OfficialComponent NUTZ_HTTP = new OfficialComponent(16, "NutzHttp");
+
private static ComponentsDefine instance = new ComponentsDefine();
private String[] components;
@@ -44,7 +48,7 @@ public class ComponentsDefine {
}
public ComponentsDefine() {
- components = new String[15];
+ components = new String[17];
addComponent(TOMCAT);
addComponent(HTTPCLIENT);
addComponent(DUBBO);
@@ -59,6 +63,8 @@ public class ComponentsDefine {
addComponent(OKHTTP);
addComponent(SPRING_REST_TEMPLATE);
addComponent(SPRING_MVC_ANNOTATION);
+ addComponent(NUTZ_MVC_ANNOTATION);
+ addComponent(NUTZ_HTTP);
}
private void addComponent(OfficialComponent component) {
diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml
index d53be96015e663670a6e04a4d8c445873d8b0d54..33ef29c4c7355313ca065da3be886f12bccb6459 100644
--- a/apm-sniffer/apm-agent/pom.xml
+++ b/apm-sniffer/apm-agent/pom.xml
@@ -100,6 +100,16 @@
apm-spring-cloud-feign-1.x-plugin
${project.version}
+
+ org.skywalking
+ apm-nutz-mvc-annotation-1.x-plugin
+ ${project.version}
+
+
+ org.skywalking
+ apm-nutz-http-1.x-plugin
+ ${project.version}
+
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2059976905b794f3c26800e7f200f2c45b1cda73
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml
@@ -0,0 +1,24 @@
+
+
+ nutz-plugins
+ org.skywalking
+ 3.2-2017
+
+ 4.0.0
+
+ apm-nutz-http-1.x-plugin
+ jar
+
+ http-1.x-plugin
+ http://maven.apache.org
+
+
+
+ org.nutz
+ nutz
+ 1.r.62
+ provided
+
+
+
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/SenderSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/SenderSendInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..c56aa039d286cbbd1b047cdb18c83479a63e14d2
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/SenderSendInterceptor.java
@@ -0,0 +1,62 @@
+package org.skywalking.apm.plugin.nutz.http.sync;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URI;
+
+import org.nutz.http.Request;
+import org.nutz.http.Request.METHOD;
+import org.nutz.http.Response;
+import org.nutz.http.Sender;
+import org.skywalking.apm.agent.core.conf.Config;
+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 SenderSendInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ Field field = Sender.class.getDeclaredField("request");
+ field.setAccessible(true);
+ Request req = (Request) field.get(objInst);
+ final URI requestURL = req.getUrl().toURI();
+ final METHOD httpMethod = req.getMethod();
+ final ContextCarrier contextCarrier = new ContextCarrier();
+ String remotePeer = requestURL.getHost() + ":" + requestURL.getPort();
+ AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer);
+
+ span.setComponent(ComponentsDefine.NUTZ_HTTP);
+ Tags.URL.set(span, requestURL.getScheme() + "://" + requestURL.getHost() + ":" + requestURL.getPort() + requestURL.getPath());
+ Tags.HTTP.METHOD.set(span, httpMethod.toString());
+ SpanLayer.asHttp(span);
+
+ req.getHeader().set(Config.Plugin.Propagation.HEADER_NAME, contextCarrier.serialize());
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ Response response = (Response)ret;
+ int statusCode = response.getStatus();
+ AbstractSpan span = ContextManager.activeSpan();
+ if (statusCode >= 400) {
+ span.errorOccurred();
+ Tags.STATUS_CODE.set(span, Integer.toString(statusCode));
+ }
+ 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/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/define/NutzHttpInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/define/NutzHttpInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..df87868db642295f3fe2d1ac70221f1a08dae1ae
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/http/sync/define/NutzHttpInstrumentation.java
@@ -0,0 +1,60 @@
+package org.skywalking.apm.plugin.nutz.http.sync.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
+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 org.skywalking.apm.agent.core.plugin.match.HierarchyMatch;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+/**
+ * {@link NutzHttpInstrumentation} enhance the doExecute
method,handleResponse
method and
+ * handleResponse
method of org.springframework.web.client.RestTemplate
by
+ * org.skywalking.apm.plugin.spring.resttemplate.sync.RestExecuteInterceptor
,
+ * org.skywalking.apm.plugin.spring.resttemplate.sync.RestResponseInterceptor
and
+ * org.skywalking.apm.plugin.spring.resttemplate.sync.RestRequestInterceptor
.
+ *
+ * org.skywalking.apm.plugin.spring.resttemplate.sync.RestResponseInterceptor
set context to header for
+ * propagate trace context after execute createRequest
.
+ *
+ * @author wendal
+ */
+public class NutzHttpInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String ENHANCE_CLASS = "org.nutz.http.Sender";
+ private static final String DO_EXECUTE_METHOD_NAME = "send";
+ private static final String DO_EXECUTE_INTERCEPTOR = "org.skywalking.apm.plugin.nutz.http.sync.SenderSendInterceptor";
+
+ @Override
+ protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(DO_EXECUTE_METHOD_NAME);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return DO_EXECUTE_INTERCEPTOR;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return HierarchyMatch.byHierarchyMatch(new String[]{ENHANCE_CLASS});
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000000000000000000000000000000000..f37126670154a64555bca81403521ab93b968172
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1 @@
+nutz-http-1.x=org.skywalking.apm.plugin.nutz.http.sync.define.NutzHttpInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a725bd6c41e2762a80b3bb4d216a4135fee45ff4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml
@@ -0,0 +1,30 @@
+
+
+ nutz-plugins
+ org.skywalking
+ 3.2-2017
+
+ 4.0.0
+
+ apm-nutz-mvc-annotation-1.x-plugin
+ jar
+
+ mvc-annotation-1.x-plugin
+ http://maven.apache.org
+
+
+
+ org.nutz
+ nutz
+ 1.r.62
+ provided
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+
+
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerConstructorInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..04afa0f54d6fdd81f2ebe96e9704720385ca7994
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerConstructorInterceptor.java
@@ -0,0 +1,32 @@
+package org.skywalking.apm.plugin.nutz.mvc;
+
+import org.nutz.mvc.annotation.At;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * The ControllerConstructorInterceptor
intercepts the Controller's constructor, in order to acquire the
+ * mapping annotation, if exist.
+ *
+ * But, you can see we only use the first mapping value, Why?
+ *
+ * Right now, we intercept the controller by annotation as you known, so we CAN'T know which uri patten is actually
+ * matched. Even we know, that costs a lot.
+ *
+ * If we want to resolve that, we must intercept the Nutz MVC core codes, that is not a good choice for now.
+ *
+ * Comment by @wu-sheng
+ */
+public class ControllerConstructorInterceptor implements InstanceConstructorInterceptor {
+
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+ String basePath = "";
+ At basePathRequestMapping = objInst.getClass().getAnnotation(At.class);
+ if (basePathRequestMapping != null) {
+ basePath = basePathRequestMapping.value()[0];
+ }
+ PathMappingCache pathMappingCache = new PathMappingCache(basePath);
+ objInst.setSkyWalkingDynamicField(pathMappingCache);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerServiceMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerServiceMethodInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..44d0b7114b1bf5e750b51d9e3137afe81565d705
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/ControllerServiceMethodInterceptor.java
@@ -0,0 +1,71 @@
+package org.skywalking.apm.plugin.nutz.mvc;
+
+import java.lang.reflect.Method;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.nutz.mvc.Mvcs;
+import org.nutz.mvc.annotation.At;
+import org.skywalking.apm.agent.core.conf.Config;
+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;
+
+/**
+ * The ControllerServiceMethodInterceptor
only use the first mapping value.
+ *
+ * @See {@link ControllerConstructorInterceptor} to explain why we are doing this.
+ */
+public class ControllerServiceMethodInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ PathMappingCache pathMappingCache = (PathMappingCache)objInst.getSkyWalkingDynamicField();
+ String requestURL = pathMappingCache.findPathMapping(method);
+ if (requestURL == null) {
+ At methodRequestMapping = method.getAnnotation(At.class);
+ if (methodRequestMapping.value().length > 0) {
+ requestURL = methodRequestMapping.value()[0];
+ } else {
+ requestURL = "";
+ }
+ pathMappingCache.addPathMapping(method, requestURL);
+ requestURL = pathMappingCache.findPathMapping(method);
+ }
+
+ HttpServletRequest request = Mvcs.getReq();
+ String tracingHeaderValue = request.getHeader(Config.Plugin.Propagation.HEADER_NAME);
+ ContextCarrier contextCarrier = new ContextCarrier().deserialize(tracingHeaderValue);
+ AbstractSpan span = ContextManager.createEntrySpan(requestURL, contextCarrier);
+ Tags.URL.set(span, request.getRequestURL().toString());
+ Tags.HTTP.METHOD.set(span, request.getMethod());
+ span.setComponent(ComponentsDefine.NUTZ_MVC_ANNOTATION);
+ SpanLayer.asHttp(span);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ HttpServletResponse response = Mvcs.getResp();
+
+ 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);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/PathMappingCache.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/PathMappingCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..f00584249122e42fbd23156758e30d86db1fc0d5
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/PathMappingCache.java
@@ -0,0 +1,28 @@
+package org.skywalking.apm.plugin.nutz.mvc;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * The PathMappingCache
represents a field
+ *
+ *
+ * @author wusheng
+ */
+public class PathMappingCache {
+ private String classPath = "";
+
+ private ConcurrentHashMap methodPathMapping = new ConcurrentHashMap();
+
+ public PathMappingCache(String classPath) {
+ this.classPath = classPath;
+ }
+
+ public String findPathMapping(Method method) {
+ return methodPathMapping.get(method);
+ }
+
+ public void addPathMapping(Method method, String methodPath) {
+ methodPathMapping.put(method, classPath + methodPath);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/AbstractControllerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/AbstractControllerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e276953add07e4093bbec6e28aac83e8a18b431
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/AbstractControllerInstrumentation.java
@@ -0,0 +1,65 @@
+package org.skywalking.apm.plugin.nutz.mvc.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.any;
+import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
+
+/**
+ *
+ * @author wendal
+ */
+public abstract class AbstractControllerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ @Override
+ protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[] {
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher getConstructorMatcher() {
+ return any();
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return "org.skywalking.apm.plugin.nutz.mvc.ControllerConstructorInterceptor";
+ }
+ }
+ };
+ }
+
+ @Override
+ protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return isAnnotatedWith(named("org.nutz.mvc.annotation.At"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.skywalking.apm.plugin.nutz.mvc.ControllerServiceMethodInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byClassAnnotationMatch(getEnhanceAnnotations());
+ }
+
+ protected abstract String[] getEnhanceAnnotations();
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/ControllerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/ControllerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bb039dcb4395396212de2ba4c37345f58d7c7dd
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/java/org/skywalking/apm/plugin/nutz/mvc/define/ControllerInstrumentation.java
@@ -0,0 +1,10 @@
+package org.skywalking.apm.plugin.nutz.mvc.define;
+
+public class ControllerInstrumentation extends AbstractControllerInstrumentation {
+
+ public static final String ENHANCE_ANNOTATION = "org.nutz.mvc.annotation.At";
+
+ @Override protected String[] getEnhanceAnnotations() {
+ return new String[] {ENHANCE_ANNOTATION};
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000000000000000000000000000000000..15ba62cdfdb5e5d2091b26d9e4f6827ec0aeac32
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1 @@
+nutz-mvc-annotation-1.x=org.skywalking.apm.plugin.nutz.mvc.define.ControllerInstrumentation
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b9249fc68c717f1218c97dcbea6d6d1de87b99da
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml
@@ -0,0 +1,27 @@
+
+
+ 4.0.0
+
+
+ org.skywalking
+ apm-sdk-plugin
+ 3.2-2017
+
+
+ nutz-plugins
+
+
+ http-1.x-plugin
+ mvc-annotation-1.x-plugin
+
+ pom
+
+ apm-sdk-plugin
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 1b06f19d82cd2400a9d13cf33b4f2c5243a5eda7..b3e6782e92b85718e3ac51729c2eac48f3009b6c 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -23,6 +23,7 @@
resin-3.x-plugin
resin-4.x-plugin
spring-plugins
+ nutz-plugins
pom