From bdd316fd0039f511f5f2daf7aa685d69a38856da Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Fri, 20 Jul 2012 10:14:36 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[LUCYSUS-1744]?= =?UTF-8?q?=20modifier=20=EB=93=B1=EB=A1=9D=20=EC=A7=80=EC=A0=90=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84.?= 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@466 84d0f5b1-2673-498c-a247-62c4ff18d310 --- .../java/com/profiler/TomcatProfiler.java | 35 +++- .../profiler/config/TomcatProfilerConfig.java | 195 ++++++++++-------- .../modifier/DefaultModifierRegistry.java | 54 +++++ .../profiler/modifier/ModifierRegistry.java | 6 + 4 files changed, 197 insertions(+), 93 deletions(-) create mode 100644 src/main/java/com/profiler/modifier/DefaultModifierRegistry.java create mode 100644 src/main/java/com/profiler/modifier/ModifierRegistry.java diff --git a/src/main/java/com/profiler/TomcatProfiler.java b/src/main/java/com/profiler/TomcatProfiler.java index 09877895a..135d3539c 100644 --- a/src/main/java/com/profiler/TomcatProfiler.java +++ b/src/main/java/com/profiler/TomcatProfiler.java @@ -7,7 +7,9 @@ import java.net.URL; import java.net.URLClassLoader; import java.security.ProtectionDomain; +import com.profiler.modifier.DefaultModifierRegistry; import com.profiler.modifier.Modifier; +import com.profiler.modifier.ModifierRegistry; import javassist.ClassPool; import javassist.NotFoundException; @@ -42,19 +44,34 @@ public class TomcatProfiler implements ClassFileTransformer { private Instrumentation instrumentation; private ClassPool classPool; - + private final ModifierRegistry modifierRepository; + private TomcatProfilerConfig tomcatProfilerConfig; public static void premain(String agentArgs, Instrumentation inst) { - new TomcatProfiler(agentArgs, inst); + TomcatProfilerConfig tomcatProfilerConfig = TomcatProfilerConfig.readConfigFile(); + new TomcatProfiler(agentArgs, inst, tomcatProfilerConfig); } - public TomcatProfiler(String agentArgs, Instrumentation inst) { + public TomcatProfiler(String agentArgs, Instrumentation inst, TomcatProfilerConfig tomcatProfilerConfig) { this.agentArgString = agentArgs; this.instrumentation = inst; this.instrumentation.addTransformer(this); this.classPool = createClassPool(); + this.modifierRepository = createModifierRegistry(tomcatProfilerConfig); + this.tomcatProfilerConfig = tomcatProfilerConfig; + + } + private ModifierRegistry createModifierRegistry(TomcatProfilerConfig tomcatProfilerConfig) { + DefaultModifierRegistry modifierRepository = new DefaultModifierRegistry(); + modifierRepository.addTomcatModifier(); + if(tomcatProfilerConfig.enableJdbcProfile()) { + modifierRepository.addJdbcModifier(); + } + return modifierRepository; + } + private ClassPool createClassPool() { ClassPool classPool = new ClassPool(null); classPool.appendSystemPath(); @@ -76,7 +93,13 @@ public class TomcatProfiler implements ClassFileTransformer { @Override public byte[] transform(ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classFileBuffer) throws IllegalClassFormatException { - if (className.startsWith("org/apache/catalina")) { + Modifier findModifier = this.modifierRepository.findModifier(className); + if(findModifier != null) { + String javassistClassName = className.replace('/', '.'); + return findModifier.modify(classPool, classLoader, javassistClassName, classFileBuffer); + } + + if (className.startsWith("org/apache/catalina")) { String javassistClassName = className.replace('/', '.'); if (javassistClassName.equals("org.apache.catalina.core.StandardHostValve")) { // Add code to monitor Request and Response @@ -99,7 +122,7 @@ public class TomcatProfiler implements ClassFileTransformer { } } // #### If JDBC_PROFILE is true, SQL data will be collected - if (TomcatProfilerConfig.JDBC_PROFILE) { + if (tomcatProfilerConfig.enableJdbcProfile()) { if (className.startsWith("com/mysql/jdbc")) { // MySQL !!!!!!!!!! String javassistClassName = className.replace('/', '.'); @@ -256,7 +279,7 @@ public class TomcatProfiler implements ClassFileTransformer { try { classPool.appendClassPath(filePath); // log("Loaded "+filePath+" library."); - } catch (Exception e) { + } catch (NotFoundException e) { } } diff --git a/src/main/java/com/profiler/config/TomcatProfilerConfig.java b/src/main/java/com/profiler/config/TomcatProfilerConfig.java index 277ea4a3f..edd81357b 100644 --- a/src/main/java/com/profiler/config/TomcatProfilerConfig.java +++ b/src/main/java/com/profiler/config/TomcatProfilerConfig.java @@ -2,110 +2,131 @@ package com.profiler.config; import java.io.FileNotFoundException; import java.io.FileReader; +import java.io.IOException; import java.util.Properties; +import com.profiler.TomcatProfiler; import com.profiler.logging.LogLevel; import com.profiler.logging.Logger; public class TomcatProfilerConfig { - private static final Logger logger = Logger.getLogger(TomcatProfilerConfig.class); + private static final Logger logger = Logger.getLogger(TomcatProfilerConfig.class); - public static String SERVER_IP = "127.0.0.1"; + public static String SERVER_IP = "127.0.0.1"; - public static int AGENT_TCP_LISTEN_PORT = 9990; - public static int SERVER_TCP_LISTEN_PORT = 9991; - public static int REQUEST_TRANSACTION_DATA_LISTEN_PORT = 9995; - public static int REQUEST_DATA_LISTEN_PORT = 9996; - public static int JVM_DATA_LISTEN_PORT = 9997; + public static int AGENT_TCP_LISTEN_PORT = 9990; + public static int SERVER_TCP_LISTEN_PORT = 9991; + public static int REQUEST_TRANSACTION_DATA_LISTEN_PORT = 9995; + public static int REQUEST_DATA_LISTEN_PORT = 9996; + public static int JVM_DATA_LISTEN_PORT = 9997; - public static long JVM_STAT_GAP = 5000L; - public static long SERVER_CONNECT_RETRY_GAP = 1000L; + public static long JVM_STAT_GAP = 5000L; + public static long SERVER_CONNECT_RETRY_GAP = 1000L; - public static LogLevel LOG_LEVEL = LogLevel.INFO; + public static LogLevel LOG_LEVEL = LogLevel.INFO; - /** - * If sql query count is over 10000 it consumes Memory. So sqlHashSet uses - * CopyOnWriteArraySet. It is slow, but it is stable. Default set is false - * and it uses HashSet. - */ - public static boolean QUERY_COUNT_OVER_10000 = false; - public static boolean JDBC_PROFILE = true; + /** + * If sql query count is over 10000 it consumes Memory. So sqlHashSet uses + * CopyOnWriteArraySet. It is slow, but it is stable. Default set is false + * and it uses HashSet. + */ + public static boolean QUERY_COUNT_OVER_10000 = false; - static { - readConfigFile(); - } + private boolean JDBC_PROFILE = true; - public static void readConfigFile() { - String hippoConfigFileName = System.getProperty("hippo.config"); + public static TomcatProfilerConfig readConfigFile() { + TomcatProfilerConfig config = new TomcatProfilerConfig(); - if (hippoConfigFileName != null) { - Properties prop = new Properties(); - try { - FileReader reader = new FileReader(hippoConfigFileName); - prop.load(reader); - reader.close(); - setPropertyValues(prop); - } catch (FileNotFoundException fnfe) { - logger.error("%s file is not exists. Please check configuration.", hippoConfigFileName); - } catch (Exception e) { - logger.fatal(e.getMessage()); - } - } else { - logger.warn("hippo.config property is not set. Using default values"); - } - } + String hippoConfigFileName = System.getProperty("hippo.config"); + if (hippoConfigFileName == null) { + logger.warn("hippo.config property is not set. Using default values"); + return config; + } - private static void setPropertyValues(Properties prop) { - // TODO : use Properties defaultvalue instead of using temp variable. + try { + Properties properties = readProperties(hippoConfigFileName); + setPropertyValues(config, properties); + return config; + } catch (FileNotFoundException fnfe) { + logger.error("%s file is not exists. Please check configuration.", hippoConfigFileName); + } catch (Exception e) { + logger.fatal(e.getMessage()); + } + return config; + } - Object temp = null; + private static Properties readProperties(String propertyName) throws FileNotFoundException, IOException { + FileReader reader = null; + try { + Properties prop = new Properties(); + reader = new FileReader(propertyName); + prop.load(reader); + return prop; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } + } - if ((temp = prop.get("SERVER_IP")) != null) { - SERVER_IP = temp.toString(); - logger.info("SERVER_IP=%s", SERVER_IP); - } - if ((temp = prop.get("AGENT_TCP_LISTEN_PORT")) != null) { - AGENT_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); - logger.info("AGENT_TCP_LISTEN_PORT=%d", AGENT_TCP_LISTEN_PORT); - } - if ((temp = prop.get("SERVER_TCP_LISTEN_PORT")) != null) { - SERVER_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); - logger.info("SERVER_TCP_LISTEN_PORT=%d", SERVER_TCP_LISTEN_PORT); - } - if ((temp = prop.get("REQUEST_TRANSACTION_DATA_LISTEN_PORT")) != null) { - REQUEST_TRANSACTION_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); - logger.info("REQUEST_TRANSACTION_DATA_LISTEN_PORT=%d", REQUEST_TRANSACTION_DATA_LISTEN_PORT); - } - if ((temp = prop.get("REQUEST_DATA_LISTEN_PORT")) != null) { - REQUEST_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); - logger.info("REQUEST_DATA_LISTEN_PORT=%d", REQUEST_DATA_LISTEN_PORT); - } - if ((temp = prop.get("JVM_DATA_LISTEN_PORT")) != null) { - JVM_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); - logger.info("JVM_DATA_LISTEN_PORT=%d", JVM_DATA_LISTEN_PORT); - } - if ((temp = prop.get("JVM_STAT_GAP")) != null) { - JVM_STAT_GAP = Long.parseLong(temp.toString()); - logger.info("JVM_STAT_GAP=%d", JVM_STAT_GAP); - } - if ((temp = prop.get("SERVER_CONNECT_RETRY_GAP")) != null) { - SERVER_CONNECT_RETRY_GAP = Long.parseLong(temp.toString()); - logger.info("SERVER_CONNECT_RETRY_GAP=%d", SERVER_CONNECT_RETRY_GAP); - } - if ((temp = prop.get("QUERY_COUNT_OVER_10000")) != null) { - QUERY_COUNT_OVER_10000 = Boolean.parseBoolean(temp.toString()); - logger.info("QUERY_COUNT_OVER_10000=%s", QUERY_COUNT_OVER_10000); - } - if ((temp = prop.get("JDBC_PROFILE")) != null) { - JDBC_PROFILE = Boolean.parseBoolean(temp.toString()); - logger.info("JDBC_PROFILE=%s", JDBC_PROFILE); - } - if ((temp = prop.get("LOG_LEVEL")) != null) { - LOG_LEVEL = LogLevel.valueOf(temp.toString()); - logger.info("LOG_LEVEL=%s", LOG_LEVEL); - } + public boolean enableJdbcProfile() { + return JDBC_PROFILE; + } - logger.info("configuration loaded successfully."); - } + private static void setPropertyValues(TomcatProfilerConfig config, Properties prop) { + // TODO : use Properties defaultvalue instead of using temp variable. + + Object temp = null; + + if ((temp = prop.get("SERVER_IP")) != null) { + config.SERVER_IP = temp.toString(); + logger.info("SERVER_IP=%s", SERVER_IP); + } + if ((temp = prop.get("AGENT_TCP_LISTEN_PORT")) != null) { + config.AGENT_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); + logger.info("AGENT_TCP_LISTEN_PORT=%d", AGENT_TCP_LISTEN_PORT); + } + if ((temp = prop.get("SERVER_TCP_LISTEN_PORT")) != null) { + config.SERVER_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); + logger.info("SERVER_TCP_LISTEN_PORT=%d", SERVER_TCP_LISTEN_PORT); + } + if ((temp = prop.get("REQUEST_TRANSACTION_DATA_LISTEN_PORT")) != null) { + config.REQUEST_TRANSACTION_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); + logger.info("REQUEST_TRANSACTION_DATA_LISTEN_PORT=%d", REQUEST_TRANSACTION_DATA_LISTEN_PORT); + } + if ((temp = prop.get("REQUEST_DATA_LISTEN_PORT")) != null) { + config.REQUEST_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); + logger.info("REQUEST_DATA_LISTEN_PORT=%d", REQUEST_DATA_LISTEN_PORT); + } + if ((temp = prop.get("JVM_DATA_LISTEN_PORT")) != null) { + config.JVM_DATA_LISTEN_PORT = Integer.parseInt(temp.toString()); + logger.info("JVM_DATA_LISTEN_PORT=%d", JVM_DATA_LISTEN_PORT); + } + if ((temp = prop.get("JVM_STAT_GAP")) != null) { + config.JVM_STAT_GAP = Long.parseLong(temp.toString()); + logger.info("JVM_STAT_GAP=%d", JVM_STAT_GAP); + } + if ((temp = prop.get("SERVER_CONNECT_RETRY_GAP")) != null) { + config.SERVER_CONNECT_RETRY_GAP = Long.parseLong(temp.toString()); + logger.info("SERVER_CONNECT_RETRY_GAP=%d", SERVER_CONNECT_RETRY_GAP); + } + if ((temp = prop.get("QUERY_COUNT_OVER_10000")) != null) { + config.QUERY_COUNT_OVER_10000 = Boolean.parseBoolean(temp.toString()); + logger.info("QUERY_COUNT_OVER_10000=%s", QUERY_COUNT_OVER_10000); + } + if ((temp = prop.get("JDBC_PROFILE")) != null) { + config.JDBC_PROFILE = Boolean.parseBoolean(temp.toString()); + logger.info("JDBC_PROFILE=%s", config.JDBC_PROFILE); + } + if ((temp = prop.get("LOG_LEVEL")) != null) { + config.LOG_LEVEL = LogLevel.valueOf(temp.toString()); + logger.info("LOG_LEVEL=%s", LOG_LEVEL); + } + + logger.info("configuration loaded successfully."); + } } diff --git a/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java new file mode 100644 index 000000000..c82901e10 --- /dev/null +++ b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java @@ -0,0 +1,54 @@ +package com.profiler.modifier; + +import com.profiler.modifier.tomcat.EntryPointStandardHostValveModifier; +import com.profiler.modifier.tomcat.TomcatConnectorModifier; +import com.profiler.modifier.tomcat.TomcatStandardServiceModifier; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DefaultModifierRegistry implements ModifierRegistry { + // TODO 혹시 동시성을 고려 해야 되는지 검토. + private Map registry = new HashMap(); + + + private List packageIncludeFilters = new ArrayList(); + + @Override + public Modifier findModifier(String className) { + if(!findPackage(className)) { + return null; + } + return registry.get(className); + } + + private boolean findPackage(String className) { + for(String filter : packageIncludeFilters) { + if(filter.equals(className)) { + return true; + } + } + return false; + } + + public void addTomcatModifier() { + packageIncludeFilters.add("org/apache/catalina"); + + Map registry = this.registry; + Modifier entryPointStandardHostValveModifier = new EntryPointStandardHostValveModifier(); + registry.put("org/apache/catalina/core/StandardHostValve", entryPointStandardHostValveModifier); + + Modifier tomcatStandardServiceModifier = new TomcatStandardServiceModifier(); + registry.put("org/apache/catalina/core/StandardService", tomcatStandardServiceModifier); + + Modifier tomcatConnectorModifier = new TomcatConnectorModifier(); + registry.put("org/apache/catalina/connector/Connector", tomcatConnectorModifier); + } + + public void addJdbcModifier() { + + + } +} diff --git a/src/main/java/com/profiler/modifier/ModifierRegistry.java b/src/main/java/com/profiler/modifier/ModifierRegistry.java new file mode 100644 index 000000000..36333586f --- /dev/null +++ b/src/main/java/com/profiler/modifier/ModifierRegistry.java @@ -0,0 +1,6 @@ +package com.profiler.modifier; + +public interface ModifierRegistry { + + Modifier findModifier(String className); +}