From 34dd7ef06d6f3adcd9452f56f4e156b897235b00 Mon Sep 17 00:00:00 2001 From: Chisu Yu Date: Wed, 29 Aug 2012 06:04:59 +0000 Subject: [PATCH] =?UTF-8?q?[=EC=9C=A0=EC=B9=98=EC=88=98]=20[NOBTS]=20add?= =?UTF-8?q?=20mysql=20interceptor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@556 84d0f5b1-2673-498c-a247-62c4ff18d310 --- src/main/java/com/profiler/StopWatch.java | 31 ++++++ src/main/java/com/profiler/context/Trace.java | 4 +- .../context/tracer/HippoAnnotation.java | 4 +- .../profiler/modifier/AbstractModifier.java | 48 +++++---- .../mysql/MySQLPreparedStatementModifier.java | 44 +++++--- .../db/mysql/MySQLStatementModifier.java | 102 ++++++++++-------- .../ExecuteQueryMethodInterceptor.java | 38 +++++++ .../EntryPointStandardHostValveModifier.java | 38 ++----- 8 files changed, 203 insertions(+), 106 deletions(-) create mode 100644 src/main/java/com/profiler/StopWatch.java create mode 100644 src/main/java/com/profiler/modifier/db/mysql/interceptors/ExecuteQueryMethodInterceptor.java diff --git a/src/main/java/com/profiler/StopWatch.java b/src/main/java/com/profiler/StopWatch.java new file mode 100644 index 000000000..7cdc6faae --- /dev/null +++ b/src/main/java/com/profiler/StopWatch.java @@ -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> local = new NamedThreadLocal>("StopWatch"); + + public static void start(String name) { + Map map = local.get(); + if (map == null) { + map = new HashMap(1); + map.put(name, System.currentTimeMillis()); + local.set(map); + } else { + map.put(name, System.currentTimeMillis()); + } + } + + public static long stopAndGetElapsed(String name) { + Map map = local.get(); + if (map == null) { + throw new IllegalStateException("Stopwatch is not started."); + } else { + return System.currentTimeMillis() - map.get(name); + } + } +} diff --git a/src/main/java/com/profiler/context/Trace.java b/src/main/java/com/profiler/context/Trace.java index 8260d3453..19714222d 100644 --- a/src/main/java/com/profiler/context/Trace.java +++ b/src/main/java/com/profiler/context/Trace.java @@ -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; diff --git a/src/main/java/com/profiler/context/tracer/HippoAnnotation.java b/src/main/java/com/profiler/context/tracer/HippoAnnotation.java index 8090b4fb9..55d3b7829 100644 --- a/src/main/java/com/profiler/context/tracer/HippoAnnotation.java +++ b/src/main/java/com/profiler/context/tracer/HippoAnnotation.java @@ -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(); diff --git a/src/main/java/com/profiler/modifier/AbstractModifier.java b/src/main/java/com/profiler/modifier/AbstractModifier.java index cb7453ca0..4431aa777 100644 --- a/src/main/java/com/profiler/modifier/AbstractModifier.java +++ b/src/main/java/com/profiler/modifier/AbstractModifier.java @@ -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; + } } diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java index 35c1a1adc..be197d12e 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java @@ -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 + "); }"); } } diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java index 4c2d5cd37..4e9816fc4 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java @@ -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()); + // } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/db/mysql/interceptors/ExecuteQueryMethodInterceptor.java b/src/main/java/com/profiler/modifier/db/mysql/interceptors/ExecuteQueryMethodInterceptor.java new file mode 100644 index 000000000..2308ae598 --- /dev/null +++ b/src/main/java/com/profiler/modifier/db/mysql/interceptors/ExecuteQueryMethodInterceptor.java @@ -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")); + } +} diff --git a/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java b/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java index 721088de9..99ea42a27 100644 --- a/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/EntryPointStandardHostValveModifier.java @@ -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);