diff --git a/src/main/java/com/profiler/Agent.java b/src/main/java/com/profiler/Agent.java index 7d04fc1d9..2c213e8a1 100644 --- a/src/main/java/com/profiler/Agent.java +++ b/src/main/java/com/profiler/Agent.java @@ -8,31 +8,37 @@ import java.util.logging.Logger; import com.profiler.common.dto.thrift.AgentInfo; import com.profiler.common.mapping.ApiMappingTable; import com.profiler.common.util.SpanUtils; +import com.profiler.config.ProfilerConfig; +import com.profiler.context.BypassStorageFactory; +import com.profiler.context.TimeBaseStorageFactory; import com.profiler.context.TraceContext; import com.profiler.sender.DataSender; import com.profiler.sender.UdpDataSender; +import com.profiler.util.Assert; import com.profiler.util.NetworkUtils; public class Agent { - public static final String FQCN = Agent.class.getName(); - private static final Logger logger = Logger.getLogger(Agent.class.getName()); private volatile boolean alive = false; + private final ProfilerConfig profilerConfig; private final ServerInfo serverInfo; private final SystemMonitor systemMonitor; + + private TraceContext traceContext; private DataSender dataSender; private final String agentId; private final String nodeName; private final String applicationName; -// private boolean validate = true; - private Agent() { + public Agent(ProfilerConfig profilerConfig) { + Assert.notNull(profilerConfig, "profilerConfig must not be null"); + + this.profilerConfig = profilerConfig; this.serverInfo = new ServerInfo(); - this.systemMonitor = new SystemMonitor(); // this.agentId = getId("hippo.agentId", "UnkonwnAgentId"); // 일단 임시로 호환성을 위해 agentid에 머신name을넣도록 하자 @@ -41,17 +47,37 @@ public class Agent { this.nodeName = getId("hippo.nodeName", machineName); this.applicationName = getId("hippo.applicationName", "UnknownApplicationName"); - // 일단 임시로 datasender와 , tracecontext 타이밍 변경. 추후 다시 조정해야 될듯. - this.dataSender = UdpDataSender.getInstance(); - // TraceContext의 생명주기 관리 방안이 없는지 강구. - TraceContext traceContext = TraceContext.getTraceContext(); - traceContext.setDataSender(this.dataSender); - systemMonitor.setDataSender(dataSender); + this.dataSender = createDataSender(); + + initializeTraceContext(); + + this.systemMonitor = new SystemMonitor(this.traceContext); + this.systemMonitor.setDataSender(dataSender); // 매핑 테이블 초기화를 위해 엑세스 - ApiMappingTable.findApiId("test", null, null); + SingletonHolder.INSTANCE = this; + } + + private void initializeTraceContext() { + + this.traceContext = TraceContext.getTraceContext(); + this.traceContext.setDataSender(this.dataSender); + + this.traceContext.setAgentId(this.agentId); + this.traceContext.setApplicationId(this.applicationName); + + if (profilerConfig.isSamplingElapsedTimeBaseEnable()) { + TimeBaseStorageFactory timeBaseStorageFactory = new TimeBaseStorageFactory(this.dataSender, this.profilerConfig); + this.traceContext.setStorageFactory(timeBaseStorageFactory); + } else { + this.traceContext.setStorageFactory(new BypassStorageFactory(dataSender)); + } + } + + private UdpDataSender createDataSender() { + return new UdpDataSender(this.profilerConfig.getCollectorServerIp(), this.profilerConfig.getCollectorServerPort()); } private String getId(String key, String defaultValue) { @@ -66,8 +92,8 @@ public class Agent { if (bytes.length > SpanUtils.AGENT_NAME_LIMIT) { logger.warning(idName + " is too long(1~24). value=" + id); } - // validate = false; - // TODO 이거 후처리를 어떻게 해야 될지. agent를 시작 시키지 않아야 될거 같은데. lifecycle이 이쪽저쪽에 퍼져 있어서 일관된 stop에 문제가 있음.. + // validate = false; + // TODO 이거 후처리를 어떻게 해야 될지. agent를 시작 시키지 않아야 될거 같은데. lifecycle이 이쪽저쪽에 퍼져 있어서 일관된 stop에 문제가 있음.. } catch (UnsupportedEncodingException e) { logger.log(Level.WARNING, "invalid agentId. Cause:" + e.getMessage(), e); } @@ -75,9 +101,10 @@ public class Agent { } private static class SingletonHolder { - public static final Agent INSTANCE = new Agent(); + public static Agent INSTANCE; } + @Deprecated public static Agent getInstance() { return SingletonHolder.INSTANCE; } @@ -102,6 +129,9 @@ public class Agent { return applicationName; } + public TraceContext getTraceContext() { + return traceContext; + } /** * HIPPO 서버로 WAS정보를 전송한다. @@ -157,11 +187,4 @@ public class Agent { this.dataSender.stop(); } - public static void startAgent() { - Agent.getInstance().start(); - } - - public static void stopAgent() { - Agent.getInstance().stop(); - } } diff --git a/src/main/java/com/profiler/LifeCycleEventListener.java b/src/main/java/com/profiler/LifeCycleEventListener.java index 709de20f2..ff5462542 100644 --- a/src/main/java/com/profiler/LifeCycleEventListener.java +++ b/src/main/java/com/profiler/LifeCycleEventListener.java @@ -1,29 +1,41 @@ package com.profiler; +import com.profiler.util.Assert; + import java.util.logging.Logger; public class LifeCycleEventListener { private final static Logger logger = Logger.getLogger(LifeCycleEventListener.class.getName()); - private static boolean started = false; + private Agent agent; + private boolean started = false; + + public LifeCycleEventListener(Agent agent) { + Assert.notNull(agent, "agent must not be null"); + this.agent = agent; + } + + public synchronized void start() { + logger.info("LifeCycleEventListener start"); - public synchronized static void start() { if (started) { logger.info("already started"); return; } - Agent.startAgent(); + agent.start(); started = true; } - public synchronized static void stop() { + public synchronized void stop() { + logger.info("LifeCycleEventListener stop"); + if (!started) { logger.info("already stopped"); return; } started = false; - Agent.stopAgent(); + agent.stop(); } } diff --git a/src/main/java/com/profiler/SystemMonitor.java b/src/main/java/com/profiler/SystemMonitor.java index f27efb59c..55be0f504 100644 --- a/src/main/java/com/profiler/SystemMonitor.java +++ b/src/main/java/com/profiler/SystemMonitor.java @@ -3,6 +3,7 @@ package com.profiler; import com.profiler.common.dto.thrift.JVMInfoThriftDTO; import com.profiler.context.TraceContext; import com.profiler.sender.DataSender; +import com.profiler.util.Assert; import com.sun.management.OperatingSystemMXBean; import java.io.IOException; @@ -41,8 +42,11 @@ public class SystemMonitor { }); private DataSender dataSender; + private TraceContext traceContext; - public SystemMonitor() { + public SystemMonitor(TraceContext traceContext) { + Assert.notNull(traceContext, "traceContext must not be null"); + this.traceContext = traceContext; } public void setDataSender(DataSender dataSender) { @@ -51,7 +55,7 @@ public class SystemMonitor { public void start() { logger.info("Starting system monitor."); - executor.scheduleAtFixedRate(new Worker(dataSender), 5, 5, TimeUnit.SECONDS); + executor.scheduleAtFixedRate(new Worker(dataSender, traceContext), 5, 5, TimeUnit.SECONDS); } public void stop() { @@ -62,18 +66,19 @@ public class SystemMonitor { private static class Worker implements Runnable { private DataSender dataSender; + private TraceContext traceContext; - public Worker(DataSender dataSender) { + public Worker(DataSender dataSender, TraceContext traceContext) { this.dataSender = dataSender; + this.traceContext = traceContext; } public void run() { try { JVMInfoThriftDTO jvmInfo = new JVMInfoThriftDTO(); - jvmInfo.setAgentId(Agent.getInstance().getAgentId()); + jvmInfo.setAgentId(traceContext.getAgentId()); jvmInfo.setDataTime(System.currentTimeMillis()); - TraceContext traceContext = TraceContext.getTraceContext(); activeThread(traceContext, jvmInfo); setGCState(jvmInfo); diff --git a/src/main/java/com/profiler/TomcatProfiler.java b/src/main/java/com/profiler/TomcatProfiler.java index eaba27e3c..cac4f688f 100644 --- a/src/main/java/com/profiler/TomcatProfiler.java +++ b/src/main/java/com/profiler/TomcatProfiler.java @@ -19,13 +19,17 @@ public class TomcatProfiler implements ClassFileTransformer { private static final Logger logger = Logger.getLogger(TomcatProfiler.class.getName()); private String agentArgString = ""; + private Instrumentation instrumentation; - private ByteCodeInstrumentor byteCodeInstrumentor; + private final ByteCodeInstrumentor byteCodeInstrumentor; private final ModifierRegistry modifierRepository; - private ProfilerConfig profilerConfig; - public static void premain(String agentArgs, Instrumentation inst) { + private final ProfilerConfig profilerConfig; + private final Agent agent; + + + public static void premain(String agentArgs, Instrumentation instrumentation) { try { ProfilerConfig profilerConfig = new ProfilerConfig(); profilerConfig.readConfigFile(); @@ -33,26 +37,32 @@ public class TomcatProfiler implements ClassFileTransformer { logger.warning("Profiler Agent not started. PROFILE_ENABLE=" + profilerConfig.isProfileEnable()); return; } - new TomcatProfiler(agentArgs, inst, profilerConfig); + Agent agent = new Agent(profilerConfig); + new TomcatProfiler(agentArgs, instrumentation, agent, profilerConfig); } catch (Exception e) { logger.log(Level.SEVERE, "Profiler Agent start fail. Cause:" + e.getMessage(), e); } } - public TomcatProfiler(String agentArgs, Instrumentation inst, ProfilerConfig profilerConfig) { + public TomcatProfiler(String agentArgs, Instrumentation instrumentation, Agent agent, ProfilerConfig profilerConfig) { this.agentArgString = agentArgs; this.profilerConfig = profilerConfig; - this.instrumentation = inst; + this.agent = agent; + + this.instrumentation = instrumentation; this.instrumentation.addTransformer(this); + String[] paths = getTomcatlibPath(); this.byteCodeInstrumentor = new JavaAssistByteCodeInstrumentor(paths); - this.modifierRepository = createModifierRegistry(byteCodeInstrumentor); + + this.modifierRepository = createModifierRegistry(); } private String[] getTomcatlibPath() { String catalinaHome = System.getProperty("catalina.home"); if (catalinaHome == null) { + logger.info("CATALINA_HOME is null"); return null; } @@ -70,8 +80,8 @@ public class TomcatProfiler implements ClassFileTransformer { } } - private ModifierRegistry createModifierRegistry(ByteCodeInstrumentor byteCodeInstrumentor) { - DefaultModifierRegistry modifierRepository = new DefaultModifierRegistry(byteCodeInstrumentor, profilerConfig); + private ModifierRegistry createModifierRegistry() { + DefaultModifierRegistry modifierRepository = new DefaultModifierRegistry(byteCodeInstrumentor, agent, profilerConfig); modifierRepository.addTomcatModifier(); @@ -89,19 +99,19 @@ public class TomcatProfiler implements ClassFileTransformer { @Override public byte[] transform(ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classFileBuffer) throws IllegalClassFormatException { + // fast java class skip if (className.startsWith("java")) { if (className.startsWith("/", 4) || className.startsWith("x/", 4)) { return classFileBuffer; } } - if (logger.isLoggable(Level.FINE)) { - logger.fine("[transform] cl" + classLoader + " className:" + className); - } Modifier findModifier = this.modifierRepository.findModifier(className); if (findModifier == null) { return null; } - + if (logger.isLoggable(Level.FINE)) { + logger.fine("[transform] cl" + classLoader + " className:" + className + " Modifier:" + findModifier.getClass().getName()); + } String javassistClassName = className.replace('/', '.'); return findModifier.modify(classLoader, javassistClassName, protectionDomain, classFileBuffer); diff --git a/src/main/java/com/profiler/config/ProfilerConfig.java b/src/main/java/com/profiler/config/ProfilerConfig.java index cf72d16b9..f94654225 100644 --- a/src/main/java/com/profiler/config/ProfilerConfig.java +++ b/src/main/java/com/profiler/config/ProfilerConfig.java @@ -16,9 +16,15 @@ public class ProfilerConfig { private static final Logger logger = Logger.getLogger(ProfilerConfig.class.getName()); private boolean profileEnable = true; + + @Deprecated public static String SERVER_IP = "127.0.0.1"; + @Deprecated public static int SERVER_UDP_PORT = 9995; + public String collectorServerIp = "127.0.0.1"; + public int collectorServerPort = 9995; + @Deprecated public static int AGENT_TCP_LISTEN_PORT = 9990; @Deprecated @@ -28,14 +34,6 @@ public class ProfilerConfig { public static long JVM_STAT_GAP = 5000L; public static long SERVER_CONNECT_RETRY_GAP = 1000L; - /** - * 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. - */ - @Deprecated - public static boolean QUERY_COUNT_OVER_10000 = false; - private boolean jdbcProfile = true; private boolean jdbcProfileMySql = true; private boolean jdbcProfileMsSql = true; @@ -43,11 +41,16 @@ public class ProfilerConfig { private boolean jdbcProfileCubrid = true; private boolean jdbcProfileDbcp = true; + private boolean samplingElapsedTimeBaseEnable; + private int samplingElapsedTimeBaseBufferSize; + private boolean samplingElapsedTimeBaseDiscard; + private long samplingElapsedTimeBaseDiscardTimeLimit; + public ProfilerConfig() { } - public void readConfigFile() throws IOException{ + public void readConfigFile() throws IOException { String hippoConfigFileName = System.getProperty("hippo.config"); if (hippoConfigFileName == null) { logger.info("hippo.config property is not set. Using default value:" + this); @@ -71,6 +74,14 @@ public class ProfilerConfig { } } + public String getCollectorServerIp() { + return collectorServerIp; + } + + public int getCollectorServerPort() { + return collectorServerPort; + } + public boolean isProfileEnable() { return profileEnable; } @@ -95,53 +106,69 @@ public class ProfilerConfig { return jdbcProfileCubrid; } + public boolean isSamplingElapsedTimeBaseEnable() { + return samplingElapsedTimeBaseEnable; + } + + public int getSamplingElapsedTimeBaseBufferSize() { + return samplingElapsedTimeBaseBufferSize; + } + + public boolean isSamplingElapsedTimeBaseDiscard() { + return samplingElapsedTimeBaseDiscard; + } + + public long getSamplingElapsedTimeBaseDiscardTimeLimit() { + return samplingElapsedTimeBaseDiscardTimeLimit; + } + private void readPropertyValues(Properties prop) { // TODO : use Properties defaultvalue instead of using temp variable. this.profileEnable = readBoolean(prop, "PROFILE_ENABLE", true); - this.SERVER_IP = readString(prop, "SERVER_IP", "127.0.0.1"); - this.SERVER_UDP_PORT = readInt(prop, "SERVER_UDP_PORT", 9995); + this.collectorServerIp = readString(prop, "SERVER_IP", "127.0.0.1"); + this.collectorServerPort = readInt(prop, "SERVER_UDP_PORT", 9995); - Object temp = null; - if ((temp = prop.get("AGENT_TCP_LISTEN_PORT")) != null) { - this.AGENT_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); + String temp = null; + if ((temp = prop.getProperty("AGENT_TCP_LISTEN_PORT")) != null) { + this.AGENT_TCP_LISTEN_PORT = Integer.parseInt(temp); if (logger.isLoggable(Level.INFO)) { logger.info("AGENT_TCP_LISTEN_PORT=" + AGENT_TCP_LISTEN_PORT); } } - if ((temp = prop.get("SERVER_TCP_LISTEN_PORT")) != null) { - this.SERVER_TCP_LISTEN_PORT = Integer.parseInt(temp.toString()); + if ((temp = prop.getProperty("SERVER_TCP_LISTEN_PORT")) != null) { + this.SERVER_TCP_LISTEN_PORT = Integer.parseInt(temp); if (logger.isLoggable(Level.INFO)) { logger.info("SERVER_TCP_LISTEN_PORT=" + SERVER_TCP_LISTEN_PORT); } } - if ((temp = prop.get("JVM_STAT_GAP")) != null) { - this.JVM_STAT_GAP = Long.parseLong(temp.toString()); + if ((temp = prop.getProperty("JVM_STAT_GAP")) != null) { + this.JVM_STAT_GAP = Long.parseLong(temp); if (logger.isLoggable(Level.INFO)) { logger.info("JVM_STAT_GAP=" + JVM_STAT_GAP); } } - if ((temp = prop.get("SERVER_CONNECT_RETRY_GAP")) != null) { - this.SERVER_CONNECT_RETRY_GAP = Long.parseLong(temp.toString()); + if ((temp = prop.getProperty("SERVER_CONNECT_RETRY_GAP")) != null) { + this.SERVER_CONNECT_RETRY_GAP = Long.parseLong(temp); if (logger.isLoggable(Level.INFO)) { logger.info("SERVER_CONNECT_RETRY_GAP=" + SERVER_CONNECT_RETRY_GAP); } } -// if ((temp = prop.get("QUERY_COUNT_OVER_10000")) != null) { -// this.QUERY_COUNT_OVER_10000 = Boolean.parseBoolean(temp.toString()); -// if (logger.isLoggable(Level.INFO)) { -// logger.info("QUERY_COUNT_OVER_10000=" + QUERY_COUNT_OVER_10000); -// } -// } + // JDBC this.jdbcProfile = readBoolean(prop, "JDBC_PROFILE", true); this.jdbcProfileMySql = readBoolean(prop, "JDBC_PROFILE_MYSQL", true); this.jdbcProfileMsSql = readBoolean(prop, "JDBC_PROFILE_MSSQL", true); this.jdbcProfileOracle = readBoolean(prop, "JDBC_PROFILE_ORACLE", true); this.jdbcProfileCubrid = readBoolean(prop, "JDBC_PROFILE_CUBRID", true); - this.jdbcProfileCubrid = readBoolean(prop, "JDBC_PROFILE_DBCP", true); + this.jdbcProfileDbcp = readBoolean(prop, "JDBC_PROFILE_DBCP", true); + // 샘플링 + io 조절 bufferSize 결정 + this.samplingElapsedTimeBaseEnable = readBoolean(prop, "sampling.elapsedtimebase.enable", true); + this.samplingElapsedTimeBaseBufferSize = readInt(prop, "sampling.elapsedtimebase.buffersize", 20); + this.samplingElapsedTimeBaseDiscard = readBoolean(prop, "sampling.elapsedtimebase.discard", true); + this.samplingElapsedTimeBaseDiscardTimeLimit = readLong(prop, "sampling.elapsedtimebase.discard.timelimit", 1000); logger.info("configuration loaded successfully."); } @@ -163,6 +190,16 @@ public class ProfilerConfig { return result; } + private long readLong(Properties prop, String propertyName, int defaultValue) { + String value = prop.getProperty(propertyName); + long result = NumberUtils.parseLong(value, defaultValue); + if (logger.isLoggable(Level.INFO)) { + logger.info(propertyName + "=" + result); + } + return result; + } + + private boolean readBoolean(Properties prop, String propertyName, boolean defaultValue) { String value = prop.getProperty(propertyName, Boolean.toString(defaultValue)); boolean result = Boolean.parseBoolean(value); diff --git a/src/main/java/com/profiler/context/BypassStorageFactory.java b/src/main/java/com/profiler/context/BypassStorageFactory.java new file mode 100644 index 000000000..bdb6412d7 --- /dev/null +++ b/src/main/java/com/profiler/context/BypassStorageFactory.java @@ -0,0 +1,19 @@ +package com.profiler.context; + +import com.profiler.sender.DataSender; + +/** + * + */ +public class BypassStorageFactory implements StorageFactory { + private BypassStorage storage = new BypassStorage(); + + public BypassStorageFactory(DataSender dataSender) { + storage.setDataSender(dataSender); + } + + @Override + public Storage createStorage() { + return storage; + } +} diff --git a/src/main/java/com/profiler/context/StorageFactory.java b/src/main/java/com/profiler/context/StorageFactory.java new file mode 100644 index 000000000..9ada12fad --- /dev/null +++ b/src/main/java/com/profiler/context/StorageFactory.java @@ -0,0 +1,8 @@ +package com.profiler.context; + +/** + * + */ +public interface StorageFactory { + Storage createStorage(); +} diff --git a/src/main/java/com/profiler/context/TimeLimitStorage.java b/src/main/java/com/profiler/context/TimeBaseStorage.java similarity index 76% rename from src/main/java/com/profiler/context/TimeLimitStorage.java rename to src/main/java/com/profiler/context/TimeBaseStorage.java index 8c846758f..b86781034 100644 --- a/src/main/java/com/profiler/context/TimeLimitStorage.java +++ b/src/main/java/com/profiler/context/TimeBaseStorage.java @@ -9,21 +9,36 @@ import java.util.logging.Logger; /** * */ -public class TimeLimitStorage implements Storage { - private int flushCount = 10; - - private List storage = new ArrayList(flushCount); +public class TimeBaseStorage implements Storage { + private boolean discard = true; private boolean limit; - private boolean dropSubSpan = true; - private int limitTime = 1000; + private long limitTime = 1000; + private int bufferSize = 20; + + private List storage = new ArrayList(bufferSize); private DataSender dataSender; + public TimeBaseStorage() { + } + + public void setDiscard(boolean discard) { + this.discard = discard; + } + @Override public void setDataSender(DataSender dataSender) { this.dataSender = dataSender; } + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } + + public void setLimitTime(long limitTime) { + this.limitTime = limitTime; + } + @Override public DataSender getDataSender() { return this.dataSender; @@ -39,9 +54,9 @@ public class TimeLimitStorage implements Storage { } else { // 1초가 지났다면. // 데이터가 flushCount이상일 경우 먼저 flush한다. - if (storage.size() >= flushCount) { + if (storage.size() >= bufferSize) { SubSpanList subSpanList = new SubSpanList(storage); - storage = new ArrayList(flushCount); + storage = new ArrayList(bufferSize); dataSender.send(subSpanList); } } @@ -70,8 +85,7 @@ public class TimeLimitStorage implements Storage { public void store(Span span) { // Span이 들어오는것은 마지막 flush타이밍이다. // 비동기일 경우는 애매함. 비동기는 개별 flush해야 되나? - if (dropSubSpan) { - + if (discard) { limit = checkLimit(span); if (!limit) { // 제한시간내 빨리 끝난 경우는 subspan을 버린다. diff --git a/src/main/java/com/profiler/context/TimeBaseStorageFactory.java b/src/main/java/com/profiler/context/TimeBaseStorageFactory.java new file mode 100644 index 000000000..fb9b8a934 --- /dev/null +++ b/src/main/java/com/profiler/context/TimeBaseStorageFactory.java @@ -0,0 +1,29 @@ +package com.profiler.context; + +import com.profiler.config.ProfilerConfig; +import com.profiler.sender.DataSender; + +/** + * + */ +public class TimeBaseStorageFactory implements StorageFactory { + + private DataSender dataSender; + private ProfilerConfig config; + + public TimeBaseStorageFactory(DataSender dataSender, ProfilerConfig config) { + this.dataSender = dataSender; + this.config = config; + } + + + @Override + public Storage createStorage() { + TimeBaseStorage timeBaseStorage = new TimeBaseStorage(); + timeBaseStorage.setDataSender(this.dataSender); + timeBaseStorage.setBufferSize(config.getSamplingElapsedTimeBaseBufferSize()); + timeBaseStorage.setLimitTime(config.getSamplingElapsedTimeBaseDiscardTimeLimit()); + timeBaseStorage.setDiscard(config.isSamplingElapsedTimeBaseDiscard()); + return timeBaseStorage; + } +} diff --git a/src/main/java/com/profiler/context/Trace.java b/src/main/java/com/profiler/context/Trace.java index 3ac4b5651..4414c7ac7 100644 --- a/src/main/java/com/profiler/context/Trace.java +++ b/src/main/java/com/profiler/context/Trace.java @@ -25,11 +25,8 @@ public final class Trace { private boolean tracingEnabled = true; - // private TraceID root; private CallStack callStack; -// private DataSender dataSender = DEFULT_DATA_SENDER; - private Storage storage; public Trace() { @@ -67,10 +64,6 @@ public final class Trace { return storage.getDataSender(); } -// public void setDataSender(DataSender dataSender) { -// this.dataSender = dataSender; -// } - public AsyncTrace createAsyncTrace() { // 경우에 따라 별도 timeout 처리가 있어야 될수도 있음. diff --git a/src/main/java/com/profiler/context/TraceContext.java b/src/main/java/com/profiler/context/TraceContext.java index e9357b6e8..f9df33998 100644 --- a/src/main/java/com/profiler/context/TraceContext.java +++ b/src/main/java/com/profiler/context/TraceContext.java @@ -3,6 +3,7 @@ package com.profiler.context; import com.profiler.sender.DataSender; import com.profiler.sender.LoggingDataSender; +import com.profiler.util.Assert; import com.profiler.util.NamedThreadLocal; import java.util.concurrent.atomic.AtomicInteger; @@ -34,6 +35,12 @@ public class TraceContext { private GlobalCallTrace globalCallTrace = new GlobalCallTrace(); + private String agentId; + + private String applicationId; + + private StorageFactory storageFactory; + public TraceContext() { } @@ -49,8 +56,7 @@ public class TraceContext { } // datasender연결 부분 수정 필요. // trace.setDataSender(this.dataSender); - TimeLimitStorage storage = new TimeLimitStorage(); - storage.setDataSender(this.dataSender); + Storage storage = storageFactory.createStorage(); trace.setStorage(storage); // // trace.setTransactionId(transactionId.getAndIncrement()); @@ -73,4 +79,25 @@ public class TraceContext { this.dataSender = dataSender; this.globalCallTrace.setDataSender(dataSender); } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public String getAgentId() { + return agentId; + } + + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + + public String getApplicationId() { + return applicationId; + } + + public void setStorageFactory(StorageFactory storageFactory) { + Assert.notNull(storageFactory, "storageFactory myst not be null"); + this.storageFactory = storageFactory; + } } diff --git a/src/main/java/com/profiler/interceptor/TraceContextSupport.java b/src/main/java/com/profiler/interceptor/TraceContextSupport.java new file mode 100644 index 000000000..530e7bcb5 --- /dev/null +++ b/src/main/java/com/profiler/interceptor/TraceContextSupport.java @@ -0,0 +1,10 @@ +package com.profiler.interceptor; + +import com.profiler.context.TraceContext; + +/** + * + */ +public interface TraceContextSupport { + void setTraceContext(TraceContext traceContext); +} diff --git a/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java b/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java index a48f763f1..154181f2b 100644 --- a/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java +++ b/src/main/java/com/profiler/interceptor/bci/ByteCodeInstrumentor.java @@ -17,4 +17,6 @@ public interface ByteCodeInstrumentor { Class defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain) throws InstrumentException; Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) throws InstrumentException; + + Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN, Object[] params) throws InstrumentException; } diff --git a/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java b/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java index 7bee84d66..afd910ab5 100644 --- a/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java +++ b/src/main/java/com/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java @@ -1,5 +1,7 @@ package com.profiler.interceptor.bci; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.URLClassLoader; import java.security.ProtectionDomain; @@ -134,6 +136,38 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor { } } + @Override + public Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN, Object[] params) throws InstrumentException { + Class aClass = this.defineClass(classLoader, interceptorFQCN, protectedDomain); + try { + Class[] paramClass = getParamClass(params); + Constructor constructor = aClass.getConstructor(paramClass); + return (Interceptor) constructor.newInstance(params); + } catch (InstantiationException e) { + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); + } catch (NoSuchMethodException e) { + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); + } catch (InvocationTargetException e) { + throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e); + } + + } + + private Class[] getParamClass(Object[] params) throws InstrumentException { + Class[] paramClass = new Class[params.length]; + for (int i = 0; i < params.length; i++) { + Object o = params[i]; + if (o == null) { + throw new InstrumentException("params is null "); + } + paramClass[i] = o.getClass(); + + } + return paramClass; + } + private void loadClassLoaderLibraries(ClassLoader classLoader) { if (classLoader instanceof URLClassLoader) { URLClassLoader urlClassLoader = (URLClassLoader) classLoader; diff --git a/src/main/java/com/profiler/modifier/AbstractModifier.java b/src/main/java/com/profiler/modifier/AbstractModifier.java index 5f9b034d5..663d47501 100644 --- a/src/main/java/com/profiler/modifier/AbstractModifier.java +++ b/src/main/java/com/profiler/modifier/AbstractModifier.java @@ -4,6 +4,9 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; +import com.profiler.context.TraceContext; +import com.profiler.interceptor.TraceContextSupport; import com.profiler.interceptor.bci.InstrumentException; import javassist.ClassPool; @@ -15,10 +18,16 @@ public abstract class AbstractModifier implements Modifier { private final Logger logger = Logger.getLogger(AbstractModifier.class.getName()); protected final ClassPool classPool; - protected ByteCodeInstrumentor byteCodeInstrumentor; + protected final ByteCodeInstrumentor byteCodeInstrumentor; + protected final Agent agent; - public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor) { + public Agent getAgent() { + return agent; + } + + public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { this.byteCodeInstrumentor = byteCodeInstrumentor; + this.agent = agent; this.classPool = byteCodeInstrumentor.getClassPool(); } @@ -28,4 +37,11 @@ public abstract class AbstractModifier implements Modifier { } } + public void setTraceContext(Interceptor interceptor) { + // TODO TraceContext를 인터셉터에 바인하는 방안의 추가 개선 필요. + if (interceptor instanceof TraceContextSupport) { + ((TraceContextSupport) interceptor).setTraceContext(agent.getTraceContext()); + } + } + } diff --git a/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java index 8957e92fd..c818625af 100644 --- a/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java +++ b/src/main/java/com/profiler/modifier/DefaultModifierRegistry.java @@ -3,6 +3,7 @@ package com.profiler.modifier; import java.util.HashMap; import java.util.Map; +import com.profiler.Agent; import com.profiler.config.ProfilerConfig; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.arcus.ArcusClientModifier; @@ -38,13 +39,15 @@ import com.profiler.modifier.tomcat.TomcatStandardServiceModifier; public class DefaultModifierRegistry implements ModifierRegistry { // TODO 혹시 동시성을 고려 해야 되는지 검토. // 왠간해서는 동시성 상황이 안나올것으로 보임. - private Map registry = new HashMap(); + private Map registry = new HashMap(512); private final ByteCodeInstrumentor byteCodeInstrumentor; private final ProfilerConfig profilerConfig; + private final Agent agent; - public DefaultModifierRegistry(ByteCodeInstrumentor byteCodeInstrumentor, ProfilerConfig profilerConfig) { + public DefaultModifierRegistry(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent, ProfilerConfig profilerConfig) { this.byteCodeInstrumentor = byteCodeInstrumentor; + this.agent = agent; this.profilerConfig = profilerConfig; } @@ -61,38 +64,38 @@ public class DefaultModifierRegistry implements ModifierRegistry { } public void addConnectorModifier() { - HTTPClientModifier httpClientModifier = new HTTPClientModifier(byteCodeInstrumentor); + HTTPClientModifier httpClientModifier = new HTTPClientModifier(byteCodeInstrumentor, agent); addModifier(httpClientModifier); - MemcachedClientModifier memcachedClientModifier = new MemcachedClientModifier(byteCodeInstrumentor); + MemcachedClientModifier memcachedClientModifier = new MemcachedClientModifier(byteCodeInstrumentor, agent); addModifier(memcachedClientModifier); - ArcusClientModifier arcusClientModifier = new ArcusClientModifier(byteCodeInstrumentor); + ArcusClientModifier arcusClientModifier = new ArcusClientModifier(byteCodeInstrumentor, agent); addModifier(arcusClientModifier); - BaseOperationModifier baseOperationModifier = new BaseOperationModifier(byteCodeInstrumentor); + BaseOperationModifier baseOperationModifier = new BaseOperationModifier(byteCodeInstrumentor, agent); addModifier(baseOperationModifier); - CacheManagerModifier cacheManagerModifier = new CacheManagerModifier(byteCodeInstrumentor); + CacheManagerModifier cacheManagerModifier = new CacheManagerModifier(byteCodeInstrumentor, agent); addModifier(cacheManagerModifier); } public void addBLOCModifier() { - HTTPHandlerModifier httpHandlerModifier = new HTTPHandlerModifier(byteCodeInstrumentor); + HTTPHandlerModifier httpHandlerModifier = new HTTPHandlerModifier(byteCodeInstrumentor, agent); addModifier(httpHandlerModifier); } public void addTomcatModifier() { - StandardHostValveInvokeModifier standardHostValveInvokeModifier = new StandardHostValveInvokeModifier(byteCodeInstrumentor); + StandardHostValveInvokeModifier standardHostValveInvokeModifier = new StandardHostValveInvokeModifier(byteCodeInstrumentor, agent); addModifier(standardHostValveInvokeModifier); - Modifier tomcatStandardServiceModifier = new TomcatStandardServiceModifier(byteCodeInstrumentor); + Modifier tomcatStandardServiceModifier = new TomcatStandardServiceModifier(byteCodeInstrumentor, agent); addModifier(tomcatStandardServiceModifier); - Modifier tomcatConnectorModifier = new TomcatConnectorModifier(byteCodeInstrumentor); + Modifier tomcatConnectorModifier = new TomcatConnectorModifier(byteCodeInstrumentor, agent); addModifier(tomcatConnectorModifier); - Modifier tomcatCatalinaModifier = new CatalinaModifier(byteCodeInstrumentor); + Modifier tomcatCatalinaModifier = new CatalinaModifier(byteCodeInstrumentor, agent); addModifier(tomcatCatalinaModifier); } @@ -126,37 +129,37 @@ public class DefaultModifierRegistry implements ModifierRegistry { // TODO MySqlDriver는 버전별로 Connection이 interface인지 class인지가 다름. 문제 없는지 // 확인필요. - Modifier mysqlNonRegisteringDriverModifier = new MySQLNonRegisteringDriverModifier(byteCodeInstrumentor); + Modifier mysqlNonRegisteringDriverModifier = new MySQLNonRegisteringDriverModifier(byteCodeInstrumentor, agent); addModifier(mysqlNonRegisteringDriverModifier); - Modifier mysqlConnectionImplModifier = new MySQLConnectionImplModifier(byteCodeInstrumentor); + Modifier mysqlConnectionImplModifier = new MySQLConnectionImplModifier(byteCodeInstrumentor, agent); addModifier(mysqlConnectionImplModifier); - Modifier mysqlStatementModifier = new MySQLStatementModifier(byteCodeInstrumentor); + Modifier mysqlStatementModifier = new MySQLStatementModifier(byteCodeInstrumentor, agent); addModifier(mysqlStatementModifier); - Modifier mysqlPreparedStatementModifier = new MySQLPreparedStatementModifier(byteCodeInstrumentor); + Modifier mysqlPreparedStatementModifier = new MySQLPreparedStatementModifier(byteCodeInstrumentor, agent); addModifier(mysqlPreparedStatementModifier); - MySQLPreparedStatementJDBC4Modifier myqlPreparedStatementJDBC4Modifier = new MySQLPreparedStatementJDBC4Modifier(byteCodeInstrumentor); + MySQLPreparedStatementJDBC4Modifier myqlPreparedStatementJDBC4Modifier = new MySQLPreparedStatementJDBC4Modifier(byteCodeInstrumentor, agent); addModifier(myqlPreparedStatementJDBC4Modifier); - Modifier mysqlResultSetModifier = new MySQLResultSetModifier(byteCodeInstrumentor); + Modifier mysqlResultSetModifier = new MySQLResultSetModifier(byteCodeInstrumentor, agent); addModifier(mysqlResultSetModifier); } private void addMsSqlDriver() { - Modifier mssqlConnectionModifier = new MSSQLConnectionModifier(byteCodeInstrumentor); + Modifier mssqlConnectionModifier = new MSSQLConnectionModifier(byteCodeInstrumentor, agent); addModifier(mssqlConnectionModifier); - Modifier mssqlStatementModifier = new MSSQLStatementModifier(byteCodeInstrumentor); + Modifier mssqlStatementModifier = new MSSQLStatementModifier(byteCodeInstrumentor, agent); addModifier(mssqlStatementModifier); - Modifier mssqlPreparedStatementModifier = new MSSQLPreparedStatementModifier(byteCodeInstrumentor); + Modifier mssqlPreparedStatementModifier = new MSSQLPreparedStatementModifier(byteCodeInstrumentor, agent); addModifier(mssqlPreparedStatementModifier); - Modifier mssqlResultSetModifier = new MSSQLResultSetModifier(byteCodeInstrumentor); + Modifier mssqlResultSetModifier = new MSSQLResultSetModifier(byteCodeInstrumentor, agent); addModifier(mssqlResultSetModifier); } @@ -164,39 +167,39 @@ public class DefaultModifierRegistry implements ModifierRegistry { private void addOracleDriver() { // TODO oracle의 경우 connection에 대한 impl이 없음. 확인필요. - Modifier oraclePreparedStatementModifier = new OraclePreparedStatementModifier(byteCodeInstrumentor); + Modifier oraclePreparedStatementModifier = new OraclePreparedStatementModifier(byteCodeInstrumentor, agent); addModifier(oraclePreparedStatementModifier); - Modifier oracleStatement = new OracleStatementModifier(byteCodeInstrumentor); + Modifier oracleStatement = new OracleStatementModifier(byteCodeInstrumentor, agent); addModifier(oracleStatement); - Modifier oracleResultSetModifier = new OracleResultSetModifier(byteCodeInstrumentor); + Modifier oracleResultSetModifier = new OracleResultSetModifier(byteCodeInstrumentor, agent); addModifier(oracleResultSetModifier); } private void addCubridDriver() { // TODO cubrid의 경우도 connection에 대한 impl이 없음. 확인필요. - Modifier cubridStatementModifier = new CubridStatementModifier(byteCodeInstrumentor); + Modifier cubridStatementModifier = new CubridStatementModifier(byteCodeInstrumentor, agent); addModifier(cubridStatementModifier); - Modifier cubridPreparedStatementModifier = new CubridPreparedStatementModifier(byteCodeInstrumentor); + Modifier cubridPreparedStatementModifier = new CubridPreparedStatementModifier(byteCodeInstrumentor, agent); addModifier(cubridPreparedStatementModifier); - Modifier cubridResultSetModifier = new CubridResultSetModifier(byteCodeInstrumentor); + Modifier cubridResultSetModifier = new CubridResultSetModifier(byteCodeInstrumentor, agent); addModifier(cubridResultSetModifier); - Modifier cubridUStatementModifier = new CubridUStatementModifier(byteCodeInstrumentor); + Modifier cubridUStatementModifier = new CubridUStatementModifier(byteCodeInstrumentor, agent); addModifier(cubridUStatementModifier); } private void addDbcpDriver() { // TODO cubrid의 경우도 connection에 대한 impl이 없음. 확인필요. - Modifier dbcpBasicDataSourceModifier = new DBCPBasicDataSourceModifier(byteCodeInstrumentor); + Modifier dbcpBasicDataSourceModifier = new DBCPBasicDataSourceModifier(byteCodeInstrumentor, agent); addModifier(dbcpBasicDataSourceModifier); - Modifier dbcpPoolModifier = new DBCPPoolModifier(byteCodeInstrumentor); + Modifier dbcpPoolModifier = new DBCPPoolModifier(byteCodeInstrumentor, agent); addModifier(dbcpPoolModifier); } } diff --git a/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java b/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java index df03a9179..7f147edcf 100644 --- a/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java +++ b/src/main/java/com/profiler/modifier/arcus/ArcusClientModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -14,33 +15,33 @@ import com.profiler.modifier.AbstractModifier; */ public class ArcusClientModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(ArcusClientModifier.class.getName()); + private final Logger logger = Logger.getLogger(ArcusClientModifier.class.getName()); - public ArcusClientModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public ArcusClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "net/spy/memcached/ArcusClient"; - } + public String getTargetClass() { + return "net/spy/memcached/ArcusClient"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } - try { - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + try { + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - Interceptor setCacheManagerInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.SetCacheManagerInterceptor"); - aClass.addInterceptor("setCacheManager", new String[] { "net.spy.memcached.CacheManager" }, setCacheManagerInterceptor); - - return aClass.toBytecode(); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return null; - } - } + Interceptor setCacheManagerInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.SetCacheManagerInterceptor"); + aClass.addInterceptor("setCacheManager", new String[]{"net.spy.memcached.CacheManager"}, setCacheManagerInterceptor); + + return aClass.toBytecode(); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/arcus/BaseOperationModifier.java b/src/main/java/com/profiler/modifier/arcus/BaseOperationModifier.java index 877588bb5..21c7277eb 100644 --- a/src/main/java/com/profiler/modifier/arcus/BaseOperationModifier.java +++ b/src/main/java/com/profiler/modifier/arcus/BaseOperationModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -15,42 +16,42 @@ import com.profiler.modifier.arcus.interceptors.BaseOperationConstructIntercepto */ public class BaseOperationModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(BaseOperationModifier.class.getName()); + private final Logger logger = Logger.getLogger(BaseOperationModifier.class.getName()); - public BaseOperationModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public BaseOperationModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "net/spy/memcached/protocol/BaseOperationImpl"; - } + public String getTargetClass() { + return "net/spy/memcached/protocol/BaseOperationImpl"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } - try { - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + try { + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); - - aClass.addTraceVariable("__asyncTrace", "__setAsyncTrace", "__getAsyncTrace", "java.lang.Object"); - - aClass.addConstructorInterceptor(null, new BaseOperationConstructInterceptor()); + aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); - Interceptor transitionStateInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.BaseOperationTransitionStateInterceptor"); - aClass.addInterceptor("transitionState", new String[] { "net.spy.memcached.ops.OperationState" }, transitionStateInterceptor); + aClass.addTraceVariable("__asyncTrace", "__setAsyncTrace", "__getAsyncTrace", "java.lang.Object"); - Interceptor cancelInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.BaseOperationCancelInterceptor"); - aClass.addInterceptor("cancel", null, cancelInterceptor); + aClass.addConstructorInterceptor(null, new BaseOperationConstructInterceptor()); - return aClass.toBytecode(); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return null; - } - } + Interceptor transitionStateInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.BaseOperationTransitionStateInterceptor"); + aClass.addInterceptor("transitionState", new String[]{"net.spy.memcached.ops.OperationState"}, transitionStateInterceptor); + + Interceptor cancelInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.BaseOperationCancelInterceptor"); + aClass.addInterceptor("cancel", null, cancelInterceptor); + + return aClass.toBytecode(); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/arcus/CacheManagerModifier.java b/src/main/java/com/profiler/modifier/arcus/CacheManagerModifier.java index 933a6cfab..3d97dee31 100644 --- a/src/main/java/com/profiler/modifier/arcus/CacheManagerModifier.java +++ b/src/main/java/com/profiler/modifier/arcus/CacheManagerModifier.java @@ -4,45 +4,44 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; import com.profiler.modifier.AbstractModifier; import com.profiler.modifier.arcus.interceptors.CacheManagerConstructInterceptor; /** - * * @author netspider - * */ public class CacheManagerModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(CacheManagerModifier.class.getName()); + private final Logger logger = Logger.getLogger(CacheManagerModifier.class.getName()); - public CacheManagerModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public CacheManagerModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "net/spy/memcached/CacheManager"; - } + public String getTargetClass() { + return "net/spy/memcached/CacheManager"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } - try { - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + try { + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); - aClass.addConstructorInterceptor(new String[] { "java.lang.String", "java.lang.String", "net.spy.memcached.ConnectionFactoryBuilder", "java.util.concurrent.CountDownLatch", "int", "int" }, new CacheManagerConstructInterceptor()); + aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); + aClass.addConstructorInterceptor(new String[]{"java.lang.String", "java.lang.String", "net.spy.memcached.ConnectionFactoryBuilder", "java.util.concurrent.CountDownLatch", "int", "int"}, new CacheManagerConstructInterceptor()); - return aClass.toBytecode(); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return null; - } - } + return aClass.toBytecode(); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/arcus/MemcachedClientModifier.java b/src/main/java/com/profiler/modifier/arcus/MemcachedClientModifier.java index 534559a71..04ccdcf3c 100644 --- a/src/main/java/com/profiler/modifier/arcus/MemcachedClientModifier.java +++ b/src/main/java/com/profiler/modifier/arcus/MemcachedClientModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -14,35 +15,35 @@ import com.profiler.modifier.AbstractModifier; */ public class MemcachedClientModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(MemcachedClientModifier.class.getName()); + private final Logger logger = Logger.getLogger(MemcachedClientModifier.class.getName()); - public MemcachedClientModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public MemcachedClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "net/spy/memcached/MemcachedClient"; - } + public String getTargetClass() { + return "net/spy/memcached/MemcachedClient"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } - try { - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + try { + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); + aClass.addTraceVariable("__serviceCode", "__setServiceCode", "__getServiceCode", "java.lang.String"); - Interceptor addOpInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.AddOpInterceptor"); - aClass.addInterceptor("addOp", new String[] { "java.lang.String", "net.spy.memcached.ops.Operation" }, addOpInterceptor); + Interceptor addOpInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.arcus.interceptors.AddOpInterceptor"); + aClass.addInterceptor("addOp", new String[]{"java.lang.String", "net.spy.memcached.ops.Operation"}, addOpInterceptor); - return aClass.toBytecode(); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - return null; - } - } + return aClass.toBytecode(); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/bloc/handler/HTTPHandlerModifier.java b/src/main/java/com/profiler/modifier/bloc/handler/HTTPHandlerModifier.java index d0cf244e7..dcb8a9cb8 100644 --- a/src/main/java/com/profiler/modifier/bloc/handler/HTTPHandlerModifier.java +++ b/src/main/java/com/profiler/modifier/bloc/handler/HTTPHandlerModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -11,35 +12,34 @@ import com.profiler.interceptor.bci.InstrumentException; import com.profiler.modifier.AbstractModifier; /** - * * @author netspider */ public class HTTPHandlerModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(HTTPHandlerModifier.class.getName()); + private final Logger logger = Logger.getLogger(HTTPHandlerModifier.class.getName()); - public HTTPHandlerModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public HTTPHandlerModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "com/nhncorp/lucy/bloc/handler/HTTPHandler$BlocAdapter"; - } + public String getTargetClass() { + return "com/nhncorp/lucy/bloc/handler/HTTPHandler$BlocAdapter"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } - byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); - try { - Interceptor interceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.bloc.handler.interceptors.ExecuteMethodInterceptor"); - InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); - aClass.addInterceptor("execute", new String[] { "external.org.apache.coyote.Request", "external.org.apache.coyote.Response" }, interceptor); - return aClass.toBytecode(); - } catch (InstrumentException e) { - // TODO log - return null; - } - } + byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName); + try { + Interceptor interceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.bloc.handler.interceptors.ExecuteMethodInterceptor"); + InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("execute", new String[]{"external.org.apache.coyote.Request", "external.org.apache.coyote.Response"}, interceptor); + return aClass.toBytecode(); + } catch (InstrumentException e) { + // TODO log + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/bloc/handler/interceptors/ExecuteMethodInterceptor.java b/src/main/java/com/profiler/modifier/bloc/handler/interceptors/ExecuteMethodInterceptor.java index d249a6e4b..dfc1ce605 100644 --- a/src/main/java/com/profiler/modifier/bloc/handler/interceptors/ExecuteMethodInterceptor.java +++ b/src/main/java/com/profiler/modifier/bloc/handler/interceptors/ExecuteMethodInterceptor.java @@ -64,7 +64,7 @@ public class ExecuteMethodInterceptor implements StaticAroundInterceptor, ByteCo } trace.markBeforeTime(); - trace.recordRpcName(ServiceType.BLOC, Agent.getInstance().getApplicationName(), requestURL); + trace.recordRpcName(ServiceType.BLOC, traceContext.getApplicationId(), requestURL); trace.recordEndPoint(request.protocol().toString() + ":" + request.serverName().toString() + ":" + request.getServerPort()); trace.recordAttribute("http.url", request.requestURI().toString()); if (parameters != null && parameters.length() > 0) { diff --git a/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java b/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java index fba02cdaa..8d19e144c 100644 --- a/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java +++ b/src/main/java/com/profiler/modifier/connector/HTTPClientModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -33,8 +34,8 @@ public class HTTPClientModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(HTTPClientModifier.class.getName()); - public HTTPClientModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public HTTPClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/cubrid/CubridPreparedStatementModifier.java b/src/main/java/com/profiler/modifier/db/cubrid/CubridPreparedStatementModifier.java index eb9ae6b6c..e914e1374 100644 --- a/src/main/java/com/profiler/modifier/db/cubrid/CubridPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/cubrid/CubridPreparedStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.cubrid; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -16,8 +17,8 @@ public class CubridPreparedStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(CubridPreparedStatementModifier.class.getName()); - public CubridPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public CubridPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/cubrid/CubridResultSetModifier.java b/src/main/java/com/profiler/modifier/db/cubrid/CubridResultSetModifier.java index b1f66846f..3127d6683 100644 --- a/src/main/java/com/profiler/modifier/db/cubrid/CubridResultSetModifier.java +++ b/src/main/java/com/profiler/modifier/db/cubrid/CubridResultSetModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.cubrid; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import javassist.CtClass; import javassist.CtMethod; @@ -15,8 +16,8 @@ public class CubridResultSetModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(CubridResultSetModifier.class.getName()); - public CubridResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public CubridResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java b/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java index eb68ec012..035d1a29d 100644 --- a/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/cubrid/CubridStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.cubrid; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.StaticAroundInterceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; @@ -17,8 +18,8 @@ public class CubridStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(CubridStatementModifier.class.getName()); - public CubridStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public CubridStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/cubrid/CubridUStatementModifier.java b/src/main/java/com/profiler/modifier/db/cubrid/CubridUStatementModifier.java index bf5efc5ad..2dc4f4dfa 100644 --- a/src/main/java/com/profiler/modifier/db/cubrid/CubridUStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/cubrid/CubridUStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.cubrid; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import javassist.CtClass; import javassist.CtMethod; @@ -15,8 +16,8 @@ public class CubridUStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(CubridUStatementModifier.class.getName()); - public CubridUStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public CubridUStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/dbcp/DBCPBasicDataSourceModifier.java b/src/main/java/com/profiler/modifier/db/dbcp/DBCPBasicDataSourceModifier.java index 044122f05..603010a0d 100644 --- a/src/main/java/com/profiler/modifier/db/dbcp/DBCPBasicDataSourceModifier.java +++ b/src/main/java/com/profiler/modifier/db/dbcp/DBCPBasicDataSourceModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.dbcp; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -15,8 +16,8 @@ public class DBCPBasicDataSourceModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(DBCPBasicDataSourceModifier.class.getName()); - public DBCPBasicDataSourceModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public DBCPBasicDataSourceModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/dbcp/DBCPPoolModifier.java b/src/main/java/com/profiler/modifier/db/dbcp/DBCPPoolModifier.java index beec52e51..3dbb85dc0 100644 --- a/src/main/java/com/profiler/modifier/db/dbcp/DBCPPoolModifier.java +++ b/src/main/java/com/profiler/modifier/db/dbcp/DBCPPoolModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.dbcp; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -15,8 +16,8 @@ public class DBCPPoolModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(DBCPPoolModifier.class.getName()); - public DBCPPoolModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public DBCPPoolModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mssql/MSSQLConnectionModifier.java b/src/main/java/com/profiler/modifier/db/mssql/MSSQLConnectionModifier.java index 4a021cee0..1e7cc169f 100644 --- a/src/main/java/com/profiler/modifier/db/mssql/MSSQLConnectionModifier.java +++ b/src/main/java/com/profiler/modifier/db/mssql/MSSQLConnectionModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mssql; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -15,8 +16,8 @@ public class MSSQLConnectionModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MSSQLConnectionModifier.class.getName()); - public MSSQLConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MSSQLConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mssql/MSSQLPreparedStatementModifier.java b/src/main/java/com/profiler/modifier/db/mssql/MSSQLPreparedStatementModifier.java index 910e5a316..d11b25949 100644 --- a/src/main/java/com/profiler/modifier/db/mssql/MSSQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mssql/MSSQLPreparedStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mssql; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -16,8 +17,8 @@ public class MSSQLPreparedStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MSSQLPreparedStatementModifier.class.getName()); - public MSSQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MSSQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mssql/MSSQLResultSetModifier.java b/src/main/java/com/profiler/modifier/db/mssql/MSSQLResultSetModifier.java index a877aa50b..fea4f1bbe 100644 --- a/src/main/java/com/profiler/modifier/db/mssql/MSSQLResultSetModifier.java +++ b/src/main/java/com/profiler/modifier/db/mssql/MSSQLResultSetModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mssql; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import javassist.CtClass; import javassist.CtMethod; @@ -16,8 +17,8 @@ public class MSSQLResultSetModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MSSQLResultSetModifier.class.getName()); - public MSSQLResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MSSQLResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mssql/MSSQLStatementModifier.java b/src/main/java/com/profiler/modifier/db/mssql/MSSQLStatementModifier.java index da33b7cf0..fa8799f14 100644 --- a/src/main/java/com/profiler/modifier/db/mssql/MSSQLStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mssql/MSSQLStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mssql; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -14,8 +15,8 @@ import java.util.logging.Logger; public class MSSQLStatementModifier extends AbstractModifier { private static final Logger logger = Logger.getLogger(MSSQLStatementModifier.class.getName()); - public MSSQLStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MSSQLStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java index e02db5a0f..814b765da 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mysql; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -16,8 +17,8 @@ public class MySQLConnectionImplModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLConnectionImplModifier.class.getName()); - public MySQLConnectionImplModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLConnectionImplModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLNonRegisteringDriverModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLNonRegisteringDriverModifier.java index 881b4d179..d6d438e6e 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLNonRegisteringDriverModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLNonRegisteringDriverModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mysql; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -18,8 +19,8 @@ public class MySQLNonRegisteringDriverModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLConnectionImplModifier.class.getName()); - public MySQLNonRegisteringDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLNonRegisteringDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementJDBC4Modifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementJDBC4Modifier.java index e4cb407e2..6dcab3373 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementJDBC4Modifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementJDBC4Modifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mysql; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -20,8 +21,8 @@ public class MySQLPreparedStatementJDBC4Modifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLPreparedStatementJDBC4Modifier.class.getName()); private final String[] includes = new String[]{"setRowId", "setNClob", "setSQLXML"}; - public MySQLPreparedStatementJDBC4Modifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLPreparedStatementJDBC4Modifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { 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 f3987d394..931f8e406 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLPreparedStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mysql; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; @@ -26,8 +27,8 @@ public class MySQLPreparedStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLPreparedStatementModifier.class.getName()); private final String[] excludes = new String[]{"setRowId", "setNClob", "setSQLXML"}; - public MySQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/mysql/MySQLResultSetModifier.java b/src/main/java/com/profiler/modifier/db/mysql/MySQLResultSetModifier.java index b796bc445..ffa1f375a 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLResultSetModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLResultSetModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.mysql; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import javassist.CtClass; import javassist.CtMethod; @@ -16,8 +17,8 @@ public class MySQLResultSetModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLResultSetModifier.class.getName()); - public MySQLResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { 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 863a6b683..0935209a0 100644 --- a/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/mysql/MySQLStatementModifier.java @@ -4,6 +4,7 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.InstrumentException; import com.profiler.modifier.db.interceptor.StatementExecuteQueryInterceptor; @@ -16,8 +17,8 @@ public class MySQLStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(MySQLStatementModifier.class.getName()); - public MySQLStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public MySQLStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java b/src/main/java/com/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java index 806910b22..fa45dfed6 100644 --- a/src/main/java/com/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.oracle; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -16,8 +17,8 @@ public class OraclePreparedStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(OraclePreparedStatementModifier.class.getName()); - public OraclePreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public OraclePreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/oracle/OracleResultSetModifier.java b/src/main/java/com/profiler/modifier/db/oracle/OracleResultSetModifier.java index 02132eaa2..155cd022c 100644 --- a/src/main/java/com/profiler/modifier/db/oracle/OracleResultSetModifier.java +++ b/src/main/java/com/profiler/modifier/db/oracle/OracleResultSetModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.oracle; +import com.profiler.Agent; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import javassist.CtClass; import javassist.CtMethod; @@ -15,8 +16,8 @@ public class OracleResultSetModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(OracleResultSetModifier.class.getName()); - public OracleResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public OracleResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/db/oracle/OracleStatementModifier.java b/src/main/java/com/profiler/modifier/db/oracle/OracleStatementModifier.java index f93350be5..0dd4d3b8d 100644 --- a/src/main/java/com/profiler/modifier/db/oracle/OracleStatementModifier.java +++ b/src/main/java/com/profiler/modifier/db/oracle/OracleStatementModifier.java @@ -1,5 +1,6 @@ package com.profiler.modifier.db.oracle; +import com.profiler.Agent; import com.profiler.config.ProfilerConstant; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.modifier.AbstractModifier; @@ -14,8 +15,8 @@ import java.util.logging.Logger; public class OracleStatementModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(OracleStatementModifier.class.getName()); - public OracleStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public OracleStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { diff --git a/src/main/java/com/profiler/modifier/tomcat/CatalinaModifier.java b/src/main/java/com/profiler/modifier/tomcat/CatalinaModifier.java index 14f29badb..08571f6ca 100644 --- a/src/main/java/com/profiler/modifier/tomcat/CatalinaModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/CatalinaModifier.java @@ -1,6 +1,8 @@ package com.profiler.modifier.tomcat; import com.profiler.interceptor.bci.ByteCodeInstrumentor; +import com.profiler.interceptor.bci.InstrumentClass; +import com.profiler.modifier.tomcat.interceptors.CatalinaAwaitInterceptor; import javassist.CtClass; import javassist.CtMethod; @@ -13,48 +15,46 @@ import java.util.logging.Logger; /** * Tomcat startup정보를 HIPPO서버로 전송하는 코드를 호출하기위한 modifier - * + * * @author netspider - * */ public class CatalinaModifier extends AbstractModifier { - private final Logger logger = Logger.getLogger(CatalinaModifier.class.getName()); + private final Logger logger = Logger.getLogger(CatalinaModifier.class.getName()); - public CatalinaModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); - } + public CatalinaModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } - public String getTargetClass() { - return "org/apache/catalina/startup/Catalina"; - } + public String getTargetClass() { + return "org/apache/catalina/startup/Catalina"; + } - public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isLoggable(Level.INFO)) { - logger.info("Modifing. " + javassistClassName); - } - return changeMethod(javassistClassName, classFileBuffer); - } + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isLoggable(Level.INFO)) { + logger.info("Modifing. " + javassistClassName); + } + return changeMethod(javassistClassName, classFileBuffer); + } - public byte[] changeMethod(String javassistClassName, byte[] classfileBuffer) { - try { - CtClass cc = classPool.get(javassistClassName); + public byte[] changeMethod(String javassistClassName, byte[] classfileBuffer) { + try { + /** + * Tomcat startup완료되면 Catalina.await()을 호출하고 stop되기를 기다린다. 이 때 + * await하기 전에 서버가 시작되면서 수집된 WAS정보를 HIPPO 서버로 전송한다. + */ + CatalinaAwaitInterceptor catalinaAwaitInterceptor = new CatalinaAwaitInterceptor(agent); + InstrumentClass aClass = this.byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("await", null, catalinaAwaitInterceptor); - /** - * Tomcat startup완료되면 Catalina.await()을 호출하고 stop되기를 기다린다. 이 때 - * await하기 전에 서버가 시작되면서 수집된 WAS정보를 HIPPO 서버로 전송한다. - */ - CtMethod initializeMethod = cc.getDeclaredMethod("await", null); - initializeMethod.insertBefore("{" + Agent.FQCN + ".getInstance().sendStartupInfo(); }"); + printClassConvertComplete(javassistClassName); - printClassConvertComplete(javassistClassName); - - return cc.toBytecode(); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, e.getMessage(), e); - } - } - return null; - } + return aClass.toBytecode(); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } + return null; + } } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/tomcat/StandardHostValveInvokeModifier.java b/src/main/java/com/profiler/modifier/tomcat/StandardHostValveInvokeModifier.java index 4b8cecb20..760d344a9 100644 --- a/src/main/java/com/profiler/modifier/tomcat/StandardHostValveInvokeModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/StandardHostValveInvokeModifier.java @@ -1,5 +1,7 @@ package com.profiler.modifier.tomcat; +import com.profiler.Agent; +import com.profiler.context.TraceContext; import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; @@ -19,8 +21,8 @@ public class StandardHostValveInvokeModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(StandardHostValveInvokeModifier.class.getName()); - public StandardHostValveInvokeModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public StandardHostValveInvokeModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { @@ -36,6 +38,8 @@ public class StandardHostValveInvokeModifier extends AbstractModifier { try { Interceptor interceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.tomcat.interceptors.StandardHostValveInvokeInterceptor"); + setTraceContext(interceptor); + InstrumentClass standardHostValve = byteCodeInstrumentor.getClass(javassistClassName); standardHostValve.addInterceptor("invoke", new String[]{"org.apache.catalina.connector.Request", "org.apache.catalina.connector.Response"}, interceptor); return standardHostValve.toBytecode(); diff --git a/src/main/java/com/profiler/modifier/tomcat/TomcatConnectorModifier.java b/src/main/java/com/profiler/modifier/tomcat/TomcatConnectorModifier.java index 2b669c4fb..0ade45c61 100644 --- a/src/main/java/com/profiler/modifier/tomcat/TomcatConnectorModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/TomcatConnectorModifier.java @@ -1,6 +1,9 @@ package com.profiler.modifier.tomcat; +import com.profiler.interceptor.Interceptor; import com.profiler.interceptor.bci.ByteCodeInstrumentor; +import com.profiler.interceptor.bci.InstrumentClass; +import com.profiler.modifier.tomcat.interceptors.ConnectorInitializeInterceptor; import javassist.CtClass; import javassist.CtMethod; @@ -20,8 +23,8 @@ public class TomcatConnectorModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(TomcatConnectorModifier.class.getName()); - public TomcatConnectorModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public TomcatConnectorModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { @@ -32,26 +35,22 @@ public class TomcatConnectorModifier extends AbstractModifier { if (logger.isLoggable(Level.INFO)) { logger.info("Modifing. " + javassistClassName); } - return changeMethod(javassistClassName, classFileBuffer); - } - - public byte[] changeMethod(String javassistClassName, byte[] classfileBuffer) { try { - CtClass cc = classPool.get(javassistClassName); - - // initialize()할 때 protocol과 port번호를 저장해둔다. - CtMethod initializeMethod = cc.getDeclaredMethod("initialize", null); - initializeMethod.insertAfter("{" + Agent.FQCN + ".getInstance().getServerInfo().addConnector(getProtocol(), getPort()); }"); +// // initialize()할 때 protocol과 port번호를 저장해둔다. + Interceptor interceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.profiler.modifier.tomcat.interceptors.ConnectorInitializeInterceptor", new Object[]{agent}); + InstrumentClass aClass = this.byteCodeInstrumentor.getClass(javassistClassName); + aClass.addInterceptor("initialize", null, interceptor); printClassConvertComplete(javassistClassName); - return cc.toBytecode(); + return aClass.toBytecode(); } catch (Exception e) { if (logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING, e.getMessage(), e); } + return null; } - - return null; } + + } \ No newline at end of file diff --git a/src/main/java/com/profiler/modifier/tomcat/TomcatStandardServiceModifier.java b/src/main/java/com/profiler/modifier/tomcat/TomcatStandardServiceModifier.java index e26f23350..364aa3e28 100644 --- a/src/main/java/com/profiler/modifier/tomcat/TomcatStandardServiceModifier.java +++ b/src/main/java/com/profiler/modifier/tomcat/TomcatStandardServiceModifier.java @@ -4,6 +4,8 @@ import java.security.ProtectionDomain; import java.util.logging.Level; import java.util.logging.Logger; +import com.profiler.Agent; +import com.profiler.LifeCycleEventListener; import com.profiler.interceptor.bci.ByteCodeInstrumentor; import com.profiler.interceptor.bci.InstrumentClass; import com.profiler.interceptor.bci.InstrumentException; @@ -23,8 +25,8 @@ public class TomcatStandardServiceModifier extends AbstractModifier { private final Logger logger = Logger.getLogger(TomcatStandardServiceModifier.class.getName()); - public TomcatStandardServiceModifier(ByteCodeInstrumentor byteCodeInstrumentor) { - super(byteCodeInstrumentor); + public TomcatStandardServiceModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); } public String getTargetClass() { @@ -40,10 +42,12 @@ public class TomcatStandardServiceModifier extends AbstractModifier { try { InstrumentClass standardService = byteCodeInstrumentor.getClass(javassistClassName); - StandardServiceStartInterceptor start = new StandardServiceStartInterceptor(); + + LifeCycleEventListener lifeCycleEventListener = new LifeCycleEventListener(agent); + StandardServiceStartInterceptor start = new StandardServiceStartInterceptor(lifeCycleEventListener); standardService.addInterceptor("start", null, start); - StandardServiceStopInterceptor stop = new StandardServiceStopInterceptor(); + StandardServiceStopInterceptor stop = new StandardServiceStopInterceptor(lifeCycleEventListener); standardService.addInterceptor("stop", null, stop); return standardService.toBytecode(); diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/CatalinaAwaitInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/CatalinaAwaitInterceptor.java new file mode 100644 index 000000000..5632ae5cc --- /dev/null +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/CatalinaAwaitInterceptor.java @@ -0,0 +1,34 @@ +package com.profiler.modifier.tomcat.interceptors; + +import com.profiler.Agent; +import com.profiler.interceptor.StaticBeforeInterceptor; +import com.profiler.util.Assert; +import com.profiler.util.StringUtils; +import net.spy.memcached.compat.log.LoggerFactory; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class CatalinaAwaitInterceptor implements StaticBeforeInterceptor { + + private Logger logger = Logger.getLogger(this.getClass().getName()); + + private Agent agent; + + public CatalinaAwaitInterceptor(Agent agent) { + Assert.notNull(agent, "agent must not be null"); + this.agent = agent; + } + + @Override + public void before(Object target, String className, String methodName, String parameterDescription, Object[] args) { + if (logger.isLoggable(Level.INFO)) { + logger.info("before " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args)); + } + agent.sendStartupInfo(); + } +} diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/ConnectorInitializeInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/ConnectorInitializeInterceptor.java new file mode 100644 index 000000000..e7bafa6c5 --- /dev/null +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/ConnectorInitializeInterceptor.java @@ -0,0 +1,36 @@ +package com.profiler.modifier.tomcat.interceptors; + +import com.profiler.Agent; +import com.profiler.interceptor.StaticAfterInterceptor; +import com.profiler.util.Assert; +import com.profiler.util.StringUtils; +import org.apache.catalina.connector.Connector; + +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class ConnectorInitializeInterceptor implements StaticAfterInterceptor { + + private Logger logger = Logger.getLogger(this.getClass().getName()); + + private Agent agent; + + public ConnectorInitializeInterceptor(Agent agent) { + Assert.notNull(agent, "agent must not be null"); + this.agent = agent; + } + + @Override + public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { + if (logger.isLoggable(Level.INFO)) { + logger.info("after " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args) + " result:" + result); + } + Connector connector = (Connector) target; + agent.getServerInfo().addConnector(connector.getProtocol(), connector.getPort()); + + } +} diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java index e1d494bf8..8560b517f 100644 --- a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardHostValveInvokeInterceptor.java @@ -15,155 +15,156 @@ import com.profiler.context.SpanID; import com.profiler.context.Trace; import com.profiler.context.TraceContext; import com.profiler.context.TraceID; -import com.profiler.interceptor.ApiIdSupport; -import com.profiler.interceptor.ByteCodeMethodDescriptorSupport; -import com.profiler.interceptor.MethodDescriptor; -import com.profiler.interceptor.StaticAroundInterceptor; +import com.profiler.interceptor.*; import com.profiler.util.NumberUtils; import com.profiler.util.StringUtils; -public class StandardHostValveInvokeInterceptor implements StaticAroundInterceptor, ByteCodeMethodDescriptorSupport, ApiIdSupport { +public class StandardHostValveInvokeInterceptor implements StaticAroundInterceptor, ByteCodeMethodDescriptorSupport, ApiIdSupport, TraceContextSupport { - private final Logger logger = Logger.getLogger(StandardHostValveInvokeInterceptor.class.getName()); - private MethodDescriptor descriptor; - private int apiId; + private final Logger logger = Logger.getLogger(StandardHostValveInvokeInterceptor.class.getName()); + private MethodDescriptor descriptor; + private int apiId; + private TraceContext traceContext; - @Override - public void before(Object target, String className, String methodName, String parameterDescription, Object[] args) { - if (logger.isLoggable(Level.INFO)) { - logger.info("before " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args)); - } + @Override + public void before(Object target, String className, String methodName, String parameterDescription, Object[] args) { + if (logger.isLoggable(Level.INFO)) { + logger.info("before " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args)); + } - try { - TraceContext traceContext = TraceContext.getTraceContext(); - traceContext.getActiveThreadCounter().start(); + try { + traceContext.getActiveThreadCounter().start(); - HttpServletRequest request = (HttpServletRequest) args[0]; - String requestURL = request.getRequestURI(); - String clientIP = request.getRemoteAddr(); + HttpServletRequest request = (HttpServletRequest) args[0]; + String requestURL = request.getRequestURI(); + String clientIP = request.getRemoteAddr(); - TraceID traceId = populateTraceIdFromRequest(request); - Trace trace; - if (traceId != null) { - TraceID nextTraceId = traceId.getNextTraceId(); - if (logger.isLoggable(Level.INFO)) { - logger.info("TraceID exist. continue trace. " + nextTraceId); - logger.log(Level.FINE, "requestUrl:" + requestURL + " clientIp" + clientIP); - } - trace = new Trace(nextTraceId); - traceContext.attachTraceObject(trace); - } else { - trace = new Trace(); - if (logger.isLoggable(Level.INFO)) { - logger.info("TraceID not exist. start new trace. " + trace.getTraceId()); - logger.log(Level.FINE, "requestUrl:" + requestURL + " clientIp" + clientIP); - } - traceContext.attachTraceObject(trace); - } + TraceID traceId = populateTraceIdFromRequest(request); + Trace trace; + if (traceId != null) { + TraceID nextTraceId = traceId.getNextTraceId(); + if (logger.isLoggable(Level.INFO)) { + logger.info("TraceID exist. continue trace. " + nextTraceId); + logger.log(Level.FINE, "requestUrl:" + requestURL + " clientIp" + clientIP); + } + trace = new Trace(nextTraceId); + traceContext.attachTraceObject(trace); + } else { + trace = new Trace(); + if (logger.isLoggable(Level.INFO)) { + logger.info("TraceID not exist. start new trace. " + trace.getTraceId()); + logger.log(Level.FINE, "requestUrl:" + requestURL + " clientIp" + clientIP); + } + traceContext.attachTraceObject(trace); + } - trace.markBeforeTime(); - trace.recordRpcName(ServiceType.TOMCAT, Agent.getInstance().getApplicationName(), requestURL); + trace.markBeforeTime(); + trace.recordRpcName(ServiceType.TOMCAT, traceContext.getApplicationId(), requestURL); - int port = request.getServerPort(); - trace.recordEndPoint(request.getProtocol() + ":" + request.getServerName() + ((port > 0) ? ":" + port : "")); - trace.recordAttribute("http.url", request.getRequestURI()); - } catch (Exception e) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, "Tomcat StandardHostValve trace start fail. Caused:" + e.getMessage(), e); - } - } - } + int port = request.getServerPort(); + trace.recordEndPoint(request.getProtocol() + ":" + request.getServerName() + ((port > 0) ? ":" + port : "")); + trace.recordAttribute("http.url", request.getRequestURI()); + } catch (Exception e) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, "Tomcat StandardHostValve trace start fail. Caused:" + e.getMessage(), e); + } + } + } - @Override - public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { - if (logger.isLoggable(Level.INFO)) { - logger.info("after " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args) + " result:" + result); - } + @Override + public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { + if (logger.isLoggable(Level.INFO)) { + logger.info("after " + StringUtils.toString(target) + " " + className + "." + methodName + parameterDescription + " args:" + Arrays.toString(args) + " result:" + result); + } - TraceContext traceContext = TraceContext.getTraceContext(); - traceContext.getActiveThreadCounter().end(); - Trace trace = traceContext.currentTraceObject(); - if (trace == null) { - return; - } + traceContext.getActiveThreadCounter().end(); + Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } - HttpServletRequest request = (HttpServletRequest) args[0]; - String parameters = getRequestParameter(request); - if (parameters != null && parameters.length() > 0) { - trace.recordAttribute("http.params", parameters); - } + HttpServletRequest request = (HttpServletRequest) args[0]; + String parameters = getRequestParameter(request); + if (parameters != null && parameters.length() > 0) { + trace.recordAttribute("http.params", parameters); + } - traceContext.detachTraceObject(); - if (trace.getCurrentStackFrame().getStackFrameId() != 0) { - logger.warning("Corrupted CallStack found. StackId not Root(0)"); - // 문제 있는 callstack을 dump하면 도움이 될듯. - } + traceContext.detachTraceObject(); + if (trace.getCurrentStackFrame().getStackFrameId() != 0) { + logger.warning("Corrupted CallStack found. StackId not Root(0)"); + // 문제 있는 callstack을 dump하면 도움이 될듯. + } - // trace.recordApi(descriptor); - trace.recordApi(this.apiId); + // trace.recordApi(descriptor); + trace.recordApi(this.apiId); - trace.recordException(result); + trace.recordException(result); - trace.markAfterTime(); - trace.traceBlockEnd(); - } + trace.markAfterTime(); + trace.traceBlockEnd(); + } - /** - * Pupulate source trace from HTTP Header. - * - * @param request - * @return - */ - private TraceID populateTraceIdFromRequest(HttpServletRequest request) { - String strUUID = request.getHeader(Header.HTTP_TRACE_ID.toString()); - if (strUUID != null) { - UUID uuid = UUID.fromString(strUUID); - long parentSpanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_PARENT_SPAN_ID.toString()), SpanID.NULL); - long spanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_SPAN_ID.toString()), SpanID.NULL); - boolean sampled = Boolean.parseBoolean(request.getHeader(Header.HTTP_SAMPLED.toString())); - short flags = NumberUtils.parseShort(request.getHeader(Header.HTTP_FLAGS.toString()), (short) 0); + /** + * Pupulate source trace from HTTP Header. + * + * @param request + * @return + */ + private TraceID populateTraceIdFromRequest(HttpServletRequest request) { + String strUUID = request.getHeader(Header.HTTP_TRACE_ID.toString()); + if (strUUID != null) { + UUID uuid = UUID.fromString(strUUID); + long parentSpanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_PARENT_SPAN_ID.toString()), SpanID.NULL); + long spanID = NumberUtils.parseLong(request.getHeader(Header.HTTP_SPAN_ID.toString()), SpanID.NULL); + boolean sampled = Boolean.parseBoolean(request.getHeader(Header.HTTP_SAMPLED.toString())); + short flags = NumberUtils.parseShort(request.getHeader(Header.HTTP_FLAGS.toString()), (short) 0); - TraceID id = new TraceID(uuid, parentSpanID, spanID, sampled, flags); - if (logger.isLoggable(Level.INFO)) { - logger.info("TraceID exist. continue trace. " + id); - } - return id; - } else { - return null; - } - } + TraceID id = new TraceID(uuid, parentSpanID, spanID, sampled, flags); + if (logger.isLoggable(Level.INFO)) { + logger.info("TraceID exist. continue trace. " + id); + } + return id; + } else { + return null; + } + } - private String getRequestParameter(HttpServletRequest request) { - Enumeration attrs = request.getParameterNames(); - StringBuilder params = new StringBuilder(); + private String getRequestParameter(HttpServletRequest request) { + Enumeration attrs = request.getParameterNames(); + StringBuilder params = new StringBuilder(); - while (attrs.hasMoreElements()) { - String keyString = attrs.nextElement().toString(); - Object value = request.getParameter(keyString); + while (attrs.hasMoreElements()) { + String keyString = attrs.nextElement().toString(); + Object value = request.getParameter(keyString); - if (value != null) { - String valueString = value.toString(); - int valueStringLength = valueString.length(); + if (value != null) { + String valueString = value.toString(); + int valueStringLength = valueString.length(); - if (valueStringLength > 0 && valueStringLength < 100) { - params.append(keyString).append("=").append(valueString); - } + if (valueStringLength > 0 && valueStringLength < 100) { + params.append(keyString).append("=").append(valueString); + } - if (attrs.hasMoreElements()) { - params.append(", "); - } - } - } - return params.toString(); - } + if (attrs.hasMoreElements()) { + params.append(", "); + } + } + } + return params.toString(); + } - @Override - public void setMethodDescriptor(MethodDescriptor descriptor) { - this.descriptor = descriptor; - } + @Override + public void setMethodDescriptor(MethodDescriptor descriptor) { + this.descriptor = descriptor; + } - @Override - public void setApiId(int apiId) { - this.apiId = apiId; - } + @Override + public void setApiId(int apiId) { + this.apiId = apiId; + } + + @Override + public void setTraceContext(TraceContext traceContext) { + this.traceContext = traceContext; + } } diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStartInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStartInterceptor.java index 5943ad26f..fa4d9fcf1 100644 --- a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStartInterceptor.java +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStartInterceptor.java @@ -15,6 +15,12 @@ import java.util.logging.Logger; public class StandardServiceStartInterceptor implements StaticAfterInterceptor { private final Logger logger = Logger.getLogger(StandardServiceStartInterceptor.class.getName()); + private LifeCycleEventListener lifeCycleEventListener; + + public StandardServiceStartInterceptor(LifeCycleEventListener lifeCycleEventListener) { + this.lifeCycleEventListener = lifeCycleEventListener; + } + @Override public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { if (logger.isLoggable(Level.INFO)) { @@ -23,6 +29,6 @@ public class StandardServiceStartInterceptor implements StaticAfterInterceptor { // if (!InterceptorUtils.isSuccess(result)) { // return; // } - LifeCycleEventListener.start(); + lifeCycleEventListener.start(); } } diff --git a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStopInterceptor.java b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStopInterceptor.java index 97a37a04c..86f81db5f 100644 --- a/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStopInterceptor.java +++ b/src/main/java/com/profiler/modifier/tomcat/interceptors/StandardServiceStopInterceptor.java @@ -13,8 +13,15 @@ import java.util.logging.Logger; * */ public class StandardServiceStopInterceptor implements StaticAfterInterceptor { + private final Logger logger = Logger.getLogger(StandardServiceStopInterceptor.class.getName()); + private LifeCycleEventListener lifeCycleEventListener; + + public StandardServiceStopInterceptor(LifeCycleEventListener lifeCycleEventListener) { + this.lifeCycleEventListener = lifeCycleEventListener; + } + @Override public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result) { if (logger.isLoggable(Level.INFO)) { @@ -24,6 +31,6 @@ public class StandardServiceStopInterceptor implements StaticAfterInterceptor { // if (!InterceptorUtils.isSuccess(result)) { // return; // } - LifeCycleEventListener.stop(); + lifeCycleEventListener.stop(); } } diff --git a/src/main/java/com/profiler/sender/LoggingDataSender.java b/src/main/java/com/profiler/sender/LoggingDataSender.java index 49e077ff3..b3a451b0c 100644 --- a/src/main/java/com/profiler/sender/LoggingDataSender.java +++ b/src/main/java/com/profiler/sender/LoggingDataSender.java @@ -25,6 +25,6 @@ public class LoggingDataSender implements DataSender { @Override public void stop() { - + logger.info("LoggingDataSender stop"); } } diff --git a/src/main/java/com/profiler/sender/UdpDataSender.java b/src/main/java/com/profiler/sender/UdpDataSender.java index 065687774..b0432a03f 100644 --- a/src/main/java/com/profiler/sender/UdpDataSender.java +++ b/src/main/java/com/profiler/sender/UdpDataSender.java @@ -6,6 +6,7 @@ import com.profiler.common.util.HeaderTBaseSerializer; import com.profiler.common.util.TBaseLocator; import com.profiler.config.ProfilerConfig; import com.profiler.context.Thriftable; +import com.profiler.util.Assert; import org.apache.thrift.TBase; import org.apache.thrift.TException; @@ -28,44 +29,46 @@ public class UdpDataSender implements DataSender, Runnable { private final LinkedBlockingQueue queue = new LinkedBlockingQueue(1024); - private final InetSocketAddress serverAddress = new InetSocketAddress(ProfilerConfig.SERVER_IP, ProfilerConfig.SERVER_UDP_PORT); - private DatagramSocket udpSocket = null; + private Thread ioThread; + private TBaseLocator locator = new DefaultTBaseLocator(); // 주의 single thread용임 private HeaderTBaseSerializer serializer = new HeaderTBaseSerializer(); private boolean started = false; + private Object stopLock = new Object(); - private Thread ioThread; + public UdpDataSender(String host, int port) { + Assert.notNull(host, "host must not be null"); - private static class SingletonHolder { - public static final UdpDataSender INSTANCE = new UdpDataSender(); + // Socket 생성에 에러가 발생하면 Agent start가 안되게 변경. + this.udpSocket = createSocket(host, port); + + this.ioThread = createIoThread(); + + this.started = true; } - - public static UdpDataSender getInstance() { - return SingletonHolder.INSTANCE; + private Thread createIoThread() { + Thread thread = new Thread(this); + thread.setName("HIPPO-UdpDataSender:IoThread"); + thread.setDaemon(true); + thread.start(); + return thread; } - private UdpDataSender() { - udpSocket = createSocket(); - ioThread = new Thread(this); - ioThread.setName("HIPPO-DataSender"); - ioThread.setDaemon(true); - ioThread.start(); - started = true; - } - - private DatagramSocket createSocket() { + private DatagramSocket createSocket(String host, int port) { try { DatagramSocket datagramSocket = new DatagramSocket(); datagramSocket.setSoTimeout(1000 * 5); + + InetSocketAddress serverAddress = new InetSocketAddress(host, port); datagramSocket.connect(serverAddress); return datagramSocket; } catch (SocketException e) { - return null; + throw new IllegalStateException("DatagramSocket create fail. Cause" + e.getMessage(), e); } } @@ -104,7 +107,7 @@ public class UdpDataSender implements DataSender, Runnable { } send0(dto); } catch (Throwable e) { - logger.log(Level.WARNING, "Unexpected Error", e); + logger.log(Level.WARNING, "Unexpected Error Cause:" + e.getMessage(), e); } } } @@ -125,19 +128,13 @@ public class UdpDataSender implements DataSender, Runnable { return; } DatagramPacket packet = new DatagramPacket(sendData, sendData.length); - if (udpSocket == null) { - // socket생성에 문제가 있으면 재생성? - udpSocket = createSocket(); - } - if (udpSocket != null) { - try { - udpSocket.send(packet); - if (logger.isLoggable(Level.FINE)) { - logger.fine("Data sent. " + dto); - } - } catch (IOException e) { - logger.log(Level.WARNING, "packet send error " + dto, e); + try { + udpSocket.send(packet); + if (logger.isLoggable(Level.FINE)) { + logger.fine("Data sent. " + dto); } + } catch (IOException e) { + logger.log(Level.WARNING, "packet send error " + dto, e); } } @@ -155,14 +152,15 @@ public class UdpDataSender implements DataSender, Runnable { try { return serializer.serialize(header, dto); } catch (TException e) { - if (logger.isLoggable(Level.INFO)) { - logger.log(Level.INFO, "Serialize fail:" + dto, e); + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, "Serialize fail:" + dto, e); } return null; } } private Header createHeader(TBase dto) { + // TODO 구지 객체 생성을 안하고 정적 lookup이 가능할것 같음. short type = locator.typeLookup(dto); Header header = new Header(); header.setType(type); diff --git a/src/main/java/com/profiler/trace/DatabaseRequestTracer.java b/src/main/java/com/profiler/trace/DatabaseRequestTracer.java index 9a225bae1..4170293f5 100644 --- a/src/main/java/com/profiler/trace/DatabaseRequestTracer.java +++ b/src/main/java/com/profiler/trace/DatabaseRequestTracer.java @@ -13,304 +13,307 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; +@Deprecated public class DatabaseRequestTracer { - public static final String FQCN = DatabaseRequestTracer.class.getName(); + public static final String FQCN = DatabaseRequestTracer.class.getName(); - private static ConcurrentMap dbConnectionURL = new ConcurrentHashMap(); + private static ConcurrentMap dbConnectionURL = new ConcurrentHashMap(); - private static Set sqlSet = null; - static { - if (ProfilerConfig.QUERY_COUNT_OVER_10000) { - sqlSet = new CopyOnWriteArraySet(); - } else { - sqlSet = new HashSet(1024); - } - } + private static Set sqlSet = null; - private static final ThreadLocal requestDataThreadLocal = new NamedThreadLocal("requestDataThreadLocal"); - private static final ThreadLocal> sqlParamMapThreadLocal = new NamedThreadLocal>("sqlParamMapThreadLocal"); + static { +// if (ProfilerConfig.QUERY_COUNT_OVER_10000) { +// sqlSet = new CopyOnWriteArraySet(); +// } else { + sqlSet = new HashSet(1024); +// } + } - /** - * These two variables are used counting "ResultSet.next()" times. - */ - private static final ThreadLocal fetchCountThreadLocal = new NamedThreadLocal("fetchCountThreadLocal"); - private static final ThreadLocal totalFetchCountThreadLocal = new NamedThreadLocal("totalFetchCountThreadLocal"); + private static final ThreadLocal requestDataThreadLocal = new NamedThreadLocal("requestDataThreadLocal"); + private static final ThreadLocal> sqlParamMapThreadLocal = new NamedThreadLocal>("sqlParamMapThreadLocal"); - public static RequestDataListThriftDTO getRequestDataList() { - return requestDataThreadLocal.get(); - } + /** + * These two variables are used counting "ResultSet.next()" times. + */ + private static final ThreadLocal fetchCountThreadLocal = new NamedThreadLocal("fetchCountThreadLocal"); + private static final ThreadLocal totalFetchCountThreadLocal = new NamedThreadLocal("totalFetchCountThreadLocal"); - public static void removeRequestDataList() { - requestDataThreadLocal.remove(); - } + public static RequestDataListThriftDTO getRequestDataList() { + return requestDataThreadLocal.get(); + } - private static boolean isRequestData() { - Integer reqHashCode = RequestTracer.getCurrentRequestHash(); - if (reqHashCode == null) { - return false; - } else { - return true; - } - } + public static void removeRequestDataList() { + requestDataThreadLocal.remove(); + } - /** - * Put data to requestDataThreadLocal. - * - * @param dataType - */ - public static void put(int dataType) { - // System.out.println(dataType+"-----RequestHashCode="+RequestTransactionTracer.getRequestHashCode()); - if (isRequestData()) { - RequestDataListThriftDTO dto = requestDataThreadLocal.get(); - dto = checkDTO(dto); - List list = dto.getRequestDataList(); - // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); + private static boolean isRequestData() { + Integer reqHashCode = RequestTracer.getCurrentRequestHash(); + if (reqHashCode == null) { + return false; + } else { + return true; + } + } - checkSqlParamMap(list); + /** + * Put data to requestDataThreadLocal. + * + * @param dataType + */ + public static void put(int dataType) { + // System.out.println(dataType+"-----RequestHashCode="+RequestTransactionTracer.getRequestHashCode()); + if (isRequestData()) { + RequestDataListThriftDTO dto = requestDataThreadLocal.get(); + dto = checkDTO(dto); + List list = dto.getRequestDataList(); + // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); - RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); - list.add(dataDto); - requestDataThreadLocal.set(dto); - } - } + checkSqlParamMap(list); - /** - * Put Connection data to requestDataThreadLocal. - * - * @param dataType - */ - public static void putConnection(int dataType, String url) { - // System.out.println(dataType+"-----RequestHashCode="+RequestTransactionTracer.getRequestHashCode()); - if (isRequestData()) { - RequestDataListThriftDTO dto = requestDataThreadLocal.get(); - dto = checkDTO(dto); - List list = dto.getRequestDataList(); - // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); + RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); + list.add(dataDto); + requestDataThreadLocal.set(dto); + } + } - checkSqlParamMap(list); + /** + * Put Connection data to requestDataThreadLocal. + * + * @param dataType + */ + public static void putConnection(int dataType, String url) { + // System.out.println(dataType+"-----RequestHashCode="+RequestTransactionTracer.getRequestHashCode()); + if (isRequestData()) { + RequestDataListThriftDTO dto = requestDataThreadLocal.get(); + dto = checkDTO(dto); + List list = dto.getRequestDataList(); + // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); - RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); - if (url != null) { - int hashCode = url.hashCode(); - String before = dbConnectionURL.putIfAbsent(hashCode, url); - if (before == null) { - dataDto.setDataString(url); - } + checkSqlParamMap(list); - dataDto.setDataHashCode(hashCode); - } - list.add(dataDto); - requestDataThreadLocal.set(dto); - } - } + RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); + if (url != null) { + int hashCode = url.hashCode(); + String before = dbConnectionURL.putIfAbsent(hashCode, url); + if (before == null) { + dataDto.setDataString(url); + } - /** - * Put SQL Query data into requestDataThreadLocal. - * - * @param dataType - */ - public static void putSqlQuery(int dataType, String data) { - if (isRequestData()) { - RequestDataListThriftDTO dto = requestDataThreadLocal.get(); - dto = checkDTO(dto); - List list = dto.getRequestDataList(); - // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); + dataDto.setDataHashCode(hashCode); + } + list.add(dataDto); + requestDataThreadLocal.set(dto); + } + } - checkSqlParamMap(list); + /** + * Put SQL Query data into requestDataThreadLocal. + * + * @param dataType + */ + public static void putSqlQuery(int dataType, String data) { + if (isRequestData()) { + RequestDataListThriftDTO dto = requestDataThreadLocal.get(); + dto = checkDTO(dto); + List list = dto.getRequestDataList(); + // System.out.println("-----RequestDataListThriftDTO list size="+list.size()); - RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); - int dataHashCode = data.hashCode(); - dataDto.setDataHashCode(dataHashCode); - boolean isAlreadySent = checkHashCode(dataHashCode); - if (!isAlreadySent) { - if (data != null) { - dataDto.setDataString(QueryStringUtil.removeAllMultiSpace(data)); - } - } - list.add(dataDto); - requestDataThreadLocal.set(dto); - } - } + checkSqlParamMap(list); - /** - * Check SQL Query HashCode set. If Query count is over 10000, it can make - * memory problem. So this method removes 100 hashCode. - * - * If you use HashSet this remove code will not run. - * - * @param dataHashCode - * @return - */ - private static boolean checkHashCode(int dataHashCode) { - if (ProfilerConfig.QUERY_COUNT_OVER_10000) { - // If sqlSet is CopyOnWriteArraySet, it removes data. - if (sqlSet.size() > 10000) { - Iterator iterator = sqlSet.iterator(); - for (int loop = 0; loop < 100; loop++) { - sqlSet.remove(iterator.next()); - } - } - } - if (sqlSet.contains(dataHashCode)) { - return true; - } else { - sqlSet.add(dataHashCode); - return false; - } - } + RequestDataThriftDTO dataDto = new RequestDataThriftDTO(dataType, System.currentTimeMillis()); + int dataHashCode = data.hashCode(); + dataDto.setDataHashCode(dataHashCode); + boolean isAlreadySent = checkHashCode(dataHashCode); + if (!isAlreadySent) { + if (data != null) { + dataDto.setDataString(QueryStringUtil.removeAllMultiSpace(data)); + } + } + list.add(dataDto); + requestDataThreadLocal.set(dto); + } + } - /** - * Manage sql param list - * - * @param list - */ - private static void checkSqlParamMap(List list) { - if (isRequestData()) { - HashMap map = sqlParamMapThreadLocal.get(); - if (map != null) { - int mapSize = map.size(); - StringBuilder params = new StringBuilder(); - for (int loop = 1; loop <= mapSize; loop++) { - params.append(map.get(loop)).append(","); - } + /** + * Check SQL Query HashCode set. If Query count is over 10000, it can make + * memory problem. So this method removes 100 hashCode. + *

+ * If you use HashSet this remove code will not run. + * + * @param dataHashCode + * @return + */ + private static boolean checkHashCode(int dataHashCode) { +// if (ProfilerConfig.QUERY_COUNT_OVER_10000) { + if (true) { + // If sqlSet is CopyOnWriteArraySet, it removes data. + if (sqlSet.size() > 10000) { + Iterator iterator = sqlSet.iterator(); + for (int loop = 0; loop < 100; loop++) { + sqlSet.remove(iterator.next()); + } + } + } + if (sqlSet.contains(dataHashCode)) { + return true; + } else { + sqlSet.add(dataHashCode); + return false; + } + } - RequestDataThriftDTO dataDto = new RequestDataThriftDTO(ProfilerConstant.REQ_DATA_TYPE_DB_PREPARED_STATEMENT_PARAM, System.currentTimeMillis()); - dataDto.setDataString(params.toString()); - list.add(dataDto); - } - sqlParamMapThreadLocal.remove(); - } - } + /** + * Manage sql param list + * + * @param list + */ + private static void checkSqlParamMap(List list) { + if (isRequestData()) { + HashMap map = sqlParamMapThreadLocal.get(); + if (map != null) { + int mapSize = map.size(); + StringBuilder params = new StringBuilder(); + for (int loop = 1; loop <= mapSize; loop++) { + params.append(map.get(loop)).append(","); + } - /** - * Add sql parameter - * - * @param sequence - * @param data - */ - public static void putSqlParam(int sequence, String data) { - if (isRequestData()) { - HashMap map = sqlParamMapThreadLocal.get(); - if (map == null) { - map = new HashMap(); - } - // if(data!=null) { - // try { - // System.out.print("Before="+data); - // String afterData1=new String(data.getBytes("MS949"), - // "ISO-8859-1");; - // System.out.print(" After1="+afterData1); - // String afterData1_1=new String(afterData1.getBytes("ISO-8859-1"), - // "EUC-KR");; - // System.out.print(" After1_1="+afterData1_1); - // - // - // String afterData3=new - // String(data.getBytes("ISO-8859-1"),"MS949"); - // System.out.print(" After3="+afterData3); - // String afterData3_1=new - // String(afterData3.getBytes("MS949"),"EUC-KR"); - // System.out.print(" After3_1="+afterData3_1); - // - // String afterData5=new - // String(data.getBytes("ISO-8859-1"),"EUC-KR"); - // System.out.print(" After5="+afterData5); - // String afterData6=new String(data.getBytes("MS949"),"EUC-KR"); - // System.out.print(" After6="+afterData6); - // - // String afterData7=new String(data.getBytes(),"ISO-8859-1"); - // System.out.print(" After7="+afterData7); - // - // System.out.println(); - // } catch(Exception e) { - // e.printStackTrace(); - // } - // } - map.put(sequence, data); - sqlParamMapThreadLocal.set(map); - } - } + RequestDataThriftDTO dataDto = new RequestDataThriftDTO(ProfilerConstant.REQ_DATA_TYPE_DB_PREPARED_STATEMENT_PARAM, System.currentTimeMillis()); + dataDto.setDataString(params.toString()); + list.add(dataDto); + } + sqlParamMapThreadLocal.remove(); + } + } - public static void putSqlParam(int sequence, byte[] data) { - putSqlParam(sequence, new String(data)); - } + /** + * Add sql parameter + * + * @param sequence + * @param data + */ + public static void putSqlParam(int sequence, String data) { + if (isRequestData()) { + HashMap map = sqlParamMapThreadLocal.get(); + if (map == null) { + map = new HashMap(); + } + // if(data!=null) { + // try { + // System.out.print("Before="+data); + // String afterData1=new String(data.getBytes("MS949"), + // "ISO-8859-1");; + // System.out.print(" After1="+afterData1); + // String afterData1_1=new String(afterData1.getBytes("ISO-8859-1"), + // "EUC-KR");; + // System.out.print(" After1_1="+afterData1_1); + // + // + // String afterData3=new + // String(data.getBytes("ISO-8859-1"),"MS949"); + // System.out.print(" After3="+afterData3); + // String afterData3_1=new + // String(afterData3.getBytes("MS949"),"EUC-KR"); + // System.out.print(" After3_1="+afterData3_1); + // + // String afterData5=new + // String(data.getBytes("ISO-8859-1"),"EUC-KR"); + // System.out.print(" After5="+afterData5); + // String afterData6=new String(data.getBytes("MS949"),"EUC-KR"); + // System.out.print(" After6="+afterData6); + // + // String afterData7=new String(data.getBytes(),"ISO-8859-1"); + // System.out.print(" After7="+afterData7); + // + // System.out.println(); + // } catch(Exception e) { + // e.printStackTrace(); + // } + // } + map.put(sequence, data); + sqlParamMapThreadLocal.set(map); + } + } - public static void putSqlParam(int sequence, Object data) { - if (data != null) { - putSqlParam(sequence, data.toString()); - } else { - putSqlParam(sequence, "null"); - } - } + public static void putSqlParam(int sequence, byte[] data) { + putSqlParam(sequence, new String(data)); + } - /** - * Check RequestDataListThriftDTO is null. If this object is null, current - * request called this Class first time. So it make RequestDataListThriftDTO - * object. - * - * @param dto - * @return - */ - private static RequestDataListThriftDTO checkDTO(RequestDataListThriftDTO dto) { - if (dto == null) { - dto = new RequestDataListThriftDTO(Agent.getInstance().getAgentId(), RequestTracer.getCurrentRequestHash(), new ArrayList()); - } - return dto; - } + public static void putSqlParam(int sequence, Object data) { + if (data != null) { + putSqlParam(sequence, data.toString()); + } else { + putSqlParam(sequence, "null"); + } + } - /** - * add ResultSet.next() method call count. - */ - public static void updateFetchCount() { - Integer totalFetchCount = totalFetchCountThreadLocal.get(); - Integer fetchCount = fetchCountThreadLocal.get(); - if (totalFetchCount == null) { - totalFetchCountThreadLocal.set(0); - } - if (fetchCount == null) { - fetchCountThreadLocal.set(0); - } - totalFetchCountThreadLocal.set(totalFetchCountThreadLocal.get() + 1); - fetchCountThreadLocal.set(fetchCountThreadLocal.get() + 1); - } + /** + * Check RequestDataListThriftDTO is null. If this object is null, current + * request called this Class first time. So it make RequestDataListThriftDTO + * object. + * + * @param dto + * @return + */ + private static RequestDataListThriftDTO checkDTO(RequestDataListThriftDTO dto) { + if (dto == null) { +// dto = new RequestDataListThriftDTO(Agent.getInstance().getAgentId(), RequestTracer.getCurrentRequestHash(), new ArrayList()); + } + return dto; + } - /** - * Before transaction end, removes current thread's fetch count data. - */ - public static void removeFetchCount() { - totalFetchCountThreadLocal.remove(); - fetchCountThreadLocal.remove(); - } + /** + * add ResultSet.next() method call count. + */ + public static void updateFetchCount() { + Integer totalFetchCount = totalFetchCountThreadLocal.get(); + Integer fetchCount = fetchCountThreadLocal.get(); + if (totalFetchCount == null) { + totalFetchCountThreadLocal.set(0); + } + if (fetchCount == null) { + fetchCountThreadLocal.set(0); + } + totalFetchCountThreadLocal.set(totalFetchCountThreadLocal.get() + 1); + fetchCountThreadLocal.set(fetchCountThreadLocal.get() + 1); + } - /** - * If ResultSet.close() method is called, this method is called. - */ - public static void addResultSetData() { - if (isRequestData()) { - // set data fetch count - Integer fetchCount = fetchCountThreadLocal.get(); - if (fetchCount != null) { - Integer totalFetchCount = totalFetchCountThreadLocal.get(); - fetchCountThreadLocal.remove(); + /** + * Before transaction end, removes current thread's fetch count data. + */ + public static void removeFetchCount() { + totalFetchCountThreadLocal.remove(); + fetchCountThreadLocal.remove(); + } - RequestDataListThriftDTO dto = requestDataThreadLocal.get(); - dto = checkDTO(dto); - List list = dto.getRequestDataList(); - int listSize = list.size(); - RequestDataThriftDTO previousDTO = list.get(listSize - 1); - if (previousDTO.getDataType() != ProfilerConstant.REQ_DATA_TYPE_DB_FETCH) { - RequestDataThriftDTO dataDto = new RequestDataThriftDTO(ProfilerConstant.REQ_DATA_TYPE_DB_FETCH, System.currentTimeMillis()); - dataDto.setExtraInt1(fetchCount); - dataDto.setExtraInt2(totalFetchCount); - list.add(dataDto); - } else { - // Because of MS SQL. - int previousTotalFetchCount = previousDTO.getExtraInt2(); - totalFetchCountThreadLocal.set(previousTotalFetchCount); - } - requestDataThreadLocal.set(dto); - } - } - } + /** + * If ResultSet.close() method is called, this method is called. + */ + public static void addResultSetData() { + if (isRequestData()) { + // set data fetch count + Integer fetchCount = fetchCountThreadLocal.get(); + if (fetchCount != null) { + Integer totalFetchCount = totalFetchCountThreadLocal.get(); + fetchCountThreadLocal.remove(); + + RequestDataListThriftDTO dto = requestDataThreadLocal.get(); + dto = checkDTO(dto); + List list = dto.getRequestDataList(); + int listSize = list.size(); + RequestDataThriftDTO previousDTO = list.get(listSize - 1); + if (previousDTO.getDataType() != ProfilerConstant.REQ_DATA_TYPE_DB_FETCH) { + RequestDataThriftDTO dataDto = new RequestDataThriftDTO(ProfilerConstant.REQ_DATA_TYPE_DB_FETCH, System.currentTimeMillis()); + dataDto.setExtraInt1(fetchCount); + dataDto.setExtraInt2(totalFetchCount); + list.add(dataDto); + } else { + // Because of MS SQL. + int previousTotalFetchCount = previousDTO.getExtraInt2(); + totalFetchCountThreadLocal.set(previousTotalFetchCount); + } + requestDataThreadLocal.set(dto); + } + } + } } diff --git a/src/main/java/com/profiler/trace/RequestTracer.java b/src/main/java/com/profiler/trace/RequestTracer.java index 042d9dd71..63c100c39 100644 --- a/src/main/java/com/profiler/trace/RequestTracer.java +++ b/src/main/java/com/profiler/trace/RequestTracer.java @@ -40,7 +40,7 @@ public class RequestTracer { // dto.setExtraData1(params.toString()); // } - UdpDataSender.getInstance().send(dto); +// UdpDataSender.getInstance().send(dto); } /** @@ -80,10 +80,10 @@ public class RequestTracer { RequestDataListThriftDTO dataListDto = DatabaseRequestTracer.getRequestDataList(); if (dataListDto != null) { - UdpDataSender.getInstance().send(dataListDto); +// UdpDataSender.getInstance().send(dataListDto); } - UdpDataSender.getInstance().send(dto); +// UdpDataSender.getInstance().send(dto); requestSet.remove(currentRequestID.get()); DatabaseRequestTracer.removeRequestDataList(); diff --git a/src/main/java/com/profiler/util/Assert.java b/src/main/java/com/profiler/util/Assert.java new file mode 100644 index 000000000..8e3ecd521 --- /dev/null +++ b/src/main/java/com/profiler/util/Assert.java @@ -0,0 +1,17 @@ +package com.profiler.util; + +/** + * + */ +public class Assert { + + public static void notNull(Object object, String message) { + if (object == null) { + throw new IllegalArgumentException(message); + } + } + + public static void notNull(Object object) { + notNull(object, "[Assertion failed] - this argument is required; it must not be null"); + } +} diff --git a/src/test/java/com/profiler/SystemMonitorTest.java b/src/test/java/com/profiler/SystemMonitorTest.java index 3efd7f4c1..70dcbcafb 100644 --- a/src/test/java/com/profiler/SystemMonitorTest.java +++ b/src/test/java/com/profiler/SystemMonitorTest.java @@ -1,5 +1,6 @@ package com.profiler; +import com.profiler.context.TraceContext; import com.profiler.sender.DataSender; import com.profiler.sender.LoggingDataSender; import org.junit.Test; @@ -15,8 +16,8 @@ public class SystemMonitorTest { @Test public void testStart() throws Exception { DataSender loggingDataSender = new LoggingDataSender(); - - SystemMonitor systemMonitor = new SystemMonitor(); + TraceContext traceContext = new TraceContext(); + SystemMonitor systemMonitor = new SystemMonitor(traceContext); systemMonitor.setDataSender(loggingDataSender); systemMonitor.start(); diff --git a/src/test/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifierTest.java b/src/test/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifierTest.java index b1972eab4..d1a408560 100644 --- a/src/test/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifierTest.java +++ b/src/test/java/com/profiler/modifier/db/mysql/MySQLConnectionImplModifierTest.java @@ -1,6 +1,8 @@ package com.profiler.modifier.db.mysql; import com.mysql.jdbc.JDBC4PreparedStatement; +import com.profiler.Agent; +import com.profiler.config.ProfilerConfig; import com.profiler.context.Trace; import com.profiler.context.TraceContext; import com.profiler.context.TraceID; @@ -26,19 +28,21 @@ public class MySQLConnectionImplModifierTest { public void setUp() throws Exception { loader = new TestClassLoader(); - MySQLNonRegisteringDriverModifier driverModifier = new MySQLNonRegisteringDriverModifier(loader.getInstrumentor()); + ProfilerConfig profilerConfig = new ProfilerConfig(); + Agent agent = new Agent(profilerConfig); + MySQLNonRegisteringDriverModifier driverModifier = new MySQLNonRegisteringDriverModifier(loader.getInstrumentor(), agent); loader.addModifier(driverModifier); - MySQLConnectionImplModifier connectionModifier = new MySQLConnectionImplModifier(loader.getInstrumentor()); + MySQLConnectionImplModifier connectionModifier = new MySQLConnectionImplModifier(loader.getInstrumentor(), agent); loader.addModifier(connectionModifier); - MySQLStatementModifier statementModifier = new MySQLStatementModifier(loader.getInstrumentor()); + MySQLStatementModifier statementModifier = new MySQLStatementModifier(loader.getInstrumentor(), agent); loader.addModifier(statementModifier); - MySQLPreparedStatementModifier preparedStatementModifier = new MySQLPreparedStatementModifier(loader.getInstrumentor()); + MySQLPreparedStatementModifier preparedStatementModifier = new MySQLPreparedStatementModifier(loader.getInstrumentor(), agent); loader.addModifier(preparedStatementModifier); - MySQLPreparedStatementJDBC4Modifier preparedStatementJDBC4Modifier = new MySQLPreparedStatementJDBC4Modifier(loader.getInstrumentor()); + MySQLPreparedStatementJDBC4Modifier preparedStatementJDBC4Modifier = new MySQLPreparedStatementJDBC4Modifier(loader.getInstrumentor(), agent); loader.addModifier(preparedStatementJDBC4Modifier); loader.initialize(); diff --git a/src/test/resources/hippo.config b/src/test/resources/hippo.config index 6200c0414..69022a613 100644 --- a/src/test/resources/hippo.config +++ b/src/test/resources/hippo.config @@ -22,3 +22,12 @@ SERVER_CONNECT_RETRY_GAP=1000 QUERY_COUNT_OVER_10000=false JDBC_PROFILE=true LOG_LEVEL=DEBUG + +#timebase 샘플링을 할지 말지 여부 결정. +sampling.elapsedtimebase.enable= true +#timebase 샘플링 시의 1개 thread에 축정할 트레이스 데이터의 갯수. +sampling.elapsedtimebase.buffersize=20 +#timebase 샘플링시 discard.timelimit 의 시간보다 작을 경우 트레이스 데이터를 버릴지 말지 여부 +sampling.elapsedtimebase.discard=true +#timebase 샘플링시 discard.timelimit 해당 시간보다 빨리 끝났을 경우 트레이스 데이터를 버려 버린다. +sampling.elapsedtimebase.discard.timelimit=1000 \ No newline at end of file