From 81a8aabc02e4e879b89cc886a5014cee63364ddf Mon Sep 17 00:00:00 2001 From: ascrutae Date: Thu, 21 Jul 2016 08:09:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=A8=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../skywalking/agent/SkywalkingAgent.java | 8 +++ skywalking-collector/skywalking-api/pom.xml | 10 +++ .../com/ai/cloud/skywalking/conf/Config.java | 2 + .../transformer/ClassTransformer.java | 64 ++++++++++++++++++ .../transformer/MethodInterceptor.java | 66 +++++++++++++++++++ .../transformer/StaticMethodInterceptor.java | 8 +++ 6 files changed, 158 insertions(+) create mode 100644 skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/ClassTransformer.java create mode 100644 skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/MethodInterceptor.java create mode 100644 skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/StaticMethodInterceptor.java diff --git a/skywalking-collector/skywalking-agent/src/main/java/com/ai/cloud/skywalking/agent/SkywalkingAgent.java b/skywalking-collector/skywalking-agent/src/main/java/com/ai/cloud/skywalking/agent/SkywalkingAgent.java index bc1b7dd85..8c0b2f273 100644 --- a/skywalking-collector/skywalking-agent/src/main/java/com/ai/cloud/skywalking/agent/SkywalkingAgent.java +++ b/skywalking-collector/skywalking-agent/src/main/java/com/ai/cloud/skywalking/agent/SkywalkingAgent.java @@ -1,12 +1,20 @@ package com.ai.cloud.skywalking.agent; +import com.ai.cloud.skywalking.conf.Config; +import com.ai.cloud.skywalking.conf.ConfigInitializer; import com.ai.cloud.skywalking.plugin.PluginBootstrap; +import com.ai.cloud.skywalking.transformer.ClassTransformer; import java.lang.instrument.Instrumentation; public class SkywalkingAgent { public static void premain(String agentArgs, Instrumentation inst) { + ConfigInitializer.initialize(); + if (Config.SkyWalking.ALL_METHOD_MONITOR){ + inst.addTransformer(new ClassTransformer()); + } + PluginBootstrap bootstrap = new PluginBootstrap(); bootstrap.start(); } diff --git a/skywalking-collector/skywalking-api/pom.xml b/skywalking-collector/skywalking-api/pom.xml index 9c1a16567..f5876477c 100644 --- a/skywalking-collector/skywalking-api/pom.xml +++ b/skywalking-collector/skywalking-api/pom.xml @@ -44,6 +44,16 @@ 1.0-Final test + + org.javassist + javassist + 3.20.0-GA + + + com.google.code.gson + gson + 2.7 + diff --git a/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/conf/Config.java b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/conf/Config.java index 8d3af182d..dd5308038 100644 --- a/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/conf/Config.java +++ b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/conf/Config.java @@ -12,6 +12,8 @@ public class Config { public static boolean AUTH_OVERRIDE = false; public static String CHARSET = "UTF-8"; + + public static boolean ALL_METHOD_MONITOR = false; } public static class BuriedPoint { diff --git a/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/ClassTransformer.java b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/ClassTransformer.java new file mode 100644 index 000000000..e36c867cf --- /dev/null +++ b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/ClassTransformer.java @@ -0,0 +1,64 @@ +package com.ai.cloud.skywalking.transformer; + +import com.ai.cloud.skywalking.logging.LogManager; +import com.ai.cloud.skywalking.logging.Logger; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtMethod; + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.reflect.Modifier; +import java.security.ProtectionDomain; + +public class ClassTransformer implements ClassFileTransformer { + + private Logger logger = LogManager.getLogger(ClassTransformer.class); + + @Override + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { + String interceptorPackage = System.getProperty("interceptor.package", ""); + if (interceptorPackage == null || interceptorPackage.length() == 0) { + return classfileBuffer; + } + + if (!className.replaceAll("/", ".").startsWith(interceptorPackage)) { + return classfileBuffer; + } + + try { + ClassPool classPool = ClassPool.getDefault(); + CtClass ctClass = classPool.get(className.replaceAll("/", ".")); + + if (ctClass.isInterface()) { + return classfileBuffer; + } + + CtMethod[] ctMethod = ctClass.getDeclaredMethods(); + for (CtMethod method : ctMethod) { + if (Modifier.isStatic(method.getModifiers())) { + continue; + } + + String methodName = method.getName(); + method.setName(methodName + "_skywalking_enhance"); + + CtMethod newMethod = + new CtMethod(method.getReturnType(), methodName, method.getParameterTypes(), + method.getDeclaringClass()); + newMethod.setBody("{" + + MethodInterceptor.class.getName() + ".before($class,,$sig,$args,$0,\"" + methodName + "\");" + + "return " + methodName + "_skywalking_enhance($$);}"); + newMethod.addCatch("{ " + MethodInterceptor.class.getName() + ".handleException(e); throw e;}", classPool.get("java.lang.Throwable"), "e"); + newMethod.insertAfter("{" + MethodInterceptor.class.getName() + ".after($class,$type,$_);}", true); + + ctClass.addMethod(newMethod); + } + return ctClass.toBytecode(); + } catch (Exception e) { + logger.error("Failed to transform class" + className, e); + return classfileBuffer; + } + + } +} diff --git a/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/MethodInterceptor.java b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/MethodInterceptor.java new file mode 100644 index 000000000..bc3ba88c9 --- /dev/null +++ b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/MethodInterceptor.java @@ -0,0 +1,66 @@ +package com.ai.cloud.skywalking.transformer; + +import com.ai.cloud.skywalking.api.IBuriedPointType; +import com.ai.cloud.skywalking.invoke.monitor.LocalMethodInvokeMonitor; +import com.ai.cloud.skywalking.model.Identification; +import com.ai.cloud.skywalking.protocol.common.CallType; +import com.google.gson.Gson; + +public class MethodInterceptor { + + + public void before(Class originClass, Class[] parametersType, Object[] allArgument, Object superCall, String methodName) { + LocalMethodInvokeMonitor localMethodInvokeMonitor = new LocalMethodInvokeMonitor(); + Identification.IdentificationBuilder identificationBuilder = Identification.newBuilder(); + identificationBuilder.viewPoint(generateViewPoint(originClass, parametersType, methodName)); + appendingParameters(allArgument, identificationBuilder); + identificationBuilder.spanType(new IBuriedPointType() { + @Override + public String getTypeName() { + return "LOCAL"; + } + + @Override + public CallType getCallType() { + return CallType.SYNC; + } + }); + + localMethodInvokeMonitor.beforeInvoke(identificationBuilder.build()); + + } + + private void appendingParameters(Object[] allArgument, Identification.IdentificationBuilder identificationBuilder) { + for (int i = 0; i < allArgument.length; i++) { + try { + identificationBuilder.appendParameter("P" + i, new Gson().toJson(allArgument[i])); + } catch (Exception e) { + // Do nothing + } finally { + identificationBuilder.appendParameter("P" + i, "Cannot convert parameter"); + } + } + } + + private String generateViewPoint(Class originClass, Class[] parametersType, String methodName) { + StringBuilder viewPoint = new StringBuilder(originClass.getName() + "." + methodName + "("); + for (Class parameterType : parametersType) { + viewPoint.append(parameterType.getClass() + ","); + } + viewPoint.append(")"); + return viewPoint.toString(); + } + + + public void handleException(Throwable e) { + new LocalMethodInvokeMonitor().occurException(e); + } + + + public void after(Class originClass, Class resultType, Object result) { + //TODO 需要把参数累加上去 + new LocalMethodInvokeMonitor().afterInvoke(); + } + + +} diff --git a/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/StaticMethodInterceptor.java b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/StaticMethodInterceptor.java new file mode 100644 index 000000000..72fbdd491 --- /dev/null +++ b/skywalking-collector/skywalking-api/src/main/java/com/ai/cloud/skywalking/transformer/StaticMethodInterceptor.java @@ -0,0 +1,8 @@ +package com.ai.cloud.skywalking.transformer; + +public class StaticMethodInterceptor { + + public void intercept(Class originClass, Object[] allArgument) { + + } +}