[강운덕] [LUCYSUS-1744] modifier 등록 지점 구현.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@466 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Woonduk Kang
2012-07-20 10:14:36 +00:00
parent 79bce2294f
commit bdd316fd00
4 changed files with 197 additions and 93 deletions
+29 -6
View File
@@ -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) {
}
}
@@ -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.");
}
}
@@ -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<String, Modifier> registry = new HashMap<String, Modifier>();
private List<String> packageIncludeFilters = new ArrayList<String>();
@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<String, Modifier> 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() {
}
}
@@ -0,0 +1,6 @@
package com.profiler.modifier;
public interface ModifierRegistry {
Modifier findModifier(String className);
}