mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-24 12:16:33 +10:00
[유치수] [NOBTS] add mysql interceptor
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@556 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package com.profiler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.profiler.util.NamedThreadLocal;
|
||||
|
||||
public class StopWatch {
|
||||
|
||||
private static ThreadLocal<Map<String, Long>> local = new NamedThreadLocal<Map<String, Long>>("StopWatch");
|
||||
|
||||
public static void start(String name) {
|
||||
Map<String, Long> map = local.get();
|
||||
if (map == null) {
|
||||
map = new HashMap<String, Long>(1);
|
||||
map.put(name, System.currentTimeMillis());
|
||||
local.set(map);
|
||||
} else {
|
||||
map.put(name, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
public static long stopAndGetElapsed(String name) {
|
||||
Map<String, Long> map = local.get();
|
||||
if (map == null) {
|
||||
throw new IllegalStateException("Stopwatch is not started.");
|
||||
} else {
|
||||
return System.currentTimeMillis() - map.get(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,9 @@ public class Trace {
|
||||
TraceID id = traceId.get();
|
||||
|
||||
if (id == null) {
|
||||
return TraceID.newTraceId();
|
||||
id = TraceID.newTraceId();
|
||||
traceId.set(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.profiler.context.tracer;
|
||||
|
||||
|
||||
public class HippoAnnotation {
|
||||
|
||||
private final long time;
|
||||
private final String value;
|
||||
private final Long duration;
|
||||
private final String threadname; // TODO: remove, just for debug.
|
||||
|
||||
private EndPoint endPoint;
|
||||
|
||||
@@ -14,6 +14,7 @@ public class HippoAnnotation {
|
||||
this.value = value;
|
||||
this.endPoint = endPoint;
|
||||
this.duration = duration;
|
||||
this.threadname = Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
@@ -33,6 +34,7 @@ public class HippoAnnotation {
|
||||
sb.append(", value=").append(value);
|
||||
sb.append(", duration=").append(duration);
|
||||
sb.append(", endpoint=").append(endPoint);
|
||||
sb.append(", threadname=").append(threadname);
|
||||
sb.append("}");
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -1,37 +1,49 @@
|
||||
package com.profiler.modifier;
|
||||
|
||||
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
import javassist.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javassist.ClassPool;
|
||||
|
||||
import com.profiler.interceptor.Interceptor;
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
|
||||
public abstract class AbstractModifier implements Modifier {
|
||||
|
||||
private final Logger logger = Logger.getLogger(AbstractModifier.class.getName());
|
||||
|
||||
protected final ClassPool classPool;
|
||||
protected ByteCodeInstrumentor byteCodeInstrumentor;
|
||||
protected ByteCodeInstrumentor byteCodeInstrumentor;
|
||||
|
||||
public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor) {
|
||||
this.byteCodeInstrumentor = byteCodeInstrumentor;
|
||||
this.byteCodeInstrumentor = byteCodeInstrumentor;
|
||||
this.classPool = byteCodeInstrumentor.getClassPool();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void printClassConvertComplete(String javassistClassName) {
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.info(javassistClassName + " class is converted.");
|
||||
}
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.info(javassistClassName + " class is converted.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void checkLibrary(ClassLoader classLoader, String javassistClassName) {
|
||||
this.byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
}
|
||||
public void checkLibrary(ClassLoader classLoader, String javassistClassName) {
|
||||
this.byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
}
|
||||
|
||||
protected Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) {
|
||||
Class<?> aClass = this.byteCodeInstrumentor.defineClass(classLoader, interceptorFQCN, protectedDomain);
|
||||
try {
|
||||
return (Interceptor) aClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
package com.profiler.modifier.db.mysql;
|
||||
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javassist.ByteArrayClassPath;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtConstructor;
|
||||
import javassist.CtMethod;
|
||||
|
||||
import com.profiler.config.TomcatProfilerConstant;
|
||||
import com.profiler.interceptor.Interceptor;
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
import com.profiler.interceptor.bci.InstrumentClass;
|
||||
import com.profiler.modifier.AbstractModifier;
|
||||
import com.profiler.trace.DatabaseRequestTracer;
|
||||
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
private final Logger logger = Logger.getLogger(MySQLPreparedStatementModifier.class.getName());
|
||||
|
||||
@@ -23,12 +26,25 @@ public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
public String getTargetClass() {
|
||||
return "com/mysql/jdbc/PreparedStatement";
|
||||
}
|
||||
|
||||
|
||||
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
|
||||
if (logger.isLoggable(Level.INFO)){
|
||||
logger.info("Modifing. " + javassistClassName);
|
||||
}
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.info("Modifing. " + javassistClassName);
|
||||
}
|
||||
|
||||
checkLibrary(classLoader, javassistClassName);
|
||||
|
||||
// Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteMethodInterceptor");
|
||||
// if (interceptor == null) {
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
// classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer));
|
||||
//
|
||||
// InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
|
||||
// aClass.addInterceptor("executeQuery", null, interceptor);
|
||||
|
||||
return changeMethod(javassistClassName, classFileBuffer);
|
||||
}
|
||||
|
||||
@@ -37,16 +53,16 @@ public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
CtClass cc = classPool.get(javassistClassName);
|
||||
|
||||
updateSetInternalMethod(cc);
|
||||
updateExecuteQueryMethod(cc);
|
||||
updateExecuteQueryMethod(cc);
|
||||
updateConstructor(cc);
|
||||
|
||||
printClassConvertComplete(javassistClassName);
|
||||
|
||||
return cc.toBytecode();
|
||||
} catch (Exception e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -81,6 +97,6 @@ public class MySQLPreparedStatementModifier extends AbstractModifier {
|
||||
|
||||
private void updateExecuteQueryMethod(CtClass cc) throws Exception {
|
||||
CtMethod method = cc.getDeclaredMethod("executeQuery", null);
|
||||
method.insertAfter("{" + DatabaseRequestTracer.FQCN + ".put(" + TomcatProfilerConstant.REQ_DATA_TYPE_DB_EXECUTE_QUERY + "); }");
|
||||
method.insertAfter("{System.out.println(\"AAAAAAA\"); " + DatabaseRequestTracer.FQCN + ".put(" + TomcatProfilerConstant.REQ_DATA_TYPE_DB_EXECUTE_QUERY + "); }");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.profiler.modifier.db.mysql;
|
||||
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
|
||||
import com.profiler.config.TomcatProfilerConstant;
|
||||
import com.profiler.modifier.AbstractModifier;
|
||||
import com.profiler.trace.DatabaseRequestTracer;
|
||||
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javassist.ByteArrayClassPath;
|
||||
|
||||
import com.profiler.interceptor.Interceptor;
|
||||
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
|
||||
import com.profiler.interceptor.bci.InstrumentClass;
|
||||
import com.profiler.modifier.AbstractModifier;
|
||||
|
||||
public class MySQLStatementModifier extends AbstractModifier {
|
||||
|
||||
private final Logger logger = Logger.getLogger(MySQLStatementModifier.class.getName());
|
||||
@@ -23,43 +22,60 @@ public class MySQLStatementModifier extends AbstractModifier {
|
||||
public String getTargetClass() {
|
||||
return "com/mysql/jdbc/StatementImpl";
|
||||
}
|
||||
|
||||
|
||||
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
|
||||
if (logger.isLoggable(Level.INFO)){
|
||||
logger.info("Modifing. " + javassistClassName);
|
||||
}
|
||||
checkLibrary(classLoader, javassistClassName);
|
||||
return changeMethod(javassistClassName, classFileBuffer);
|
||||
}
|
||||
|
||||
private byte[] changeMethod(String javassistClassName, byte[] classfileBuffer) {
|
||||
try {
|
||||
CtClass cc = classPool.get(javassistClassName);
|
||||
|
||||
updateExecuteQueryMethod(cc);
|
||||
|
||||
printClassConvertComplete(javassistClassName);
|
||||
|
||||
return cc.toBytecode();
|
||||
} catch (Exception e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.info("Modifing. " + javassistClassName);
|
||||
}
|
||||
return null;
|
||||
// checkLibrary(classLoader, javassistClassName);
|
||||
|
||||
Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.db.mysql.interceptors.ExecuteQueryMethodInterceptor");
|
||||
if (interceptor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer));
|
||||
|
||||
InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
|
||||
aClass.addInterceptor("executeQuery", new String[] { "java.lang.String" }, interceptor);
|
||||
|
||||
return aClass.toBytecode();
|
||||
|
||||
// return changeMethod(javassistClassName, classFileBuffer);
|
||||
}
|
||||
|
||||
private void updateExecuteQueryMethod(CtClass cc) throws Exception {
|
||||
CtClass[] params = new CtClass[1];
|
||||
params[0] = classPool.getCtClass("java.lang.String");
|
||||
CtMethod method = cc.getDeclaredMethod("executeQuery", params);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{");
|
||||
sb.append(DatabaseRequestTracer.FQCN + ".putSqlQuery(" + TomcatProfilerConstant.REQ_DATA_TYPE_DB_QUERY + ",$1);");
|
||||
sb.append(DatabaseRequestTracer.FQCN + ".put(" + TomcatProfilerConstant.REQ_DATA_TYPE_DB_EXECUTE_QUERY + ");");
|
||||
sb.append("}");
|
||||
|
||||
method.insertAfter(sb.toString());
|
||||
}
|
||||
// private byte[] changeMethod(String javassistClassName, byte[]
|
||||
// classfileBuffer) {
|
||||
// try {
|
||||
// CtClass cc = classPool.get(javassistClassName);
|
||||
//
|
||||
// updateExecuteQueryMethod(cc);
|
||||
//
|
||||
// printClassConvertComplete(javassistClassName);
|
||||
//
|
||||
// return cc.toBytecode();
|
||||
// } catch (Exception e) {
|
||||
// if (logger.isLoggable(Level.WARNING)) {
|
||||
// logger.log(Level.WARNING, e.getMessage(), e);
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// private void updateExecuteQueryMethod(CtClass cc) throws Exception {
|
||||
// CtClass[] params = new CtClass[1];
|
||||
// params[0] = classPool.getCtClass("java.lang.String");
|
||||
// CtMethod method = cc.getDeclaredMethod("executeQuery", params);
|
||||
//
|
||||
// StringBuilder sb = new StringBuilder();
|
||||
// sb.append("{");
|
||||
// sb.append(DatabaseRequestTracer.FQCN + ".putSqlQuery(" +
|
||||
// TomcatProfilerConstant.REQ_DATA_TYPE_DB_QUERY + ",$1);");
|
||||
// sb.append(DatabaseRequestTracer.FQCN + ".put(" +
|
||||
// TomcatProfilerConstant.REQ_DATA_TYPE_DB_EXECUTE_QUERY + ");");
|
||||
// sb.append("}");
|
||||
//
|
||||
// method.insertAfter(sb.toString());
|
||||
// }
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.profiler.modifier.db.mysql.interceptors;
|
||||
|
||||
import com.profiler.StopWatch;
|
||||
import com.profiler.context.Annotation;
|
||||
import com.profiler.context.Trace;
|
||||
import com.profiler.interceptor.StaticAroundInterceptor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
public class ExecuteQueryMethodInterceptor implements StaticAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void before(Object target, String className, String methodName, Object[] args) {
|
||||
try {
|
||||
System.out.println("ThreadID=" + Thread.currentThread().getId());
|
||||
|
||||
Trace.recordRpcName("mysql", "");
|
||||
|
||||
if (args.length > 0) {
|
||||
Trace.record("Query=" + args[0]);
|
||||
}
|
||||
|
||||
Trace.record(new Annotation.ClientSend());
|
||||
|
||||
StopWatch.start("ExecuteQueryMethodInterceptor");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(Object target, String className, String methodName, Object[] args, Object result) {
|
||||
Trace.record(new Annotation.ClientRecv(), StopWatch.stopAndGetElapsed("ExecuteQueryMethodInterceptor"));
|
||||
}
|
||||
}
|
||||
+9
-29
@@ -36,44 +36,24 @@ public class EntryPointStandardHostValveModifier extends AbstractModifier {
|
||||
if (logger.isLoggable(Level.INFO)) {
|
||||
logger.info("Modifing. " + javassistClassName);
|
||||
}
|
||||
addRequestTracerToCurrentClassLoader(classLoader);
|
||||
|
||||
System.out.println("\n\n\n\n\n\n");
|
||||
System.out.println("EntryPointStandardHostValveModifier=" + classLoader);
|
||||
System.out.println("EntryPointStandardHostValveModifier parent=" + classLoader.getParent());
|
||||
Interceptor interceptor = newInterceptor(classLoader, protectedDomain);
|
||||
if(interceptor == null) {
|
||||
return null;
|
||||
}
|
||||
System.out.println("\n\n\n\n\n\n");
|
||||
addRequiredCladdToCurrentClassLoader(classLoader);
|
||||
|
||||
this.byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
Interceptor interceptor = newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.tomcat.interceptors.InvokeMethodInterceptor");
|
||||
if (interceptor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
|
||||
classPool.insertClassPath(new ByteArrayClassPath(javassistClassName, classFileBuffer));
|
||||
|
||||
InstrumentClass aClass = this.byteCodeInstrumentor.getClass(javassistClassName);
|
||||
aClass.addInterceptor("invoke", new String[] { "org.apache.catalina.connector.Request", "org.apache.catalina.connector.Response" }, interceptor);
|
||||
InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
|
||||
aClass.addInterceptor("invoke", new String[] { "org.apache.catalina.connector.Request", "org.apache.catalina.connector.Response" }, interceptor);
|
||||
|
||||
return aClass.toBytecode();
|
||||
}
|
||||
|
||||
private Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain) {
|
||||
Class aClass = this.byteCodeInstrumentor.defineClass(classLoader, "com.profiler.modifier.tomcat.InvokeMethodInterceptor", protectedDomain);
|
||||
try {
|
||||
return (Interceptor)aClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
if (logger.isLoggable(Level.WARNING)) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addRequestTracerToCurrentClassLoader(ClassLoader classLoader) {
|
||||
private void addRequiredCladdToCurrentClassLoader(ClassLoader classLoader) {
|
||||
try {
|
||||
classLoader.loadClass(RequestTracer.FQCN);
|
||||
classLoader.loadClass(CLASS_NAME_REQUEST_THRIFT_DTO);
|
||||
|
||||
Reference in New Issue
Block a user