作者: SkyWalking 兴趣爱好者,赵禹光
public class AgentMain { public static void premain(String agentOps, Instrumentation instrumentation) { new AgentBuilder.Default() .type(ElementMatchers.named("org.springframework.web.servlet.DispatcherServlet")) .transform((builder, type, classLoader, module) -> builder.method(ElementMatchers.named("doDispatch")) .intercept(MethodDelegation.to(DoDispatchInterceptor.class))) .installOn(instrumentation); } }
public class DoDispatchInterceptor { @RuntimeType public static Object intercept(@Argument(0) HttpServletRequest request, @SuperCall Callable<?> callable) { final StringBuilder in = new StringBuilder(); if (request.getParameterMap() != null && request.getParameterMap().size() > 0) { request.getParameterMap().keySet().forEach(key -> in.append("key=" + key + "_value=" + request.getParameter(key) + ",")); } long agentStart = System.currentTimeMillis(); try { return callable.call(); } catch (Exception e) { System.out.println("Exception :" + e.getMessage()); return null; } finally { System.out.println("path:" + request.getRequestURI() + " 入参:" + in + " 耗时:" + (System.currentTimeMillis() - agentStart)); } } }
Manifest-Version: 1.0
Premain-Class: com.z.test.agent.AgentMain
Can-Redefine-Classes: true
dependencies
+net.bytebuddy.byte-buddy
+javax.servlet.javax.servlet-api *scope=provided
plugins
+maven-jar-plugin *manifestFile=src/main/resources/META-INF/MANIFEST.MF
+maven-shade-plugin *include:net.bytebuddy:byte-buddy:jar:
+maven-compiler-plugin
@SpringBootApplication(scanBasePackages = {"com"}) public class TestBootWeb { public static void main(String[] args) { SpringApplication.run(TestBootWeb.class, args); } @RestController public class ApiController { @PostMapping("/ping") public String ping(HttpServletRequest request) { return "pong"; } } }
VM options增加:-JavaAgent:{$HOME}/Code/github/z_my_test/test-agent/target/test-agent-1.0-SNAPSHOT.jar=args
Before launch 在Build之前增加:
Working directory:{$HOME}/Code/github/incubator-skywalking
Command line:-T 1C -pl test-agent -am clean package -Denforcer.skip=true -Dmaven.test.skip=true -Dmaven.compile.fork=true
VM options增加:-JavaAgent:-JavaAgent:{$HOME}/Code/github/incubator-skywalking/skywalking-agent/skywalking-agent.jar:不要用dist里面的skywalking-agent.jar,具体原因大家可以看看源码:apm-sniffer/apm-agent/pom.xml中的maven插件的使用。
Before launch 在Build之前增加:
Working directory:{$HOME}/Code/github/incubator-skywalking
Command line:-T 1C -pl apm-sniffer/apm-sdk-plugin -amd clean package -Denforcer.skip=true -Dmaven.test.skip=true -Dmaven.compile.fork=true: 这里我针对插件包,因为紧接着下文要开发插件
另外根pom注释maven-checkstyle-plugin也可加速编译
<artifactId>apm-sdk-plugin</artifactId> <modules> <module>kob-plugin</module> ... <modules>
kob=org.apache.skywalking.apm.plugin.kob.KobInstrumentation
public class KobInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "com.ke.kob.client.spring.core.TaskDispatcher"; private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.kob.KobInterceptor"; @Override protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return null; } @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher<MethodDescription> getMethodsMatcher() { return named("dispatcher1"); } @Override public String getMethodsInterceptor() { return INTERCEPT_CLASS; } @Override public boolean isOverrideArgs() { return false; } } }; } }
public class KobInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable { final ContextCarrier contextCarrier = new ContextCarrier(); com.ke.kob.client.spring.model.TaskContext context = (TaskContext) allArguments[0]; CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); next.setHeadValue(JSON.toJSONString(context.getUserParam())); } AbstractSpan span = ContextManager.createEntrySpan("client:"+allArguments[1]+",task:"+context.getTaskKey(), contextCarrier); span.setComponent(ComponentsDefine.TRANSPORT_CLIENT); SpanLayer.asRPCFramework(span); } @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) { } }