Skip to content

Commit

Permalink
Set Maintainer
Browse files Browse the repository at this point in the history
  • Loading branch information
i36lib committed Dec 11, 2024
1 parent 1611d75 commit 66b2716
Show file tree
Hide file tree
Showing 63 changed files with 2,237 additions and 1,556 deletions.
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
$ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-domain.biz2.pkg2 -jar YourJar.jar # 省略其他无关参数
```

#### 关于`org.slf4j.MDC`
#### 关于`MDC`

可通过slf4j的MDC获取当前上下文的TraceID
可通过`slf4j`或者`log4j``MDC`获取当前上下文的Trace ID

- 当通过 `MDC.get("X-Ato-Span-Id")`时返回当前上下文的 `SpanId`
- 当通过 `MDC.get("X-Ato-P-Span-Id")`时返回当前上下文的 `ParentSpanId`
Expand All @@ -33,9 +33,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

Expand Down Expand Up @@ -70,17 +68,26 @@ $ java -javaagent=/dir/to/autotrace4j.jar=com.your-domain.biz1.pkg1,com.your-dom

### 6、Scheduled Task

已支持XXL Job和Spring的Scheduled定时任务在产生时生成TraceId
支持XXL Job、Spring Scheduled定时任务、PowerJob在产生时生成TraceId

- XxlJob Handler:`com.handler.com.xxl.job.core.IJobHandler`
- Spring Schedule Task:`org.springframework.scheduling.annotation.Scheduled`
- PowerJob Processor:`tech.powerjob.worker.core.processor.sdk.BasicProcessor`

### 7、Logging

目前支持在logback中输出日志时注入trace id进行输出:
支持在logback中输出日志时注入trace id进行输出:

- Log4j:`log4j:log4j`
- logback:`ch.qos.logback:logback-core`
- Java loggin:`java.util.logging`

### 8、Middleware

​ 支持如下中间件的增强

- Dubbo:`org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter`
`org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter`

## Contribute

Expand Down
19 changes: 15 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

<groupId>io.github.artlibs</groupId>
<artifactId>autotrace4j</artifactId>
<version>0.1.3</version>
<version>0.2.0</version>
<packaging>jar</packaging>

<url>https://github.com/artlibs/autotrace4j</url>
<description>An auto trace agent base on byte-buddy for Java.</description>

<properties>
<premain.class>io.github.artlibs.autotrace4j.AutoTrace4j</premain.class>
<buddy.shaded.patten>io.github.artlibs.autotrace4j.bytebuddy</buddy.shaded.patten>
<buddy.shaded.patten>io.github.artlibs.autotrace4j.jar.bytebuddy</buddy.shaded.patten>
<junit-jupiter-engine.version>5.8.1</junit-jupiter-engine.version>
<bytebuddy.version>1.14.13</bytebuddy.version>
<maven-jar.version>2.3.2</maven-jar.version>
Expand Down Expand Up @@ -59,7 +60,7 @@
<version>2.0.32</version>
<scope>test</scope>
</dependency>
<!-- for interceptor testing -->
<!-- for transformer testing -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
Expand Down Expand Up @@ -108,7 +109,7 @@
<email>[email protected]</email>
<url>https://github.com/i36lib</url>
<roles>
<role>developer</role>
<role>Maintainer</role>
</roles>
<timezone>+8</timezone>
</developer>
Expand All @@ -132,6 +133,16 @@
</roles>
<timezone>+8</timezone>
</developer>
<developer>
<id>orangewest</id>
<name>orangewest</name>
<email>[email protected]</email>
<url>https://github.com/orangewest</url>
<roles>
<role>developer</role>
</roles>
<timezone>+8</timezone>
</developer>
</developers>

<issueManagement>
Expand Down
187 changes: 139 additions & 48 deletions src/main/java/io/github/artlibs/autotrace4j/AutoTrace4j.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
package io.github.artlibs.autotrace4j;

import io.github.artlibs.autotrace4j.interceptor.Transformer;
import io.github.artlibs.autotrace4j.context.TraceContext;
import io.github.artlibs.autotrace4j.exception.LoadInterceptorException;
import io.github.artlibs.autotrace4j.transformer.At4jTransformer;
import io.github.artlibs.autotrace4j.transformer.TransformListener;
import io.github.artlibs.autotrace4j.support.ClassUtils;
import io.github.artlibs.autotrace4j.support.JavaModuleUtils;
import net.bytebuddy.utility.JavaModule;
import io.github.artlibs.autotrace4j.support.Constants;
import io.github.artlibs.autotrace4j.support.ModuleUtils;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static io.github.artlibs.autotrace4j.support.JavaModuleUtils.getOwnModule;
import static io.github.artlibs.autotrace4j.support.JavaModuleUtils.notJavaModule;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;

/**
* Auto Trace for Java
*
* Auto Trace Agent for Java.
* <p>
* AutoTrace4j 是一个借鉴 SkyWalking 基于 ByteBuddy 字节码增强框架实现的
* 轻量级日志串联追踪组件。其通过 Java Agent 的方式进行使用,通过对逻辑流当中
* 的关键节点进行增强(生成Trace ID、传递Trace ID),无侵入地实现链路日志串联。
* <p>
* @author Fury
* @since 2024-03-30
* <p>
Expand All @@ -25,61 +36,141 @@ public final class AutoTrace4j {
private AutoTrace4j(){}

/**
* Java Attach agentmain
* Java Agent 入口
*
* @param enhancePackages enhance packages
* @param bizPackages 业务包前缀,用以辅助筛选增强范围
* @param instrument Instrumentation
*/
public static void agentmain(String enhancePackages, Instrumentation instrument) throws IOException, URISyntaxException {
premain(enhancePackages, instrument);
public static void premain(String bizPackages, Instrumentation instrument) throws IOException, URISyntaxException {
agentmain(bizPackages, instrument);
}

/**
* Java Agent premain
* Attach API 入口
*
* @param enhancePackages enhance packages
* @param bizPackages 业务包前缀,用以辅助筛选增强范围
* @param instrument Instrumentation
*/
public static void premain(String enhancePackages, Instrumentation instrument) throws IOException, URISyntaxException {
if (Objects.isNull(enhancePackages) || enhancePackages.trim().isEmpty()) {
public static void agentmain(String bizPackages, Instrumentation instrument) throws IOException, URISyntaxException {
if (Objects.isNull(bizPackages) || bizPackages.trim().isEmpty()) {
throw new IllegalArgumentException(
"Please specify your java package name prefix (Agent parameter)" +
" to determine the enhancement scope; such as\n"
+ "-javaagent:/dir/to/autotrace4j.jar=com.your-domain1.pkg1,com.your-domain2.pkg2");
"Please specify your biz package prefix (Agent parameter)" +
" to determine the biz intercept scope; e.g.\n"
+ "-javaagent:/dir/to/autotrace4j.jar=com.your-domain1.pkg,com.your-domain2.pkg");
}
String ctxPackagePrefix = AutoTrace4j.class.getPackage().getName() + ".context";
ClassUtils.injectClassToBootStrap(instrument, ctxPackagePrefix);
//note: this method must be called after injectClassToBootStrap, don't move it forward
compatibleJavaModule(ctxPackagePrefix);
// do intercept
Transformer.intercept(enhancePackages).on(instrument);

AutoTrace4j.Transformer.withBizScope(bizPackages).on(instrument);
}

private static void compatibleJavaModule(String ctxPackagePrefix) {
if (notJavaModule()) {
return;
public static class Transformer {
private Transformer(){}

private static List<At4jTransformer> transformerList = null;
private static ElementMatcher.Junction<TypeDescription> bizScopeJunction;

/**
* 业务类范围限定,用以辅助筛选增强范围
* <p>
* @param bizPackages 业务包前缀,用以辅助筛选增强范围
* @return TraceBuilder
*/
public static Transformer withBizScope(String bizPackages) {
setBizScopeJunction(bizPackages);
return new Transformer();
}

final String[] agentNecessaryJavaBasePackages = {
"sun.net.www.protocol.http",
"sun.net.www",
"jdk.internal.loader",
};

// java9+: open the system module to us
JavaModuleUtils.openJavaBaseModuleForAnotherModule(
agentNecessaryJavaBasePackages,
JavaModule.ofType(JavaModuleUtils.MethodLockSupport.class)
);
// java9+: remove the package - module mapping to avoid double context package's class
// note: this method need the privilege of 'jdk.internal.loader' package
JavaModuleUtils.removePkgModuleMapping(new String[]{ ctxPackagePrefix });
// java9+: open the system module to bootstrap's unnamed module
// we need found the unnamed module by ModuleLocator
JavaModuleUtils.openJavaBaseModuleForAnotherModule(
agentNecessaryJavaBasePackages,
getOwnModule(ctxPackagePrefix + ".jdk.ModuleLocator")
);
}
/**
* 在该 Instrumentation 上执行转换器的注入
* <p>
* @param instrument Instrumentation
* @throws IOException -
*/
public void on(Instrumentation instrument) throws IOException, URISyntaxException {
String contextPackage = AutoTrace4j.class.getPackage().getName() + ".context";
ClassUtils.injectClassToBootStrap(instrument, contextPackage);

// note: this method must be called after injectClassToBootStrap, don't move it forward
ModuleUtils.compatibleJavaModule(contextPackage);

AgentBuilder builder = this.newAgentBuilder();
for (At4jTransformer transformer : loadTransformers()) {
builder = builder.type(transformer.typeMatcher()).transform(transformer);
}
builder.installOn(instrument);

// init trace for main thread.
TraceContext.setTraceId(TraceContext.generate());
TraceContext.setSpanId(TraceContext.generate());
}

/**
* 获取业务范围判断器
* <p>
* @return Junction
*/
public static ElementMatcher.Junction<TypeDescription> getBizScopeJunction() {
return bizScopeJunction;
}

/**
* 创建一个 ByteBuddy AgentBuilder 实例,忽略掉部分转换筛选范围:
* - com.intellij.rt.*
* - jdk.jfr.*
* - io.github.artlibs.autotrace4j.*
* <p>
* @return AgentBuilder 一个 ByteBuddy Agent Builder
*/
private AgentBuilder newAgentBuilder() {
return new AgentBuilder.Default()
.ignore(nameStartsWith("com.intellij.rt.")
.or(nameStartsWith("jdk.jfr."))
.or(nameStartsWith(AutoTrace4j.class.getPackage().getName()))
)
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.InjectionStrategy.UsingUnsafe.INSTANCE)
.with(new TransformListener());
}

/**
* 构建业务类范围限定的判断器实例
* <p>
* @param bizPackages 业务包前缀
*/
private static void setBizScopeJunction(String bizPackages) {
for (String prefix : bizPackages.split(Constants.COMMA)) {
if (Objects.isNull(bizScopeJunction)) {
bizScopeJunction = nameStartsWith(prefix);
continue;
}
bizScopeJunction = bizScopeJunction.or(nameStartsWith(prefix));
}
}

/**
* 从指定包加载所有增强类并为其创建单例对象
* <p>
* @return 增强类实例列表
* @throws IOException -
* @throws URISyntaxException -
*/
private static List<At4jTransformer> loadTransformers() throws IOException, URISyntaxException {
if (Objects.nonNull(transformerList) && !transformerList.isEmpty()) {
return transformerList;
}

transformerList = new ArrayList<>(64);
ClassUtils.walkClassFiles((path, classCanonicalName) -> {
try {
Class<?> clazz = Class.forName(classCanonicalName);
if (At4jTransformer.class.isAssignableFrom(clazz)) {
transformerList.add((At4jTransformer) clazz.getDeclaredConstructor().newInstance());
}
} catch (Exception e) {
throw new LoadInterceptorException(e);
}
}, At4jTransformer.class.getPackage().getName() + ".impl", true);

return transformerList;
}
}
}
Loading

0 comments on commit 66b2716

Please sign in to comment.