提交 3279e189 编写于 作者: oldratlee's avatar oldratlee 🔥

Merge branch 'dev/sample-ttl-agent-extension-transformlet'

......@@ -40,7 +40,8 @@ before_install:
- echo -e "JAVA_HOME=$JAVA_HOME\nPATH=$PATH\nSHELL=$SHELL"
script:
- ./scripts/integration-test.sh
- scripts/integration-test.sh
- ttl-integrations/sample-ttl-agent-extension-transformlet/scripts/integration-test.sh
after_success:
# codecov
......
# `TTL Agent`扩展`Transformlet`实现的示例工程
## 扩展`Transformlet`的实现
为了提供`TTL Agent`扩展`Transformlet`,包含2部分:
1. `TTL Agent`扩展`Transformlet`的实现类:[`SampleExtensionTransformlet`](src/main/java/com/alibaba/ttl/agent/extension_transformlet/sample/transformlet/SampleExtensionTransformlet.java)
- 这个示例`Transformlet`修改了类[`ToBeTransformedClass`](src/main/java/com/alibaba/ttl/agent/extension_transformlet/sample/biz/ToBeTransformedClass.java)`toBeTransformedMethod`方法:在修改方法前插入一行代码,修改方法参数值乘以2(`$1 *= 2;`)。
1. `TTL Agent`扩展`Transformlet`的配置文件:[`META-INF/ttl.agent.transformlets`](src/main/resources/META-INF/ttl.agent.transformlets)
- 配置文件的内容是 扩展`Transformlet`实现类的全类名。
在这个示例工程是`com.alibaba.ttl.agent.extension_transformlet.sample.transformlet.SampleExtensionTransformlet`
- `TTL Agent`会扫描`Class Path`上的`META-INF/ttl.agent.transformlets`文件,自动发现并启用这些扩展`Transformlet`
即只要将扩展`Transformlet`的依赖`Jar`引入到应用中就会自动生效。
- 这个扫描并自动加载生效与`JDK`[`ServiceLoader`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html)一样,只是使用不同的扩展配置文件。
## 扩展`Transformlet`的测试与生效验证
单元测试类 在 [`ToBeTransformedClassTest`](src/test/java/com/alibaba/ttl/agent/extension_transformlet/sample/biz/ToBeTransformedClassTest.java)
通过运行`Maven`单元测试验证扩展`Transformlet` `SampleExtensionTransformlet`是否生效:
```bash
# sample-ttl-agent-extension-transformlet 工程目录,执行
# 1. 先 mvn install TTL lib
(cd ../.. && mvn install -Dmaven.test.skip)
# 2. 验证 扩展Transformlet SampleExtensionTransformlet 是否生效
mvn test -Penable-TtlAgent-forTest
# 更多输出TTL的Transform类操作的日志
mvn test -Penable-TtlAgent-forTest -Penable-LogTransform-forTest
```
## 运行示例`SampleMain`
可以通过`Java`命令行参数来运行示例`SampleMain`
```java
java -javaagent:path/to/transmittable-thread-local-2.x.y.jar \
-cp target/classes \
com.alibaba.ttl.agent.extension_transformlet.sample.biz.SampleMain
```
通过脚本[`scripts/run.sh`](scripts/run.sh)快速上面命令行的运行。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>sample-ttl-agent-extension-transformlet</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<ttl.version>2.13.0-SNAPSHOT</ttl.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${ttl.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>enable-TtlAgent-forTest</id>
<properties>
<surefire.ttl.agent.log.class.transform/>
<surefire.verbose.class/>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--
property `com.alibaba:transmittable-thread-local:jar` is generated by maven-dependency-plugin
-->
<argLine>
${surefire.verbose.class}
-javaagent:${com.alibaba:transmittable-thread-local:jar}=ttl.agent.logger:STDOUT
${surefire.ttl.agent.log.class.transform}
</argLine>
</configuration>
</plugin>
<plugin>
<!--
How to get path to dependency jar with maven
https://stackoverflow.com/a/56396097/922688
Apache Maven Dependency Plugin – Introduction
https://maven.apache.org/plugins/maven-dependency-plugin/
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>enable-LogTransform-forTest</id>
<properties>
<surefire.ttl.agent.log.class.transform>-Dttl.agent.log.class.transform</surefire.ttl.agent.log.class.transform>
</properties>
</profile>
<profile>
<id>enable-verboseClass-forTest</id>
<properties>
<surefire.verbose.class>-verbose:class</surefire.verbose.class>
</properties>
</profile>
</profiles>
</project>
#!/bin/bash
set -eEuo pipefail
# adjust current dir to project dir
cd "$(dirname "$(readlink -f "$0")")/.."
TTL_ROOT_PROJECT_DIR="$(dirname "$(readlink -f "../")")"
source "$TTL_ROOT_PROJECT_DIR/scripts/common_build.sh"
source "$TTL_ROOT_PROJECT_DIR/scripts/prepare-jdk.sh"
for jv in 8 11; do
switch_to_jdk "$jv"
headInfo "test with JDK $JAVA_HOME"
MVN_WITH_BASIC_OPTIONS test
MVN_WITH_BASIC_OPTIONS test -Penable-TtlAgent-forTest
done
#!/bin/bash
set -eEuo pipefail
# adjust current dir to project dir
cd "$(dirname "$(readlink -f "$0")")/.."
TTL_ROOT_PROJECT_DIR="$(dirname "$(readlink -f "../")")"
source "$TTL_ROOT_PROJECT_DIR/scripts/common_build.sh"
ttl_version=$(extractFirstElementValueFromPom version "../../pom.xml")
readonly ttl_agent_path="$TTL_ROOT_PROJECT_DIR/target/transmittable-thread-local-$ttl_version.jar"
mvn_ttl_lib() {
(
cd "$TTL_ROOT_PROJECT_DIR"
MVN_WITH_BASIC_OPTIONS -q -Dmaven.test.skip "$@"
)
}
if [ "${1:-}" != "skipClean" ]; then
mvn_ttl_lib clean package
# compile sample-ttl-agent-extension-transformlet
MVN_WITH_BASIC_OPTIONS -q clean compile
else
if [ ! -f "$ttl_agent_path" ]; then
mvn_ttl_lib package
fi
# compile sample-ttl-agent-extension-transformlet
MVN_WITH_BASIC_OPTIONS -q compile
fi
readonly ttl_agent_options="-javaagent:$ttl_agent_path=ttl.agent.logger:STDOUT,ttl.agent.log.class.transform:true"
readonly main_class=com.alibaba.ttl.agent.extension_transformlet.sample.biz.SampleMain
logAndRun "$JAVA_HOME/bin/java" -Duser.language=en -Duser.country=US \
"${ttl_agent_options}" \
-cp target/classes $main_class
package com.alibaba.ttl.agent.extension_transformlet.sample.biz;
import com.alibaba.ttl.threadpool.agent.TtlAgent;
import com.alibaba.ttl.threadpool.agent.transformlet.ClassInfo;
public class SampleMain {
/**
* @see ToBeTransformedClass#toBeTransformedMethod(int)
* @see com.alibaba.ttl.agent.extension_transformlet.sample.transformlet.SampleExtensionTransformlet#doTransform(ClassInfo)
*/
public static void main(String[] args) throws Exception {
final ToBeTransformedClass instance = new ToBeTransformedClass();
System.out.println("========================================");
if (TtlAgent.isTtlAgentLoaded()) {
System.out.println("Run WITH TTL Agent");
} else {
System.out.println("Run Without TTL Agent");
}
System.out.println(instance.toBeTransformedMethod(21));
System.out.println("========================================");
}
}
package com.alibaba.ttl.agent.extension_transformlet.sample.biz;
public class ToBeTransformedClass {
public int toBeTransformedMethod(int input) {
return input;
}
}
package com.alibaba.ttl.agent.extension_transformlet.sample.transformlet;
import com.alibaba.ttl.agent.extension_transformlet.sample.biz.ToBeTransformedClass;
import com.alibaba.ttl.threadpool.agent.logging.Logger;
import com.alibaba.ttl.threadpool.agent.transformlet.ClassInfo;
import com.alibaba.ttl.threadpool.agent.transformlet.TtlTransformlet;
import com.alibaba.ttl.threadpool.agent.transformlet.javassist.CannotCompileException;
import com.alibaba.ttl.threadpool.agent.transformlet.javassist.CtClass;
import com.alibaba.ttl.threadpool.agent.transformlet.javassist.CtMethod;
import com.alibaba.ttl.threadpool.agent.transformlet.javassist.NotFoundException;
import java.io.IOException;
/**
* {@link TtlTransformlet} for {@link ToBeTransformedClass}.
*
* <B><I>Caution:</I></B><br>
* MUST use string constant for class/method name!
* <p>
* MUST NOT use {@code Class<?> class = ToBeTransformedClass.class} to get the class to be transformed({@code ToBeTransformedClass}),
* {@code ToBeTransformedClass.class} operation will force to load the class to be transformed,
* and cause the Transformlet to <b>SKIP</b> the class transform!
*/
public class SampleExtensionTransformlet implements TtlTransformlet {
private static final Logger logger = Logger.getLogger(SampleExtensionTransformlet.class);
public static final String TO_BE_TRANSFORMED_CLASS_NAME = "com.alibaba.ttl.agent.extension_transformlet.sample.biz.ToBeTransformedClass";
public static final String TO_BE_TRANSFORMED_METHOD = "toBeTransformedMethod";
public void doTransform(ClassInfo classInfo) throws IOException, NotFoundException, CannotCompileException {
if (!classInfo.getClassName().equals(TO_BE_TRANSFORMED_CLASS_NAME)) return;
final CtClass ctClass = classInfo.getCtClass();
final CtMethod method = ctClass.getDeclaredMethod(TO_BE_TRANSFORMED_METHOD);
final String code = "$1 *= 2;";
method.insertBefore(code);
logger.info("[SampleExtensionTransformlet] insert code before method " + TO_BE_TRANSFORMED_METHOD
+ " of class " + method.getDeclaringClass().getName() + ": " + code);
classInfo.setModified();
}
}
com.alibaba.ttl.agent.extension_transformlet.sample.transformlet.SampleExtensionTransformlet
package com.alibaba.ttl.agent.extension_transformlet.sample.biz;
import com.alibaba.ttl.threadpool.agent.TtlAgent;
import org.junit.Test;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
public class ToBeTransformedClassTest {
@Test
public void test_method1() {
final ToBeTransformedClass instance = new ToBeTransformedClass();
System.out.println("========================================");
if (TtlAgent.isTtlAgentLoaded()) {
System.out.println("Test **WITH** TTL Agent");
assertEquals(42, instance.toBeTransformedMethod(21));
} else {
System.out.println("Test WITHOUT TTL Agent");
assertEquals(21, instance.toBeTransformedMethod(21));
}
System.out.println("========================================");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册