Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
1ee9697
v2.3.0-SNAPSHOT
observeralone Jun 30, 2025
81f1d11
adjust: delete build and core spring boot dependency
observeralone Jun 30, 2025
5fae999
feat: add commons-compress and JarFileArchive
observeralone Jul 1, 2025
bed6190
feat: add StreamHandler to JarFileArchive
observeralone Jul 1, 2025
02de369
delete: System.out.println
observeralone Jul 1, 2025
b15c84b
adjust: JarFileArchive
observeralone Jul 1, 2025
ad16bbc
adjust: JarFileArchive
observeralone Jul 2, 2025
28d69bb
test
observeralone Jul 2, 2025
b10d525
feat: add JarCache and replace JarFileArchive and JarUtils
observeralone Jul 2, 2025
1b331de
feat: use URLClassLoader replace spring LaunchedURLClassLoader
observeralone Jul 2, 2025
938223a
feat: delete spring dependency from root pom.xml
observeralone Jul 2, 2025
a3b6bdd
feat: add EaseAgentClassLoader
observeralone Jul 3, 2025
36903b3
feat: delete unused file and add explanation
observeralone Jul 3, 2025
859dae0
feat: set null to EaseAgentClassLoader parent
observeralone Jul 3, 2025
6feba01
reset: add externals to EaseAgentClassLoader and add StringSequence
observeralone Jul 4, 2025
35903cf
adjust: JarCache.tmpDir
observeralone Jul 4, 2025
8cc4cb8
feat: add codeVersions to Points
observeralone Jul 7, 2025
6e92e9a
test: add PluginRegistryTest.isVersion unit test
observeralone Jul 8, 2025
43c8c8d
remove: spring-webmvc dependency from httpservlet plugin
observeralone Jul 8, 2025
4321c8a
feat: load points before load ClassTransformation
observeralone Jul 9, 2025
65ecc00
fix: NPE
observeralone Jul 10, 2025
409c4fa
feat: use ClassUtils.isInstance for replase spring-boot dependency
observeralone Jul 10, 2025
ec87498
feat: support multi-version matching
observeralone Jul 11, 2025
9711205
feat: add code version default,jdk8 to HttpURLConnectionGetResponseCo…
observeralone Jul 11, 2025
d66c269
feat: add codeVersions default,spring-boot_2_x to resTemplate plugin
observeralone Jul 11, 2025
e4bd7bf
feat: add CodeVersion and use config runtime.code.version.points.xx=xx
observeralone Jul 11, 2025
4514d96
feat: add CodeVersion spring-boot:2.x.x to spring-gateway-plugin
observeralone Jul 11, 2025
98f238c
feat: remove httpservlet code version
observeralone Jul 11, 2025
6095cfd
feat: CodeVersion to ConfigConst and add code version to servicename
observeralone Jul 15, 2025
33178c6
feat: add tomcat plugin
observeralone Jul 16, 2025
caddd7a
feat: add tomcat trace interceptor
observeralone Jul 16, 2025
2f9efa1
fix: httpservlet test
observeralone Jul 17, 2025
979f98d
feat: add tomcat plugin metric,access,forwarded
observeralone Jul 17, 2025
38e4665
test: add tomcat plugin unit test
observeralone Jul 18, 2025
fca815a
feat: tomcat dependency from spring-boot-starter-tomcat
observeralone Jul 18, 2025
d7d4b6d
feat: package tomcat when jdk17 and add dependency for unit test
observeralone Jul 18, 2025
424f029
rename: tomcat to tomcat-jdk17
observeralone Jul 21, 2025
4aa1d95
feat: add plugin spring-boot-3.5.3 and spring-boot-rest-template-3.5.3
observeralone Jul 21, 2025
73ee942
feat: add plugin spring-boot-gateway-3.5.3
observeralone Jul 22, 2025
117b8df
feat: add spring-boot-gateway-3.5.3 advice
observeralone Jul 22, 2025
b8b20ba
feat: add spring-boot-gateway-3.5.3 tracing and unit test
observeralone Jul 22, 2025
8afe76a
fix: gateway GlobalFilterInterceptor and use init type
observeralone Jul 23, 2025
b25d782
feat: add plugin.observability.global.init.enabled=true
observeralone Jul 23, 2025
29d8a68
feat: add spring-boot-3.5.3 FORWARDED and METRIC and unit test
observeralone Jul 23, 2025
da649bd
feat: add jdk17 to workflows test
observeralone Jul 24, 2025
d236d9e
adjust: fix test
observeralone Jul 24, 2025
1aff77d
adjust: old gateway GlobalFilterInterceptor to init and check agent …
observeralone Jul 24, 2025
234d9ef
optimization: NonReentrantInterceptor.after
observeralone Jul 29, 2025
be4fedb
feat: add plugin httpurlconnection-jdk17
observeralone Jul 29, 2025
fa6b5cd
feat: add plugin httpurlconnection-jdk17 unit test
observeralone Jul 29, 2025
8c22ec6
feat: add plugin spring-boot-servicename-3.5.3
observeralone Jul 31, 2025
bfe9a40
feat: add gateway servicename
observeralone Aug 1, 2025
4e59f15
unit test: add servicename test
observeralone Aug 1, 2025
4fd1438
feat: add TypeFieldGetter and skip Interceptor when HttpURLConnection…
observeralone Aug 6, 2025
5c8fbe4
optimize: add hasInterface URLConnection.connect to HttpURLConnection…
observeralone Aug 6, 2025
c62bd7d
doc: add code version
observeralone Aug 7, 2025
3015f1b
feat: add spring-boot-3.x.x-demo.md
observeralone Aug 7, 2025
d4b66a2
fix: unit test
observeralone Aug 7, 2025
1953be0
feat: release 2.3.0
observeralone Aug 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
java-version: [ 8, 11, 16 ]
java-version: [ 8, 11, 16, 17 ]
java-distribution: [ adopt, adopt-openj9 ]

# Steps represent a sequence of tasks that will be executed as part of the job
Expand All @@ -53,4 +53,4 @@ jobs:

# Runs a single command using the runners shell
- name: Build with Maven
run: mvn clean package
run: mvn clean package
20 changes: 2 additions & 18 deletions build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<artifactId>easeagent</artifactId>
<groupId>com.megaease.easeagent</groupId>
<version>2.2.9</version>
<version>2.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand All @@ -38,23 +38,6 @@
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${version.spring-boot}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.megaease.easeagent</groupId>
<artifactId>metrics</artifactId>
Expand Down Expand Up @@ -209,6 +192,7 @@
<Premain-Class>com.megaease.easeagent.Main</Premain-Class>
<Bootstrap-Class>com.megaease.easeagent.StartBootstrap</Bootstrap-Class>
<Logging-Property>log4j.configurationFile</Logging-Property>
<Easeagent-Version>${version}</Easeagent-Version>
</manifestEntries>
</archive>
<archiverConfig>
Expand Down
7 changes: 6 additions & 1 deletion build/src/main/resources/agent.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ easeagent.server.enabled=true
easeagent.server.port=9900
# Enable health/readiness
easeagent.health.readiness.enabled=true
plugin.integrability.global.healthReady.enabled=true
# forwarded headers page
# Pass-through headers from the root process all the way to the end
# format: easeagent.progress.forwarded.headers={headerName}
Expand Down Expand Up @@ -36,6 +37,7 @@ observability.tracings.tag.response.headers.eg.1=X-EG-Retryer
observability.tracings.tag.response.headers.eg.2=X-EG-Rate-Limiter
observability.tracings.tag.response.headers.eg.3=X-EG-Time-Limiter
# -------------------- plugin global config ---------------------
plugin.observability.global.init.enabled=true
plugin.observability.global.tracing.enabled=true
plugin.observability.global.metric.enabled=true
plugin.observability.global.metric.interval=30
Expand Down Expand Up @@ -198,7 +200,7 @@ plugin.observability.redis.metric.url=/platform-metrics
# plugin.observability.springGateway.metric.appendType=kafka
#
# -------------------- request ---------------------
## httpclient tracing:httpclient and httpclient5
## httpclient tracing\uFF1Ahttpclient and httpclient5
# plugin.observability.httpclient.tracing.enabled=true
## okHttp tracing
# plugin.observability.okHttp.tracing.enabled=true
Expand Down Expand Up @@ -352,3 +354,6 @@ reporter.tracing.output.messageTimeout=1000
## final output url: http://127.0.0.10:9090/metric
#reporter.metric.sender.url=/metrics

## support spring boot 3.5.3: jdk17+3.5.3
#runtime.code.version.points.jdk=jdk17
#runtime.code.version.points.spring-boot=3.x.x
2 changes: 1 addition & 1 deletion config/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<artifactId>easeagent</artifactId>
<groupId>com.megaease.easeagent</groupId>
<version>2.2.9</version>
<version>2.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
import static com.megaease.easeagent.plugin.api.config.ConfigConst.*;

public class ConfigUtils {
private ConfigUtils() {}
private ConfigUtils() {
}

public static <R> void bindProp(String name, Config configs, BiFunction<Config, String, R> func, Consumer<R> consumer, R def) {
Runnable process = () -> {
Expand Down Expand Up @@ -134,12 +135,16 @@ public static String buildPluginProperty(String domain, String namespace, String
return String.format(PLUGIN_FORMAT, domain, namespace, id, property);
}

public static String buildCodeVersionKey(String key) {
return RUNTIME_CODE_VERSION_POINTS_PREFIX + key;
}

/**
* extract config item with a fromPrefix to and convert the prefix to 'toPrefix' for configuration Compatibility
*
* @param cfg config source map
* @param cfg config source map
* @param fromPrefix from
* @param toPrefix to
* @param toPrefix to
* @return Extracted and converted KV map
*/
public static Map<String, String> extractAndConvertPrefix(Map<String, String> cfg, String fromPrefix, String toPrefix) {
Expand All @@ -162,8 +167,9 @@ public static Map<String, String> extractAndConvertPrefix(Map<String, String> cf

/**
* Extract config items from config by prefix
* @param config config
* @param prefix prefix
*
* @param config config
* @param prefix prefix
* @return Extracted KV
*/
public static Map<String, String> extractByPrefix(Config config, String prefix) {
Expand Down
2 changes: 1 addition & 1 deletion context/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<artifactId>easeagent</artifactId>
<groupId>com.megaease.easeagent</groupId>
<version>2.2.9</version>
<version>2.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
8 changes: 1 addition & 7 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<artifactId>easeagent</artifactId>
<groupId>com.megaease.easeagent</groupId>
<version>2.2.9</version>
<version>2.3.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down Expand Up @@ -105,12 +105,6 @@
<artifactId>reactor-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${version.spring}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public static AgentBuilder getAgentBuilder(Configs config, boolean test) {
.with(AgentBuilder.LocationStrategy.ForClassLoader.STRONG
.withFallbackTo(ClassFileLocator.ForClassLoader.ofSystemLoader()));
AgentBuilder.Ignored ignore = builder.ignore(isSynthetic())
.or(nameStartsWith("sun."))
.or(nameStartsWith("sun.").and(not(nameStartsWith("sun.net.www.protocol.http")) ))
.or(nameStartsWith("com.sun."))
.or(nameStartsWith("brave."))
.or(nameStartsWith("zipkin2."))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@

package com.megaease.easeagent.core.plugin;

import com.megaease.easeagent.config.ConfigUtils;
import com.megaease.easeagent.config.Configs;
import com.megaease.easeagent.core.plugin.matcher.ClassTransformation;
import com.megaease.easeagent.core.plugin.matcher.MethodTransformation;
import com.megaease.easeagent.core.plugin.registry.PluginRegistry;
import com.megaease.easeagent.core.plugin.transformer.CompoundPluginTransformer;
import com.megaease.easeagent.core.plugin.transformer.DynamicFieldTransformer;
import com.megaease.easeagent.core.plugin.transformer.ForAdviceTransformer;
import com.megaease.easeagent.core.plugin.transformer.TypeFieldTransformer;
import com.megaease.easeagent.log4j2.Logger;
import com.megaease.easeagent.log4j2.LoggerFactory;
import com.megaease.easeagent.plugin.AgentPlugin;
import com.megaease.easeagent.plugin.interceptor.InterceptorProvider;
import com.megaease.easeagent.plugin.CodeVersion;
import com.megaease.easeagent.plugin.Ordered;
import com.megaease.easeagent.plugin.Points;
import com.megaease.easeagent.plugin.field.AgentDynamicFieldAccessor;
import com.megaease.easeagent.plugin.interceptor.InterceptorProvider;
import com.megaease.easeagent.plugin.utils.common.StringUtils;
import net.bytebuddy.agent.builder.AgentBuilder;

import java.util.*;
Expand All @@ -46,19 +50,27 @@ private PluginLoader() {

public static AgentBuilder load(AgentBuilder ab, Configs conf) {
pluginLoad();
pointsLoad(conf);
providerLoad();
Set<ClassTransformation> sortedTransformations = pointsLoad();
Set<ClassTransformation> sortedTransformations = classTransformationLoad();

for (ClassTransformation transformation : sortedTransformations) {
ab = ab.type(transformation.getClassMatcher(), transformation.getClassloaderMatcher())
.transform(compound(transformation.isHasDynamicField(), transformation.getMethodTransformations()));
.transform(compound(transformation.isHasDynamicField(), transformation.getMethodTransformations(), transformation.getTypeFieldAccessor()));
}
return ab;
}

public static void providerLoad() {
for (InterceptorProvider provider : BaseLoader.load(InterceptorProvider.class)) {
log.debug("loading provider:{}", provider.getClass().getName());
String pointsClassName = PluginRegistry.getPointsClassName(provider.getAdviceTo());
Points points = PluginRegistry.getPoints(pointsClassName);
if (points == null) {
log.debug("Unload provider:{}, can not found Points<{}>", provider.getClass().getName(), pointsClassName);
continue;
} else {
log.debug("Loading provider:{}", provider.getClass().getName());
}

try {
log.debug("provider for:{} at {}",
Expand All @@ -73,14 +85,14 @@ public static void providerLoad() {
}
}

public static Set<ClassTransformation> pointsLoad() {
List<Points> points = BaseLoader.load(Points.class);
public static Set<ClassTransformation> classTransformationLoad() {
Collection<Points> points = PluginRegistry.getPoints();
return points.stream().map(point -> {
try {
return PluginRegistry.register(point);
return PluginRegistry.registerClassTransformation(point);
} catch (Exception e) {
log.error(
"Unable to load points in [class {}]",
"Unable to load classTransformation in [class {}]",
point.getClass().getName(),
e);
return null;
Expand Down Expand Up @@ -111,12 +123,54 @@ public static void pluginLoad() {
}
}

public static void pointsLoad(Configs conf) {
for (Points points : BaseLoader.load(Points.class)) {
if (!isCodeVersion(points, conf)) {
continue;
} else {
log.info("Loading points [class Points<{}>]", points.getClass().getName());
}

try {
PluginRegistry.register(points);
} catch (Exception | LinkageError e) {
log.error(
"Unable to load extension [class {}]",
points.getClass().getName(),
e);
}
}
}

public static boolean isCodeVersion(Points points, Configs conf) {
CodeVersion codeVersion = points.codeVersions();
if (codeVersion.isEmpty()) {
return true;
}
String versionKey = ConfigUtils.buildCodeVersionKey(codeVersion.getKey());
Set<String> versions = new HashSet<>(conf.getStringList(versionKey));
if (versions.isEmpty()) {
versions = Points.DEFAULT_VERSIONS;
}
Set<String> pointVersions = codeVersion.getVersions();
for (String version : versions) {
if (pointVersions.contains(version)) {
return true;
}
}
log.info("Unload points [class Points<{}>], the config [{}={}] is not in Points.codeVersions()=[{}:{}]",
points.getClass().getCanonicalName(), versionKey, String.join(",", versions),
codeVersion.getKey(), String.join(",", codeVersion.getVersions()));
return false;
}


/**
* @param methodTransformations method matchers under a special classMatcher
* @return transform
*/
public static AgentBuilder.Transformer compound(boolean hasDynamicField,
Iterable<MethodTransformation> methodTransformations) {
Iterable<MethodTransformation> methodTransformations, String typeFieldAccessor) {
List<AgentBuilder.Transformer> agentTransformers = StreamSupport
.stream(methodTransformations.spliterator(), false)
.map(ForAdviceTransformer::new)
Expand All @@ -126,6 +180,10 @@ public static AgentBuilder.Transformer compound(boolean hasDynamicField,
agentTransformers.add(new DynamicFieldTransformer(AgentDynamicFieldAccessor.DYNAMIC_FIELD_NAME));
}

if (StringUtils.hasText(typeFieldAccessor)) {
agentTransformers.add(new TypeFieldTransformer(typeFieldAccessor));
}

return new CompoundPluginTransformer(agentTransformers);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ public class ClassTransformation implements Ordered {
private int order;
private Junction<TypeDescription> classMatcher;
private ElementMatcher<ClassLoader> classloaderMatcher;
private Set<MethodTransformation> methodTransformations;
private Set<MethodTransformation> methodTransformations;
private boolean hasDynamicField;
private String typeFieldAccessor;

public ClassTransformation(int order,
ElementMatcher<ClassLoader> classloaderMatcher,
Junction<TypeDescription> classMatcher,
Set<MethodTransformation> methodTransformations,
boolean hasDynamicField) {
boolean hasDynamicField,
String typeFieldAccessor) {
this.order = order;
if (classloaderMatcher == null) {
this.classloaderMatcher = any();
Expand All @@ -49,6 +51,7 @@ public ClassTransformation(int order,
this.classMatcher = classMatcher;
this.methodTransformations = methodTransformations;
this.hasDynamicField = hasDynamicField;
this.typeFieldAccessor = typeFieldAccessor;
}

public static Builder builder() {
Expand All @@ -67,6 +70,8 @@ public static class Builder {
private Set<MethodTransformation> methodTransformations;
private boolean hasDynamicField;

private String typeFieldAccessor;

Builder() {
}

Expand Down Expand Up @@ -95,9 +100,14 @@ public Builder hasDynamicField(boolean hasDynamicField) {
return this;
}

public Builder typeFieldAccessor(String typeFieldAccessor) {
this.typeFieldAccessor = typeFieldAccessor;
return this;
}

public ClassTransformation build() {
return new ClassTransformation(order, classloaderMatcher, classMatcher,
methodTransformations, hasDynamicField);
methodTransformations, hasDynamicField, typeFieldAccessor);
}

public String toString() {
Expand Down
Loading
Loading