diff --git a/pom.xml b/pom.xml
index d3d4eec..7a93d28 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,76 +1,90 @@
- 4.0.0
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ 4.0.0
- com.wenshuo
- javaagent
- 2.1.2
- jar
+ com.wenshuo
+ javaagent
+ 2.1.2
+ jar
- javaagent
- 基于javaagent技术来记录方法执行次数和时间
- https://github.com/dingjs/javaagent
+ javaagent
+ 基于javaagent技术来记录方法执行次数和时间
+ https://github.com/dingjs/javaagent
-
- UTF-8
- 1.6
- UTF-8
-
-
-
- dingjsh
- 丁建水
- 47954233@qq.com
-
-
-
-
- Apache License, Version 2.0
- https://www.apache.org/licenses/LICENSE-2.0.txt
- repo
-
-
+
+ UTF-8
+ 1.6
+ UTF-8
+
+
+
+ dingjsh
+ 丁建水
+ 47954233@qq.com
+
+
+
+
+ Apache License, Version 2.0
+ https://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.3.0
-
-
-
- com.wenshuo.agent.Agent
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.8.1
-
-
- ${project.build.target}
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.3.0
+
+
+
+ com.wenshuo.agent.Agent
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ ${project.build.target}
+
+
+
+
-
+
+
+ com.sun
+ tools
+ ${java.version}
+ system
+ true
+ ${java.home}/../lib/tools.jar
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.36
+ compile
+ true
+
- com.sun
- tools
- ${java.version}
- system
+ commons-logging
+ commons-logging
+ 1.2
+ compile
true
- ${java.home}/../lib/tools.jar
-
- junit
- junit
- 4.13.2
- test
-
-
+
diff --git a/src/main/java/com/wenshuo/agent/Agent.java b/src/main/java/com/wenshuo/agent/Agent.java
index c32f651..4397784 100644
--- a/src/main/java/com/wenshuo/agent/Agent.java
+++ b/src/main/java/com/wenshuo/agent/Agent.java
@@ -4,8 +4,13 @@
* Copyright 2015 wenshuo, Inc. All rights reserved.
* wenshuo PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
+
package com.wenshuo.agent;
+
import java.lang.instrument.Instrumentation;
+
+import com.wenshuo.agent.applog.AppLogFactory;
+import com.wenshuo.agent.applog.IAppLog;
import com.wenshuo.agent.log.ExecuteLogUtils;
import com.wenshuo.agent.transformer.AgentLogClassFileTransformer;
@@ -16,10 +21,12 @@
*/
public class Agent {
+ private static IAppLog log = AppLogFactory.getAppLog(Agent.class);
+
public static void premain(String agentArs, Instrumentation inst) {
- System.out.println("javaagent启动成功,将自动记录方法的执行次数和时间");
// 初始化配置
ConfigUtils.initProperties(agentArs);
+ log.info("javaagent启动成功,将自动记录方法的执行次数和时间,日志文件路径:" + ConfigUtils.getLogFileName());
ExecuteLogUtils.init();
inst.addTransformer(new AgentLogClassFileTransformer());
}
diff --git a/src/main/java/com/wenshuo/agent/ConfigUtils.java b/src/main/java/com/wenshuo/agent/ConfigUtils.java
index 400a9be..e086fc2 100644
--- a/src/main/java/com/wenshuo/agent/ConfigUtils.java
+++ b/src/main/java/com/wenshuo/agent/ConfigUtils.java
@@ -7,6 +7,9 @@
import java.util.Properties;
import java.util.Set;
+import com.wenshuo.agent.applog.AppLogFactory;
+import com.wenshuo.agent.applog.IAppLog;
+
/**
* 获取配置信息
* ConfigUtils
@@ -24,6 +27,8 @@ public class ConfigUtils {
private static Set excludeClassRegexs;
+ private static IAppLog log = AppLogFactory.getAppLog(ConfigUtils.class);
+
private ConfigUtils() {
super();
}
@@ -49,7 +54,7 @@ private static Properties getProperties(String propertiesFileName) {
input = ConfigUtils.class.getClassLoader().getResourceAsStream("agent.properties");
properties.load(input);
} catch (Exception e) {
- System.err.println("未找到默认配置");
+ log.warn("未找到默认配置");
} finally {
AgentUtils.closeQuietly(input);
}
@@ -58,7 +63,7 @@ private static Properties getProperties(String propertiesFileName) {
input = new FileInputStream(propertiesFileName);
properties.load(input);
} catch (Exception e) {
- System.err.println(e);
+ log.error("解析配置文件出错:" + propertiesFileName, e);
} finally {
AgentUtils.closeQuietly(input);
}
@@ -158,4 +163,5 @@ public static boolean isUsingNanoTime() {
String value = getProperty(ConfigConsts.LOG_TIME_NANO);
return "true".equalsIgnoreCase(value);
}
+
}
diff --git a/src/main/java/com/wenshuo/agent/applog/AppLogFactory.java b/src/main/java/com/wenshuo/agent/applog/AppLogFactory.java
new file mode 100644
index 0000000..4283064
--- /dev/null
+++ b/src/main/java/com/wenshuo/agent/applog/AppLogFactory.java
@@ -0,0 +1,52 @@
+/**
+ * @projectName javaagent
+ * @package com.wenshuo.agent.applog
+ * @className com.wenshuo.agent.applog.IAppLogFactory
+ * @copyright Copyright 2023 Thunisoft, Inc All rights reserved.
+ */
+
+package com.wenshuo.agent.applog;
+
+/**
+ * AppLogFactory
+ *
+ * @author dingjsh
+ * @description javaagent日志工厂类
+ * @date 2023-10-16 11:49
+ * @since 2.1.3
+ */
+public class AppLogFactory {
+
+ private static final String SLF4J_FACTORY_CLASS_NAME = "org.slf4j.LoggerFactory";
+
+ private static final String COMMONS_LOGGING_FACTORY_CLASS_NAME = "org.apache.commons.logging.LogFactory";
+
+ /**
+ * 如果工程中有slf4j,则采用slf4j输出日志,如果有commons-logging,则采用commons-logging,否则用console
+ * @param clazz
+ * @return javaagent日志对象
+ */
+ public static IAppLog getAppLog(Class> clazz) {
+ if (isClassPresent(SLF4J_FACTORY_CLASS_NAME, Thread.currentThread().getContextClassLoader())) {
+ return new Slf4jAppLog(clazz);
+ } else if (isClassPresent(COMMONS_LOGGING_FACTORY_CLASS_NAME, Thread.currentThread().getContextClassLoader())) {
+ return new CommonsLoggingAppLog(clazz);
+ } else {
+ return new ConsoleAppLog();
+ }
+ }
+
+ protected static boolean isClassPresent(String className, ClassLoader classLoader) {
+ try {
+ resolve(className, classLoader);
+ return true;
+ } catch (Throwable throwable) {
+ return false;
+ }
+ }
+
+ protected static Class> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
+ return classLoader != null ? Class.forName(className, false, classLoader) : Class.forName(className);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/applog/CommonsLoggingAppLog.java b/src/main/java/com/wenshuo/agent/applog/CommonsLoggingAppLog.java
new file mode 100644
index 0000000..f832c0d
--- /dev/null
+++ b/src/main/java/com/wenshuo/agent/applog/CommonsLoggingAppLog.java
@@ -0,0 +1,50 @@
+/**
+ * @projectName javaagent
+ * @package com.wenshuo.agent.applog
+ * @className com.wenshuo.agent.applog.CommonsLoggingAppLog
+ * @copyright Copyright 2023 Thunisoft, Inc All rights reserved.
+ */
+
+package com.wenshuo.agent.applog;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * CommonsLoggingAppLog
+ *
+ * @author dingjsh
+ * @description
+ * @date 2023-10-16 17:35
+ * @since 2.1.3
+ */
+class CommonsLoggingAppLog implements IAppLog {
+
+ private Log log;
+
+ public CommonsLoggingAppLog(Class> clazz) {
+ log = LogFactory.getLog(clazz);
+ }
+
+ @Override
+ public void info(String message) {
+ log.info(message);
+
+ }
+
+ @Override
+ public void warn(String message) {
+ log.warn(message);
+ }
+
+ @Override
+ public void error(String message) {
+ log.error(message);
+ }
+
+ @Override
+ public void error(String message, Throwable t) {
+ log.error(message, t);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/applog/ConsoleAppLog.java b/src/main/java/com/wenshuo/agent/applog/ConsoleAppLog.java
new file mode 100644
index 0000000..d9011c8
--- /dev/null
+++ b/src/main/java/com/wenshuo/agent/applog/ConsoleAppLog.java
@@ -0,0 +1,40 @@
+/**
+ * @projectName javaagent
+ * @package com.wenshuo.agent.applog
+ * @className com.wenshuo.agent.applog.ConsoleAppLog
+ * @copyright Copyright 2023 Thunisoft, Inc All rights reserved.
+ */
+
+package com.wenshuo.agent.applog;
+
+/**
+ * ConsoleAppLog
+ *
+ * @author dingjsh
+ * @description
+ * @date 2023-10-16 17:37
+ * @since 2.1.3
+ */
+class ConsoleAppLog implements IAppLog {
+
+ @Override
+ public void info(String message) {
+ System.out.println("[info ] " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.out.println("[warn ] " + message);
+ }
+
+ @Override
+ public void error(String message) {
+ System.err.println("[error ] " + message);
+ }
+
+ @Override
+ public void error(String message, Throwable t) {
+ System.err.println("[error ] " + message);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/applog/IAppLog.java b/src/main/java/com/wenshuo/agent/applog/IAppLog.java
new file mode 100644
index 0000000..2aa9821
--- /dev/null
+++ b/src/main/java/com/wenshuo/agent/applog/IAppLog.java
@@ -0,0 +1,28 @@
+/**
+ * @projectName javaagent
+ * @package com.wenshuo.agent.applog
+ * @className com.wenshuo.agent.applog.IAppLog
+ * @copyright Copyright 2023 Thunisoft, Inc All rights reserved.
+ */
+
+package com.wenshuo.agent.applog;
+
+/**
+ * IAppLog
+ *
+ * @author dingjsh
+ * @description javaagent日志接口
+ * @date 2023-10-16 11:46
+ * @since 2.1.3
+ */
+public interface IAppLog {
+
+ void info(String message);
+
+ void warn(String message);
+
+ void error(String message);
+
+ void error(String message, Throwable t);
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/applog/Slf4jAppLog.java b/src/main/java/com/wenshuo/agent/applog/Slf4jAppLog.java
new file mode 100644
index 0000000..ed60c66
--- /dev/null
+++ b/src/main/java/com/wenshuo/agent/applog/Slf4jAppLog.java
@@ -0,0 +1,50 @@
+/**
+ * @projectName javaagent
+ * @package com.wenshuo.agent.applog
+ * @className com.wenshuo.agent.applog.Slf4jAppLog
+ * @copyright Copyright 2023 Thunisoft, Inc All rights reserved.
+ */
+
+package com.wenshuo.agent.applog;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Slf4jAppLog
+ *
+ * @author dingjsh
+ * @description
+ * @date 2023-10-16 16:58
+ * @since 2.1.3
+ */
+class Slf4jAppLog implements IAppLog {
+
+ private Logger log;
+
+ public Slf4jAppLog(Class> clazz) {
+ log = LoggerFactory.getLogger(clazz);
+ }
+
+ @Override
+ public void info(String message) {
+ log.info(message);
+
+ }
+
+ @Override
+ public void warn(String message) {
+ log.warn(message);
+ }
+
+ @Override
+ public void error(String message) {
+ log.error(message);
+ }
+
+ @Override
+ public void error(String message, Throwable t) {
+ log.error(message, t);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/log/ExecuteLogUtils.java b/src/main/java/com/wenshuo/agent/log/ExecuteLogUtils.java
index c1f9678..624d8c1 100644
--- a/src/main/java/com/wenshuo/agent/log/ExecuteLogUtils.java
+++ b/src/main/java/com/wenshuo/agent/log/ExecuteLogUtils.java
@@ -2,6 +2,7 @@
* @(#)ExecuteLogUtils.java 2015-7-27 下午05:57:01 javaagent Copyright 2015 wenshuo, Inc. All rights reserved. wenshuo
* PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
+
package com.wenshuo.agent.log;
import java.io.BufferedWriter;
@@ -24,6 +25,8 @@
import com.wenshuo.agent.AgentUtils;
import com.wenshuo.agent.ConfigUtils;
import com.wenshuo.agent.NamedThreadFactory;
+import com.wenshuo.agent.applog.AppLogFactory;
+import com.wenshuo.agent.applog.IAppLog;
/**
* ExecuteLogUtils
@@ -57,6 +60,8 @@ public class ExecuteLogUtils {
private static volatile boolean isInitialized = false;
+ private static final IAppLog log = AppLogFactory.getAppLog(ExecuteLogUtils.class);
+
private ExecuteLogUtils() {
super();
}
@@ -76,7 +81,7 @@ public static synchronized void init() {
logAvgExecuteTime = ConfigUtils.isLogAvgExecuteTime();
isUsingNanoTime = ConfigUtils.isUsingNanoTime();
if (AgentUtils.isBlank(logFileName)) {
- System.err.println("日志文件名为空");
+ log.error("日志文件名为空");
throw new RuntimeException("日志文件名为空");
}
setNextDateStartTimeMillis();
@@ -136,7 +141,7 @@ private static void logExecuteCounter(String className, String methodName, long
ConcurrentHashMap methodCounterMap = getOrCreateClassExecutesMapping(className);
long[] counter = methodCounterMap.get(methodName);
if (null == counter) {
- methodCounterMap.put(methodName, new long[]{1, executeTime});
+ methodCounterMap.put(methodName, new long[] {1, executeTime});
} else {
counter[0]++;
counter[1] = executeTime + counter[1];
@@ -179,7 +184,7 @@ private static void writeLog(String logValue, boolean newLine, long currTimeMill
counterLogWriter.newLine();
}
} catch (IOException e) {
- System.err.println(e);
+ log.error(e.getMessage(), e);
}
}
@@ -188,7 +193,7 @@ private static void flushLogAndClose() {
try {
counterLogWriter.flush();
} catch (IOException e) {
- System.err.println(e);
+ log.error(e.getMessage(), e);
} finally {
AgentUtils.closeQuietly(counterLogWriter);
counterLogWriter = null;
@@ -224,7 +229,7 @@ private static void initWriter() {
counterLogWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logFile, true), ENCODING),
BUFFER_SIZE);
} catch (IOException e) {
- System.err.println(e);
+ log.error(e.getMessage(), e);
throw new RuntimeException("无法初始化【" + logFileName + "】,建议您检查磁盘空间,或者手动删除该日志文件");
}
}
@@ -254,7 +259,7 @@ private static File getLogFile(String logFileName) throws IOException {
AgentUtils.forceMkdir(dirFile);
boolean created = logFile.createNewFile();
if (!created) {
- System.err.println("【" + logFileName + "】创建失败");
+ log.error("【" + logFileName + "】创建失败");
throw new RuntimeException("【" + logFileName + "】创建失败");
}
}
@@ -276,7 +281,7 @@ private static Date date2StartTime(Date date) {
try {
startTime = sdf.parse(dateStr + " 00:00:00");
} catch (ParseException e) {
- System.err.println(e);
+ log.error(e.getMessage(), e);
}
return startTime;
}
@@ -313,4 +318,5 @@ private static long removeJSONArrayEndBracket() throws IOException {
f.close();
return length;
}
+
}
\ No newline at end of file
diff --git a/src/main/java/com/wenshuo/agent/log/OutputLogRunnable.java b/src/main/java/com/wenshuo/agent/log/OutputLogRunnable.java
index 3a08620..09e4f47 100644
--- a/src/main/java/com/wenshuo/agent/log/OutputLogRunnable.java
+++ b/src/main/java/com/wenshuo/agent/log/OutputLogRunnable.java
@@ -4,27 +4,28 @@
* Copyright 2015 wenshuo, Inc. All rights reserved.
* wenshuo PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
+
package com.wenshuo.agent.log;
+import com.wenshuo.agent.applog.AppLogFactory;
+import com.wenshuo.agent.applog.IAppLog;
+
/**
* OutputLogRunnable
- *
+ *
* @author dingjsh
* @time 2015-7-28下午03:27:20
*/
public class OutputLogRunnable implements Runnable {
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Runnable#run()
- */
+ private static IAppLog log = AppLogFactory.getAppLog(OutputLogRunnable.class);
+
@Override
public void run() {
- try{
+ try {
ExecuteLogUtils.outputCounterLog();
- }catch(Exception e){
- System.err.println(e);
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
}
}
diff --git a/src/main/java/com/wenshuo/agent/transformer/AgentLogClassFileTransformer.java b/src/main/java/com/wenshuo/agent/transformer/AgentLogClassFileTransformer.java
index 545b231..6602f06 100644
--- a/src/main/java/com/wenshuo/agent/transformer/AgentLogClassFileTransformer.java
+++ b/src/main/java/com/wenshuo/agent/transformer/AgentLogClassFileTransformer.java
@@ -1,7 +1,16 @@
package com.wenshuo.agent.transformer;
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.security.ProtectionDomain;
+import java.util.Collections;
+import java.util.Set;
+import java.util.regex.Pattern;
+
import com.wenshuo.agent.ConfigUtils;
import com.wenshuo.agent.PojoDetector;
+import com.wenshuo.agent.applog.AppLogFactory;
+import com.wenshuo.agent.applog.IAppLog;
import com.wenshuo.agent.javassist.CannotCompileException;
import com.wenshuo.agent.javassist.ClassPool;
import com.wenshuo.agent.javassist.CtClass;
@@ -9,16 +18,10 @@
import com.wenshuo.agent.javassist.LoaderClassPath;
import com.wenshuo.agent.javassist.Modifier;
import com.wenshuo.agent.javassist.NotFoundException;
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.security.ProtectionDomain;
-import java.util.Collections;
-import java.util.Set;
-import java.util.regex.Pattern;
/**
* AgentLogClassFileTransformer 类增强,增加agent日志
- *
+ *
* @author dingjsh
* @time 2015-7-24上午09:53:44
*/
@@ -28,9 +31,10 @@ public class AgentLogClassFileTransformer implements ClassFileTransformer {
private static final String AGENT_PACKAGE_NAME = "com.wenshuo.agent";
+ private static IAppLog log = AppLogFactory.getAppLog(AgentLogClassFileTransformer.class);
public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ ProtectionDomain protectionDomain, byte[] classfileBuffer) {
byte[] byteCode = classfileBuffer;
className = className.replace('/', '.');
if (!isNeedLogExecuteInfo(className)) {
@@ -55,7 +59,7 @@ private byte[] aopLog(ClassLoader loader, String className, byte[] byteCode) {
}
byteCode = aopLog(cc, className, byteCode);
} catch (Exception ex) {
- System.err.println(ex);
+ log.error(ex.getMessage(), ex);
}
return byteCode;
}
@@ -91,19 +95,20 @@ private void aopLog(String className, CtMethod m) throws CannotCompileException
boolean isMethodStatic = Modifier.isStatic(m.getModifiers());
String aopClassName = isMethodStatic ? "\"" + className + "\"" : "this.getClass().getName()";
final String timeMethodStr
- = ConfigUtils.isUsingNanoTime() ? "java.lang.System.nanoTime()" : "java.lang.System.currentTimeMillis()";
+ = ConfigUtils.isUsingNanoTime() ? "java.lang.System.nanoTime()" : "java.lang.System.currentTimeMillis"
+ + "()";
// 避免变量名重复
m.addLocalVariable("dingjsh_javaagent_elapsedTime", CtClass.longType);
m.insertBefore("dingjsh_javaagent_elapsedTime = " + timeMethodStr + ";");
m.insertAfter("dingjsh_javaagent_elapsedTime = " + timeMethodStr + " - dingjsh_javaagent_elapsedTime;");
m.insertAfter(LOG_UTILS + ".log(" + aopClassName + ",\"" + m.getName()
- + "\",(long)dingjsh_javaagent_elapsedTime" + ");");
+ + "\",(long)dingjsh_javaagent_elapsedTime" + ");");
}
/**
* 是否需要记录执行信息
- *
+ *
* @param className 类名
* @return 是否需要记录执行信息
* @author dingjsh
@@ -152,4 +157,5 @@ private boolean isNeedLogExecuteInfo(String className) {
}
return isNeeded;
}
+
}