添加全方法监控的功能

This commit is contained in:
ascrutae 2016-07-21 08:09:42 +08:00
parent f5acbaff87
commit 81a8aabc02
6 changed files with 158 additions and 0 deletions

View File

@ -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();
}

View File

@ -44,6 +44,16 @@
<version>1.0-Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.20.0-GA</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -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 {

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,8 @@
package com.ai.cloud.skywalking.transformer;
public class StaticMethodInterceptor {
public void intercept(Class originClass, Object[] allArgument) {
}
}