[강운덕] [LUCYSUS-1744] agent의 classLoader에서 slf4j logger를 로드하는 코드 개발.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@1369 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Woonduk Kang
2013-03-29 04:39:25 +00:00
parent 746573a85a
commit c2f577d17f
9 changed files with 180 additions and 42 deletions
@@ -1,9 +1,13 @@
package com.profiler;
import com.profiler.logging.LoggerBinder;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
/**
*
@@ -13,6 +17,7 @@ public class AgentClassLoader {
private URLClassLoader classLoader;
private String bootClass = "com.profiler.AgentBootStrap";
private String bootMethod = "boot";
private Object agentBootStrap;
public AgentClassLoader(URL[] urls) {
ClassLoader classLoader = AgentClassLoader.class.getClassLoader();
@@ -26,34 +31,69 @@ public class AgentClassLoader {
public void setBootMethod(String bootMethod) {
this.bootMethod = bootMethod;
}
public void test() {
URL resource = this.classLoader.getResource("/log4j.xml");
System.out.println("log4j.xml=" + resource);
URL resource1 = this.classLoader.getResource("/nhn_source/hippo_project/deploy/agent/agentlib/lib/log4j.xml");
System.out.println("log4j.xml=" + resource1);
URL[] aaa = this.classLoader.getURLs();
for (URL url : aaa) {
System.out.println("" + url);
}
URL resource2 = classLoader.getResource(".");
System.out.println("resource2:" + resource2);
try {
Enumeration<URL> resources = this.classLoader.getResources(".");
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
System.out.println("" + url);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void boot() {
try{
Class<?> bootStrap = this.classLoader.loadClass(bootClass);
Object agentBootStrap = bootStrap.newInstance();
Method bootMethod = bootStrap.getDeclaredMethod(this.bootMethod);
Thread currentThread = Thread.currentThread();
ClassLoader before = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(this.classLoader);
try {
bootMethod.invoke(agentBootStrap);
} finally {
currentThread.setContextClassLoader(before);
}
agentBootStrap = bootStrap.newInstance();
invoke(bootStrap, this.bootMethod);
} catch (ClassNotFoundException e) {
throw new RuntimeException("boot class not found. Caused:" + e.getMessage(), e);
} catch (NoSuchMethodException e) {
throw new RuntimeException("boot method not found. Caused:" + e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new RuntimeException(this.bootMethod + "() fail. Caused:" + e.getMessage(), e);
} catch (InstantiationException e) {
throw new RuntimeException("boot create fail. Caused:" + e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException("boot method invoke fail. Caused:" + e.getMessage(), e);
}
}
private Object invoke(Class<?> clazz, String method) {
Method bootMethod = null;
try {
bootMethod = clazz.getDeclaredMethod(method);
} catch (NoSuchMethodException e) {
throw new RuntimeException("boot method not found. Caused:" + e.getMessage(), e);
}
final Thread currentThread = Thread.currentThread();
ClassLoader before = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(this.classLoader);
try {
return bootMethod.invoke(agentBootStrap);
} catch (InvocationTargetException e) {
throw new RuntimeException(this.bootMethod + "() fail. Caused:" + e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException("boot method invoke fail. Caused:" + e.getMessage(), e);
}
finally {
currentThread.setContextClassLoader(before);
}
}
public LoggerBinder initializeLoggerBinder() {
return (LoggerBinder) invoke(agentBootStrap.getClass(), "initializeLoggerBinder");
}
}
@@ -29,15 +29,25 @@ public class ClassPathResolver {
private String agentJarFullPath;
private String agentDirPath;
private Pattern agentPattern;
private List<String> fileExtensionList;
public ClassPathResolver() {
this.classPath = getClassPathFromSystemProperty();
this.agentPattern = DEFAULT_AGENT_PATTERN;
this(getClassPathFromSystemProperty());
}
public ClassPathResolver(String classPath) {
this.classPath = classPath;
this.agentPattern = DEFAULT_AGENT_PATTERN;
this.fileExtensionList = getDefaultFileExtensionList();
}
public List<String> getDefaultFileExtensionList() {
List<String> extensionList = new ArrayList<String>();
extensionList.add("jar");
extensionList.add("xml");
extensionList.add("properties");
return extensionList;
}
public ClassPathResolver(String classPath, String agentPattern) {
@@ -53,7 +63,7 @@ public class ClassPathResolver {
this.classPath = getClassPathFromSystemProperty();
}
public String getClassPathFromSystemProperty() {
public static String getClassPathFromSystemProperty() {
return System.getProperty("java.class.path");
}
@@ -119,6 +129,9 @@ public class ClassPathResolver {
jarURLList.add(url);
}
}
// agentDir 패스도 넣어야 xml을 찾을 때 해당 패스에서 찾음.
URL agentDirUri = toURI(new File(agentLibPath));
jarURLList.add(agentDirUri);
return jarURLList;
}
@@ -136,7 +149,13 @@ public class ClassPathResolver {
return libDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().lastIndexOf(".jar") != -1;
String path = pathname.getName();
for (String extension : fileExtensionList) {
if (path.lastIndexOf("." + extension) != -1) {
return true;
}
}
return false;
}
});
}
+10 -3
View File
@@ -14,6 +14,8 @@ import java.util.logging.Logger;
import com.profiler.common.ServiceType;
import com.profiler.config.ProfilerConfig;
import com.profiler.logging.LoggerBinder;
import com.profiler.logging.LoggerFactory;
import com.profiler.interceptor.bci.ByteCodeInstrumentor;
import com.profiler.interceptor.bci.JavaAssistByteCodeInstrumentor;
import com.profiler.modifier.DefaultModifierRegistry;
@@ -53,11 +55,16 @@ public class TomcatProfiler implements ClassFileTransformer {
List<URL> libUrlList = resolveLib(classPathResolver);
AgentClassLoader agentClassLoader = new AgentClassLoader(libUrlList.toArray(new URL[libUrlList.size()]));
agentClassLoader.setBootClass("com.profiler.boot.BootClassTest");
// agentClassLoader.test();
try {
agentClassLoader.boot();
LoggerBinder loggerBinder = agentClassLoader.initializeLoggerBinder();
loggerBinder.getLogger("LoggerFactory initialize start");
LoggerFactory.initialize(loggerBinder);
com.profiler.logging.Logger tomcatLogger = LoggerFactory.getLogger(TomcatProfiler.class);
tomcatLogger.info("LoggerFactory initialize end");
} catch (Exception e) {
logger.info("test error");
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
logger.log(Level.INFO, "boot class not found", e);
}
try {
@@ -86,7 +93,7 @@ public class TomcatProfiler implements ClassFileTransformer {
return profilerConfig;
}
private static List<URL> resolveLib(ClassPathResolver classPathResolver) {
private static List<URL> resolveLib(ClassPathResolver classPathResolver) {
String agentJarFullPath = classPathResolver.getAgentJarFullPath();
logger.info("agentJarPath:" + agentJarFullPath);
@@ -0,0 +1,13 @@
package com.profiler.logging;
/**
*
*/
public interface Logger {
public void info(String msg);
public void info(String format, Object arg);
}
@@ -0,0 +1,10 @@
package com.profiler.logging;
import com.profiler.logging.Logger;
/**
*
*/
public interface LoggerBinder {
Logger getLogger(String name);
}
@@ -0,0 +1,24 @@
package com.profiler.logging;
/**
*
*/
public final class LoggerFactory {
private static LoggerBinder loggerBinder;
public static void initialize(LoggerBinder loggerBinder) {
if (LoggerFactory.loggerBinder == null) {
System.out.println("set logger binder-------------");
LoggerFactory.loggerBinder = loggerBinder;
}
}
public static Logger getLogger(String name) {
return loggerBinder.getLogger(name);
}
public static Logger getLogger(Class name) {
return getLogger(name.getName());
}
}
@@ -7,7 +7,6 @@ import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -45,7 +44,6 @@ public class UdpDataSender implements DataSender, Runnable {
private HeaderTBaseSerializer serializer = new HeaderTBaseSerializer();
private AtomicBoolean allowInput = new AtomicBoolean();
private CountDownLatch shutdownLatch = new CountDownLatch(1);
public UdpDataSender(String host, int port) {
Assert.notNull(host, "host must not be null");
@@ -115,8 +113,9 @@ public class UdpDataSender implements DataSender, Runnable {
}
try {
shutdownLatch.await(5, TimeUnit.SECONDS);
ioThread.join(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
logger.info("UdpDataSender stopped incompletely.");
}
@@ -132,7 +131,6 @@ public class UdpDataSender implements DataSender, Runnable {
drain: while (true) {
try {
if (!allowInput.get() && isEmpty()) {
shutdownLatch.countDown();
break;
}
@@ -144,7 +142,6 @@ public class UdpDataSender implements DataSender, Runnable {
while (true) {
if (!allowInput.get() && isEmpty()) {
shutdownLatch.countDown();
break;
}
@@ -155,7 +152,7 @@ public class UdpDataSender implements DataSender, Runnable {
}
}
} catch (Throwable th) {
logger.log(Level.WARNING, "Unexpected Error Cause:" + th.getMessage(), th);
logger.log(Level.WARNING, "Unexpected Error. Cause:" + th.getMessage(), th);
}
}
}
@@ -165,7 +162,7 @@ public class UdpDataSender implements DataSender, Runnable {
try {
sendPacket(dto);
} catch (Throwable th) {
logger.log(Level.WARNING, "Unexpected Error Cause:" + th.getMessage(), th);
logger.log(Level.WARNING, "Unexpected Error. Cause:" + th.getMessage(), th);
}
}
}