From b62af05bcfffa2cafb096b87eddd3ed27a014e49 Mon Sep 17 00:00:00 2001 From: Leo <414563035@qq.com> Date: Mon, 9 Dec 2024 19:42:04 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 65 ++++-- .../artlibs/autotrace4j/AutoTrace4j.java | 12 +- .../autotrace4j/context/TraceContext.java | 70 +------ .../autotrace4j/context/TraceInjector.java | 185 ++++++++++++++++++ .../autotrace4j/logger/LogConstants.java | 1 + .../autotrace4j/logger/LoggerFactory.java | 62 +++--- .../logger/appender/AsyncAppender.java | 10 +- ...reamAppender.java => ConsoleAppender.java} | 4 +- ...ultFileAppender.java => FileAppender.java} | 40 ++-- .../logger/layout/DefaultLayout.java | 10 +- .../autotrace4j/support/ModuleUtils.java | 2 +- .../autotrace4j/support/ThrowableUtils.java | 8 +- .../transformer/TransformListener.java | 30 +-- .../impl/CommonSimpleLogTransformer.java | 4 +- .../impl/Log4j2StringLayoutTransformer.java | 57 ++++++ .../impl/Log4jQuietWriterTransformer.java | 6 +- .../impl/LogbackLog4jAsyncTransformer.java | 15 +- .../impl/LogbackLog4jEventTransformer.java | 10 +- .../impl/LogbackOutStreamTransformer.java | 5 +- .../impl/jdk/JavaUtilLoggingTransformer.java | 4 +- .../artlibs/autotrace4j/LoggerTest.java | 117 +++++------ 21 files changed, 488 insertions(+), 229 deletions(-) create mode 100644 src/main/java/io/github/artlibs/autotrace4j/context/TraceInjector.java rename src/main/java/io/github/artlibs/autotrace4j/logger/appender/{DefaultPrintStreamAppender.java => ConsoleAppender.java} (93%) rename src/main/java/io/github/artlibs/autotrace4j/logger/appender/{DefaultFileAppender.java => FileAppender.java} (88%) create mode 100644 src/main/java/io/github/artlibs/autotrace4j/transformer/impl/Log4j2StringLayoutTransformer.java diff --git a/README.md b/README.md index fa73948..5662fc0 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ ## Auto Trace for Java -[](https://github.com/artlibs/autotrace4j/actions/workflows/testing.yml) [](https://maven-badges.herokuapp.com/maven-central/io.github.artlibs/autotrace4j/) [](https://github.com/artlibs/autotrace4j/releases) [](https://www.apache.org/licenses/LICENSE-2.0) +[](https://github.com/artlibs/autotrace4j/actions/workflows/testing.yml) [](https://github.com/artlibs/autotrace4j/releases) [](https://www.apache.org/licenses/LICENSE-2.0) `autotrace4j`是一个基于ByteBuddy编写的轻量级日志跟踪工具,其基本逻辑是在各个上下文当中通过代码增强关键节点来传递`trace id`,最后在日志输出时注入到输出结果当中,以实现日志的跟踪串联。 - 我们借鉴了SkyWalking的实现原理,使用ByteBuddy在各个上下文环节进行关键点增强来传递Trace ID。 - #### 易使用 - 基于Agent的方式来使用该工具,对业务代码无侵入。 + 基于Agent的方式来使用该工具,对业务代码无侵入、运维可在基础层面统一配置,业务方可无感知。 #### 轻量级 @@ -18,9 +16,26 @@ `autotrace4j`的使用非常简单,只需从[release](https://github.com/artlibs/autotrace4j/releases)中下载最新的agent jar包,在启动脚本中以agent方式运行: ```shell -$ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-domain.biz2.pkg2 -jar YourJar.jar # 省略其他无关参数 +$ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-domain.biz2.pkg2 -Dautotrace4j.log.enable=true -jar YourJar.jar # 省略其他无关参数 ``` +- 一般情况下不需要开启autotrace4j内部日志,即***不需要***`-Dautotrace4j.log.enable=true`,如果需要观测到增强过程增强了哪些类,或在调试autotrace4j时有需要,可开启该日志选项,其他选项可使用默认参数: + - `-Dautotrace4j.log.enable=true` 设置开启autotrace4j内部日志 + - `-Dautotrace4j.log.dir=/path/to/your/log/dir` 修改autotrace4j内部日志保存路径 + - `-Dautotrace4j.log.level=TRACE` (可选`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`)修改日志级别 + - `-Dautotrace4j.log.file.retention=5` 设置autotrace4j内部日志保留天数为5天 + - `-Dautotrace4j.log.file.size=10485760`设置单个文件大小为10M(`10*1024*1024=10485760`) + +#### 关于日志 + +可通过如下系统属性开启和设置日志来观察增强过程: + +- `autotrace4j.log.enable`:是否开启autotrace4j日志,默认`false` +- `autotrace4j.log.dir`:autotrace4j日志文件保存路径,默认为临时目录`java.io.tmpdir` +- `autotrace4j.log.level`:autotrace4j日志级别,默认为`DEBUG` +- `autotrace4j.log.file.retention`:autotrace4j日志文件保留时间,单位天,默认为`7`天 +- `autotrace4j.log.file.size`:autotrace4j日志文件大小限制,单位字节(`B`),默认为`0`表示不限制 + #### 关于`MDC` 可通过`slf4j`或者`log4j`的`MDC`获取当前上下文的Trace ID: @@ -33,7 +48,7 @@ $ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-dom ### 1、Thread - 针对Thread进行了增强,在创建线程时支持自动Trace跟踪: `java.lang.Thread` + 针对Thread进行了增强,在创建线程时支持自动传递当前Trace: `java.lang.Thread` ### 2、Thread Pool @@ -58,17 +73,18 @@ $ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-dom - `javax.servlet.Filter` - `javax.servlet.http.HttpServlet` -### 5、MessageQunue +### 5、Middleware - 目前支持阿里云ONS和RocketMQ在生产和消费时带上TraceId: + 支持阿里云ONS和RocketMQ在生产和消费时传递trace,支持Dubbo: - RocektMQ:`Producer` & `Consumer` - Aliyun ONS:`Producer` & `Consumer` -- Kafka:comming soon.... +- Dubbo:`org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter` + `org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter` -### 6、Scheduled Task +### 6、Scheduled - 支持XXL Job、Spring Scheduled定时任务、PowerJob在产生时生成TraceId: + 支持XXL Job、Spring Scheduled定时任务、PowerJob在产生时传递TraceId: - XxlJob Handler:`com.handler.com.xxl.job.core.IJobHandler` - Spring Schedule Task:`org.springframework.scheduling.annotation.Scheduled` @@ -76,19 +92,26 @@ $ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-dom ### 7、Logging - 支持在logback中输出日志时注入trace id进行输出: + 支持几个主流日志框架的最终输出,自动加入trace信息(主要针对Stream和RollingFile的字符串和JSON格式): -- Log4j:`log4j:log4j` -- logback:`ch.qos.logback:logback-core` -- Java loggin:`java.util.logging` +- `JUL`、`Log4j`、`Logback`、`Log4j2` -### 8、Middleware +## Contribute - 支持如下中间件的增强 +欢迎贡献你的代码(`Fork` & `Pull Request`),一起完善`autotrace4j`库! -- Dubbo:`org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter` - `org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter` +- 如何增加支持: -## Contribute + 在`io.github.artlibs.autotrace4j.transformer`下仿照其他转换器新增 + +- 关于单元测试: + + 在`io.github.artlibs.autotrace4j.At4jTest`中参考其他案例增加单元测试 + +本地单测: + +```shell +$ export JAVA_HOME=/path/to/your/jdk21/home +$ make test +``` -欢迎贡献你的代码,一起完善`autotrace4j`库! diff --git a/src/main/java/io/github/artlibs/autotrace4j/AutoTrace4j.java b/src/main/java/io/github/artlibs/autotrace4j/AutoTrace4j.java index bc9140d..2e58ab3 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/AutoTrace4j.java +++ b/src/main/java/io/github/artlibs/autotrace4j/AutoTrace4j.java @@ -18,6 +18,8 @@ import java.util.List; import java.util.Objects; +import static io.github.artlibs.autotrace4j.logger.LoggerFactory.getLogFileDirectory; +import static io.github.artlibs.autotrace4j.logger.LoggerFactory.loggerEnabled; import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith; /** @@ -87,11 +89,17 @@ public static Transformer withBizScope(String bizPackages) { */ public void on(Instrumentation instrument) throws IOException, URISyntaxException { String contextPackage = AutoTrace4j.class.getPackage().getName() + ".context"; + + // inject context class into bootstrap loader ClassUtils.injectClassToBootStrap(instrument, contextPackage); - // note: this method must be called after injectClassToBootStrap, don't move it forward + // note: this method must be called after injectClassToBootStrap ModuleUtils.compatibleJavaModule(contextPackage); + if (loggerEnabled()) { + System.err.println("已开启[autotrace4j]日志:" + getLogFileDirectory()); + } + AgentBuilder builder = this.newAgentBuilder(); for (At4jTransformer transformer : loadTransformers()) { builder = builder.type(transformer.typeMatcher()).transform(transformer); @@ -99,8 +107,8 @@ public void on(Instrumentation instrument) throws IOException, URISyntaxExceptio builder.installOn(instrument); // init trace for main thread. - TraceContext.setTraceId(TraceContext.generate()); TraceContext.setSpanId(TraceContext.generate()); + TraceContext.setTraceId(TraceContext.generate()); } /** diff --git a/src/main/java/io/github/artlibs/autotrace4j/context/TraceContext.java b/src/main/java/io/github/artlibs/autotrace4j/context/TraceContext.java index a068498..9f9d8cd 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/context/TraceContext.java +++ b/src/main/java/io/github/artlibs/autotrace4j/context/TraceContext.java @@ -1,10 +1,9 @@ package io.github.artlibs.autotrace4j.context; -import java.util.Objects; import java.util.UUID; /** - * Trace context for SpanId, ParentSpanId, TraceId + * Trace context * * @author Fury * @since 2024-03-30 @@ -138,71 +137,4 @@ public static String generate() { .replace("-", ""); } - private static final String SEPARATOR = " - "; - private static final String QUOTE_COLON = "\":\""; - - /** - * Inject trace id into log message - * @param message String - * @return result - */ - public static String injectTraceId(String message) { - if (Objects.isNull(message) || Objects.isNull(TraceContext.getTraceId())) { - return message; - } - - try { - String trimMessage = message.trim(); - - // JSON FORMAT - if (trimMessage.startsWith("{") && trimMessage.endsWith("}")) { - return injectJsonString(message, trimMessage); - } - - // TODO: XML FORMAT - - // TODO: HTML FORMAT - - return injectString(message); - } catch (Exception e) { - e.printStackTrace(); - } - - return message; - } - - private static String injectString(String message) { - if (message.trim().isEmpty() || message.contains("[TraceId]" + TraceContext.getTraceId())) { - return message; - } - - String preTrimMessage = "[TraceId]" + TraceContext.getTraceId() + SEPARATOR; - if (Objects.nonNull(TraceContext.getSpanId())) { - preTrimMessage += "[SpanId]" + TraceContext.getSpanId() + SEPARATOR; - } - if (Objects.nonNull(TraceContext.getParentSpanId())) { - preTrimMessage += "[P-SpanId]" + TraceContext.getParentSpanId() + SEPARATOR; - } - - return preTrimMessage + message; - } - - private static String injectJsonString(String message, String trimMessage) { - if (message.contains(TraceContext.ATO_TRACE_ID) && message.contains(TraceContext.getTraceId())) { - return message; - } - - String injectedTraceFields = "\"" + TraceContext.ATO_TRACE_ID + QUOTE_COLON + TraceContext.getTraceId() + "\","; - if (Objects.nonNull(TraceContext.getSpanId())) { - injectedTraceFields = injectedTraceFields - + "\"" + TraceContext.ATO_SPAN_ID + QUOTE_COLON + TraceContext.getSpanId() + "\","; - } - if (Objects.nonNull(TraceContext.getParentSpanId())) { - injectedTraceFields = injectedTraceFields - + "\"" + TraceContext.ATO_PARENT_SPAN_ID + QUOTE_COLON + TraceContext.getParentSpanId() + "\","; - } - trimMessage = "{" + injectedTraceFields + trimMessage.substring(1); - - return message.endsWith("\n") ? trimMessage + "\n" : trimMessage; - } } diff --git a/src/main/java/io/github/artlibs/autotrace4j/context/TraceInjector.java b/src/main/java/io/github/artlibs/autotrace4j/context/TraceInjector.java new file mode 100644 index 0000000..88de501 --- /dev/null +++ b/src/main/java/io/github/artlibs/autotrace4j/context/TraceInjector.java @@ -0,0 +1,185 @@ +package io.github.artlibs.autotrace4j.context; + +import java.util.Objects; + +import static io.github.artlibs.autotrace4j.context.TraceContext.*; + +/** + * Trace Injector + * + * @author Fury + * @since 2024-12-08 + *
+ * All rights Reserved. + */ +public interface TraceInjector { + TraceInjector DF = new TraceInjector(){/* default trace injector */}; + + /** + * inject trace into log msg + * @param logMsg - + * @return - + */ + default String injectTrace(String logMsg) { + if (Objects.isNull(logMsg) || logMsg.trim().isEmpty()) { + return logMsg; + } + + try { + String trimMsg = logMsg.trim(); + for (Format fmt : Format.values()) { + if (fmt.detect(trimMsg)) { + return fmt.inject(logMsg, trimMsg); + } + } + + return Format.DEFAULT.inject(logMsg, logMsg.trim()); + } catch (Exception e) { + e.printStackTrace(); + } + + return logMsg; + } + + enum Format { + CSV { + /** + * {@inheritDoc} + */ + @Override + public boolean detect(String trimMsg) { + // TODO: not support yet + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String inject(String logMsg, String trimMsg) { + // TODO: not support yet + return logMsg; + } + }, + JSON { + /** + * {@inheritDoc} + */ + @Override + public boolean detect(String trimMsg) { + return trimMsg.startsWith("{") && trimMsg.endsWith("}"); + } + + /** + * {@inheritDoc} + */ + @Override + public String inject(String logMsg, String trimMsg) { + if (logMsg.contains(ATO_TRACE_ID) && logMsg.contains(getTraceId())) { + return logMsg; + } + + String injectedTraceFields = "\"" + ATO_TRACE_ID + + QUOTE_COLON + getTraceId() + "\","; + if (Objects.nonNull(getSpanId())) { + injectedTraceFields = injectedTraceFields + "\"" + ATO_SPAN_ID + + QUOTE_COLON + getSpanId() + "\","; + } + if (Objects.nonNull(getParentSpanId())) { + injectedTraceFields = injectedTraceFields + "\"" + ATO_PARENT_SPAN_ID + + QUOTE_COLON + getParentSpanId() + "\","; + } + trimMsg = "{" + injectedTraceFields + trimMsg.substring(1); + + return logMsg.endsWith("\n") ? trimMsg + "\n" : trimMsg; + } + }, + XML { + /** + * {@inheritDoc} + */ + @Override + public boolean detect(String trimMsg) { + // TODO: not support yet + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String inject(String logMsg, String trimMsg) { + // TODO: not support yet + return logMsg; + } + }, + HTML { + /** + * {@inheritDoc} + */ + @Override + public boolean detect(String trimMsg) { + // TODO: not support yet + return false; + } + + /** + * {@inheritDoc} + */ + @Override + public String inject(String logMsg, String trimMsg) { + // TODO: not support yet + return logMsg; + } + }, + DEFAULT { + /** + * {@inheritDoc} + */ + @Override + public boolean detect(String trimMsg) { + // 默认当成纯文本字符串 + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public String inject(String logMsg, String trimMsg) { + if (logMsg.trim().isEmpty() || logMsg.contains("[TraceId]" + getTraceId())) { + return logMsg; + } + + String preTrimMessage = "[TraceId]" + getTraceId() + SEPARATOR; + if (Objects.nonNull(getSpanId())) { + preTrimMessage += "[SpanId]" + getSpanId() + SEPARATOR; + } + if (Objects.nonNull(getParentSpanId())) { + preTrimMessage += "[P-SpanId]" + getParentSpanId() + SEPARATOR; + } + + return preTrimMessage + logMsg; + } + }, + ; + + /** + * 检测文本是否是指定格式 + * @param trimMsg - + * @return - + */ + abstract boolean detect(String trimMsg); + + /** + * 注入trace到log消息中 + * @param logMsg - + * @param trimMsg - + * @return - + */ + abstract String inject(String logMsg, String trimMsg); + + private static final String SEPARATOR = " - "; + private static final String QUOTE_COLON = "\":\""; + } +} diff --git a/src/main/java/io/github/artlibs/autotrace4j/logger/LogConstants.java b/src/main/java/io/github/artlibs/autotrace4j/logger/LogConstants.java index 06d85a6..076e3a1 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/logger/LogConstants.java +++ b/src/main/java/io/github/artlibs/autotrace4j/logger/LogConstants.java @@ -16,6 +16,7 @@ private LogConstants(){} public static final String RIGHT_MIDDLE_BRACKET = "]"; public static final String CAUSED_BY = "Caused by: "; + public static final String SYSTEM_PROPERTY_LOG_ENABLE = "autotrace4j.log.enable"; public static final String SYSTEM_PROPERTY_LOG_DIR = "autotrace4j.log.dir"; public static final String SYSTEM_PROPERTY_LOG_LEVEL = "autotrace4j.log.level"; public static final String SYSTEM_PROPERTY_LOG_FILE_RETENTION = "autotrace4j.log.file.retention"; diff --git a/src/main/java/io/github/artlibs/autotrace4j/logger/LoggerFactory.java b/src/main/java/io/github/artlibs/autotrace4j/logger/LoggerFactory.java index 2472e74..eb1f727 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/logger/LoggerFactory.java +++ b/src/main/java/io/github/artlibs/autotrace4j/logger/LoggerFactory.java @@ -1,16 +1,19 @@ package io.github.artlibs.autotrace4j.logger; import io.github.artlibs.autotrace4j.logger.appender.AppenderCombiner; -import io.github.artlibs.autotrace4j.logger.appender.DefaultFileAppender; -import io.github.artlibs.autotrace4j.logger.appender.DefaultPrintStreamAppender; +import io.github.artlibs.autotrace4j.logger.appender.FileAppender; +import io.github.artlibs.autotrace4j.logger.appender.ConsoleAppender; import io.github.artlibs.autotrace4j.logger.event.Level; import io.github.artlibs.autotrace4j.logger.event.LogEvent; import io.github.artlibs.autotrace4j.logger.layout.DefaultLayout; import io.github.artlibs.autotrace4j.support.SystemUtils; +import java.nio.file.Path; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import static io.github.artlibs.autotrace4j.logger.LogConstants.*; + /** * 功能:日志工厂 *
@@ -35,35 +38,50 @@ private LoggerFactory(){} static { // appender set APPENDER_COMBINER = new AppenderCombiner<>(); - DefaultPrintStreamAppender defaultPrintStreamAppender = new DefaultPrintStreamAppender(new DefaultLayout(), System.out, System.err); - defaultPrintStreamAppender.start(); - APPENDER_COMBINER.addAppender(defaultPrintStreamAppender); - SystemUtils.getSysPropertyPath(LogConstants.SYSTEM_PROPERTY_LOG_DIR) - .ifPresent(path -> { - DefaultFileAppender defaultFileAppender = new DefaultFileAppender( - new DefaultLayout(), - path, - SystemUtils - .getSysPropertyInteger(LogConstants.SYSTEM_PROPERTY_LOG_FILE_RETENTION) - .orElse(LogConstants.DEFAULT_LOG_FILE_RETENTION), - SystemUtils - .getSysPropertyInteger(LogConstants.SYSTEM_PROPERTY_LOG_FILE_SIZE) - .orElse(LogConstants.DEFAULT_LOG_FILE_SIZE) - ); - defaultFileAppender.start(); - APPENDER_COMBINER.addAppender(defaultFileAppender); - }); + + if (loggerEnabled()) { + ConsoleAppender consoleAppender = new ConsoleAppender(new DefaultLayout(), System.out, System.err); + consoleAppender.start(); + APPENDER_COMBINER.addAppender(consoleAppender); + + FileAppender fileAppender = new FileAppender( + new DefaultLayout(), getLogFileDirectory(), + SystemUtils.getSysPropertyInteger(SYSTEM_PROPERTY_LOG_FILE_RETENTION) + .orElse(DEFAULT_LOG_FILE_RETENTION), + SystemUtils.getSysPropertyInteger(SYSTEM_PROPERTY_LOG_FILE_SIZE) + .orElse(DEFAULT_LOG_FILE_SIZE) + ); + fileAppender.start(); + APPENDER_COMBINER.addAppender(fileAppender); + } + APPENDER_COMBINER.start(); + // level set LEVEL = getLevelConfig(); } + public static boolean loggerEnabled() { + return Boolean.TRUE.equals(SystemUtils.getSysPropertyBool(SYSTEM_PROPERTY_LOG_ENABLE) + .orElse(Boolean.FALSE)); + } + + public static Path getLogFileDirectory() { + Path directory = SystemUtils.getSysPropertyPath(SYSTEM_PROPERTY_LOG_DIR) + .orElse(SystemUtils.getSysTempDir()); + if (!directory.endsWith("autotrace4j")) { + directory = directory.resolve("autotrace4j"); + } + + return directory; + } + private static Level getLevelConfig() { return Optional - .ofNullable(System.getProperty(LogConstants.SYSTEM_PROPERTY_LOG_LEVEL)) + .ofNullable(System.getProperty(SYSTEM_PROPERTY_LOG_LEVEL)) .map(String::toUpperCase) .map(Level::valueOf) - .orElse(Level.INFO); + .orElse(Level.DEBUG); } public static Logger getLogger(Class> clazz) { diff --git a/src/main/java/io/github/artlibs/autotrace4j/logger/appender/AsyncAppender.java b/src/main/java/io/github/artlibs/autotrace4j/logger/appender/AsyncAppender.java index 0aefad8..507e8d5 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/logger/appender/AsyncAppender.java +++ b/src/main/java/io/github/artlibs/autotrace4j/logger/appender/AsyncAppender.java @@ -29,7 +29,7 @@ protected AsyncAppender() { @Override public boolean start() { - new Thread(() -> { + Thread async = new Thread(() -> { while (true) { try { if (started()) { @@ -40,7 +40,13 @@ public boolean start() { System.err.println(ThrowableUtils.throwableToStr(e)); } } - }).start(); + }); + + // Fix: 设置成守护线程以防止主线程退出时阻止JVM的停止 + async.setDaemon(true); + + async.start(); + return super.start(); } diff --git a/src/main/java/io/github/artlibs/autotrace4j/logger/appender/DefaultPrintStreamAppender.java b/src/main/java/io/github/artlibs/autotrace4j/logger/appender/ConsoleAppender.java similarity index 93% rename from src/main/java/io/github/artlibs/autotrace4j/logger/appender/DefaultPrintStreamAppender.java rename to src/main/java/io/github/artlibs/autotrace4j/logger/appender/ConsoleAppender.java index 9e59864..89870b8 100644 --- a/src/main/java/io/github/artlibs/autotrace4j/logger/appender/DefaultPrintStreamAppender.java +++ b/src/main/java/io/github/artlibs/autotrace4j/logger/appender/ConsoleAppender.java @@ -16,12 +16,12 @@ *
* All rights Reserved.
*/
-public class DefaultPrintStreamAppender extends AsyncAppender
+ * @author Fury
+ * @since 2024-03-30
+ *
+ * All rights Reserved.
+ */
+public class Log4j2StringLayoutTransformer extends AbsVisitorTransformer {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ElementMatcher super TypeDescription> typeMatcher() {
+ // log4j2: org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender
+ // method: directEncodeEvent & writeByteArrayToManager -> layout:encode & layout:toByteArray
+ // StringLayout有诸多实现:pattern, json, xml, yaml, csv等等,需要注意可能的破坏格式
+ return hasSuperType(named("org.apache.logging.log4j.core.layout.Encoder"));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected MethodMatcherHolder methodMatchers() {
+ return ofMatcher(isPublic()
+ .and(named("encode"))
+ .and(takesArgument(0, StringBuilder.class))
+ .and(takesArgument(1, hasSuperType(named("org.apache.logging.log4j.core.layout.ByteBufferDestination"))))
+ .and(returns(void.class))
+ );
+ }
+
+ /**
+ * OnMethodExit
+ * @param builder -
+ */
+ @Advice.OnMethodEnter
+ public static void adviceOnMethodEnter(
+ @Advice.Argument(value = 0, typing = Assigner.Typing.DYNAMIC
+ , readOnly = false) StringBuilder builder) {
+ builder = new StringBuilder(TraceInjector.DF.injectTrace(builder.toString()));
+ }
+
+}
diff --git a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/Log4jQuietWriterTransformer.java b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/Log4jQuietWriterTransformer.java
index fa09f6d..1479d5c 100644
--- a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/Log4jQuietWriterTransformer.java
+++ b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/Log4jQuietWriterTransformer.java
@@ -1,16 +1,16 @@
package io.github.artlibs.autotrace4j.transformer.impl;
+import io.github.artlibs.autotrace4j.context.TraceInjector;
import io.github.artlibs.autotrace4j.transformer.abs.AbsVisitorTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
-import static io.github.artlibs.autotrace4j.context.TraceContext.injectTraceId;
import static net.bytebuddy.matcher.ElementMatchers.*;
/**
- * Log4j 增强转换器
+ * Log4j的输出注入
*
* @author Fury
* @since 2024-03-30
@@ -46,7 +46,7 @@ protected MethodMatcherHolder methodMatchers() {
public static void adviceOnMethodEnter(
@Advice.Argument(value = 0, typing = Assigner.Typing.DYNAMIC
, readOnly = false) String message) {
- message = injectTraceId(message);
+ message = TraceInjector.DF.injectTrace(message);
}
}
diff --git a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jAsyncTransformer.java b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jAsyncTransformer.java
index 7d47165..c8cf8dc 100644
--- a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jAsyncTransformer.java
+++ b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jAsyncTransformer.java
@@ -27,8 +27,12 @@ public class LogbackLog4jAsyncTransformer extends AbsVisitorTransformer {
*/
@Override
public ElementMatcher super TypeDescription> typeMatcher() {
- return named("ch.qos.logback.core.spi.AppenderAttachableImpl")
- .or(named("org.apache.log4j.helpers.AppenderAttachableImpl"));
+ return // logback - appendLoopOnAppenders
+ named("ch.qos.logback.core.spi.AppenderAttachableImpl")
+ // log4j - appendLoopOnAppenders
+ .or(named("org.apache.log4j.helpers.AppenderAttachableImpl"))
+ // log4j2 -
+ .or(hasSuperType(named("org.apache.logging.log4j.core.config.AppenderControl")));
}
/**
@@ -36,8 +40,11 @@ public ElementMatcher super TypeDescription> typeMatcher() {
*/
@Override
protected MethodMatcherHolder methodMatchers() {
- return ofMatcher(isPublic().and(named("appendLoopOnAppenders"))
- .and(returns(int.class)));
+ return ofMatcher(isPublic()
+ // logback & log4j
+ .and(named("appendLoopOnAppenders").and(returns(int.class)))
+ // log4j2
+ .or(named("callAppender").and(returns(void.class))));
}
@Advice.OnMethodEnter
diff --git a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jEventTransformer.java b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jEventTransformer.java
index ae98126..3c10aa1 100644
--- a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jEventTransformer.java
+++ b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackLog4jEventTransformer.java
@@ -7,7 +7,7 @@
import static net.bytebuddy.matcher.ElementMatchers.*;
/**
- * Logback/Log4j - LoggingEvent 增强转换器
+ * Logback/Log4j/Log4j2 - LoggingEvent 增强转换器
*
* @author Fury
* @since 2024-03-30
@@ -23,8 +23,12 @@ public class LogbackLog4jEventTransformer extends AbsVisitorTransformer.AbsConst
@Override
public ElementMatcher super TypeDescription> typeMatcher() {
return not(isInterface()).and(not(isAbstract())).and(
- hasSuperType(named("ch.qos.logback.classic.spi.ILoggingEvent"))
- .or(hasSuperType(named("org.apache.log4j.spi.LoggingEvent")))
+ // logback
+ hasSuperType(named("ch.qos.logback.classic.spi.ILoggingEvent")).or(
+ // log4j
+ hasSuperType(named("org.apache.log4j.spi.LoggingEvent"))
+ // log4j2
+ ).or( hasSuperType(named("org.apache.logging.log4j.core.LogEvent")) )
);
}
diff --git a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackOutStreamTransformer.java b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackOutStreamTransformer.java
index b10e7db..8406822 100644
--- a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackOutStreamTransformer.java
+++ b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/LogbackOutStreamTransformer.java
@@ -1,12 +1,12 @@
package io.github.artlibs.autotrace4j.transformer.impl;
+import io.github.artlibs.autotrace4j.context.TraceInjector;
import io.github.artlibs.autotrace4j.transformer.abs.AbsVisitorTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
-import static io.github.artlibs.autotrace4j.context.TraceContext.injectTraceId;
import static net.bytebuddy.matcher.ElementMatchers.*;
/**
@@ -24,6 +24,7 @@ public class LogbackOutStreamTransformer extends AbsVisitorTransformer {
*/
@Override
public ElementMatcher super TypeDescription> typeMatcher() {
+ // Supports FileAppender, RollingFileAppender, ConsoleAppender e.g.
return hasSuperType(named("ch.qos.logback.core.OutputStreamAppender"));
}
@@ -46,7 +47,7 @@ protected MethodMatcherHolder methodMatchers() {
public static void adviceOnMethodEnter(
@Advice.Argument(value = 0, typing = Assigner.Typing.DYNAMIC
, readOnly = false) byte[] byteArray) {
- byteArray = injectTraceId(new String(byteArray)).getBytes();
+ byteArray = TraceInjector.DF.injectTrace(new String(byteArray)).getBytes();
}
}
diff --git a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/jdk/JavaUtilLoggingTransformer.java b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/jdk/JavaUtilLoggingTransformer.java
index 5322448..b5c78de 100644
--- a/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/jdk/JavaUtilLoggingTransformer.java
+++ b/src/main/java/io/github/artlibs/autotrace4j/transformer/impl/jdk/JavaUtilLoggingTransformer.java
@@ -1,12 +1,12 @@
package io.github.artlibs.autotrace4j.transformer.impl.jdk;
+import io.github.artlibs.autotrace4j.context.TraceInjector;
import io.github.artlibs.autotrace4j.transformer.abs.AbsVisitorTransformer;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
-import static io.github.artlibs.autotrace4j.context.TraceContext.injectTraceId;
import static net.bytebuddy.matcher.ElementMatchers.*;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@@ -40,6 +40,6 @@ protected MethodMatcherHolder methodMatchers() {
@Advice.OnMethodExit
public static void adviceOnMethodExit(@Advice.Return(readOnly = false
, typing = Assigner.Typing.DYNAMIC) String result) {
- result = injectTraceId(result);
+ result = TraceInjector.DF.injectTrace(result);
}
}
diff --git a/src/test/java/io/github/artlibs/autotrace4j/LoggerTest.java b/src/test/java/io/github/artlibs/autotrace4j/LoggerTest.java
index c27261e..5451ee3 100644
--- a/src/test/java/io/github/artlibs/autotrace4j/LoggerTest.java
+++ b/src/test/java/io/github/artlibs/autotrace4j/LoggerTest.java
@@ -1,7 +1,6 @@
package io.github.artlibs.autotrace4j;
import io.github.artlibs.autotrace4j.context.ReflectUtils;
-import io.github.artlibs.autotrace4j.logger.LogConstants;
import io.github.artlibs.autotrace4j.logger.Logger;
import io.github.artlibs.autotrace4j.logger.LoggerFactory;
import io.github.artlibs.autotrace4j.logger.appender.*;
@@ -34,6 +33,8 @@
import static io.github.artlibs.autotrace4j.context.ReflectUtils.getField;
import static io.github.artlibs.autotrace4j.context.ReflectUtils.getFieldValue;
+import static io.github.artlibs.autotrace4j.logger.LogConstants.*;
+import static io.github.artlibs.autotrace4j.logger.event.Level.DEBUG;
import static io.github.artlibs.autotrace4j.logger.event.Level.INFO;
import static io.github.artlibs.autotrace4j.support.FileUtils.deleteDirectoryRecursively;
@@ -47,13 +48,15 @@
*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LoggerTest {
-
- protected static final Level TEST_DEFAULT_LEVEL = INFO;
- protected static final Path LOG_DIR = SystemUtils.getSysTempDir().resolve("test").resolve(LoggerTest.class.getSimpleName());
+ protected static final Level TEST_DEFAULT_LEVEL = DEBUG;
+ protected static final Path LOG_DIR = SystemUtils.getSysTempDir()
+ .resolve("autotrace4j-test")
+ .resolve(LoggerTest.class.getSimpleName());
@BeforeAll
public static void beforeAll() throws IOException {
deleteDirectoryRecursively(LOG_DIR);
+ System.setProperty(SYSTEM_PROPERTY_LOG_ENABLE, "true");
}
@BeforeEach
@@ -77,7 +80,6 @@ public void benchMark() throws InterruptedException, IllegalAccessException {
System.out.println("toast: " + (endTime - startTime));
}
-
@Test
@Order(1)
void defaultLayout() {
@@ -107,30 +109,19 @@ void defaultLayout() {
);
}
- private static Logger newLogger(String name, Appender> appender, Level level) {
- try {
- ConstructorscheduleAtFixedRate
方法定时清理,但鉴于上诉的'良好效果',不做此修改。
+ * @param date -
+ * @return -
+ */
private ScheduledFuture> triggerCleanTask(LocalDateTime date) {
return scheduledExecutorService.schedule(new CleanerTask(date, this), 0, TimeUnit.MILLISECONDS);
}
private Tuple2