Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
252e50cd7e
|
|
@ -1,38 +1,40 @@
|
|||
package com.ai.cloud.skywalking.conf;
|
||||
|
||||
import static com.ai.cloud.skywalking.conf.Config.SkyWalking.AUTH_OVERRIDE;
|
||||
import static com.ai.cloud.skywalking.conf.Config.SkyWalking.AUTH_SYSTEM_ENV_NAME;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.ai.cloud.skywalking.conf.Config.SkyWalking.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ConfigInitializer {
|
||||
private static Logger logger = Logger.getLogger(ConfigInitializer.class.getName());
|
||||
private static Logger logger = LogManager.getLogger(ConfigInitializer.class);
|
||||
|
||||
public static void initialize() {
|
||||
InputStream inputStream = ConfigInitializer.class.getResourceAsStream("/sky-walking.auth");
|
||||
if (inputStream == null) {
|
||||
logger.log(Level.ALL, "No provider sky-walking certification documents, sky-walking api auto shutdown.");
|
||||
logger.info("No provider sky-walking certification documents, sky-walking api auto shutdown.");
|
||||
} else {
|
||||
try {
|
||||
Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
initNextLevel(properties, Config.class, new ConfigDesc());
|
||||
AuthDesc.isAuth = Boolean.valueOf(System.getenv(AUTH_SYSTEM_ENV_NAME));
|
||||
logger.log(Level.ALL, "sky-walking auth check : " + AuthDesc.isAuth);
|
||||
logger.info("sky-walking auth check : " + AuthDesc.isAuth);
|
||||
if(!AuthDesc.isAuth && AUTH_OVERRIDE){
|
||||
AuthDesc.isAuth = AUTH_OVERRIDE;
|
||||
logger.log(Level.ALL, "sky-walking auth override: " + AuthDesc.isAuth);
|
||||
logger.info("sky-walking auth override: " + AuthDesc.isAuth);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.log(Level.ALL, "Parsing certification file failed, sky-walking api auto shutdown.");
|
||||
logger.error("Parsing certification file failed, sky-walking api auto shutdown.", e);
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.ALL, "Failed to read the certification file, sky-walking api auto shutdown.");
|
||||
logger.error("Failed to read the certification file, sky-walking api auto shutdown.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
package com.ai.cloud.skywalking.plugin;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.ai.cloud.skywalking.conf.AuthDesc;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.EnhanceClazz4Interceptor;
|
||||
|
||||
public class PluginBootstrap {
|
||||
private static Logger logger = LogManager.getLogger(PluginBootstrap.class);
|
||||
|
||||
public void start() {
|
||||
if (!AuthDesc.isAuth()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PluginResourcesResolver resolver = new PluginResourcesResolver();
|
||||
Enumeration<URL> resources = resolver.getResources();
|
||||
|
||||
if (resources == null || !resources.hasMoreElements()) {
|
||||
logger.info("no plugin files (skywalking-plugin.properties) found, continue to start application.");
|
||||
return;
|
||||
}
|
||||
|
||||
while (resources.hasMoreElements()) {
|
||||
URL pluginUrl = resources.nextElement();
|
||||
try {
|
||||
PluginCfg.CFG.load(pluginUrl.openStream());
|
||||
} catch (Throwable t) {
|
||||
logger.error("plugin [{}] init failure.", pluginUrl, t);
|
||||
}
|
||||
}
|
||||
|
||||
EnhanceClazz4Interceptor enhanceClazz4Interceptor = new EnhanceClazz4Interceptor();
|
||||
enhanceClazz4Interceptor.enhance();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.ai.cloud.skywalking.plugin;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ai.cloud.skywalking.util.StringUtil;
|
||||
|
||||
public class PluginCfg {
|
||||
public final static PluginCfg CFG = new PluginCfg();
|
||||
|
||||
private Set<String> interceptorClassList = new HashSet<String>();
|
||||
|
||||
private PluginCfg(){}
|
||||
|
||||
void load(InputStream input) throws IOException{
|
||||
try{
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
|
||||
String nhanceOriginClassName = null;
|
||||
while((nhanceOriginClassName = reader.readLine()) != null){
|
||||
if(!StringUtil.isEmpty(nhanceOriginClassName)){
|
||||
interceptorClassList.add(nhanceOriginClassName.trim());
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getInterceptorClassList(){
|
||||
return interceptorClassList;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.ai.cloud.skywalking.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class PluginResourcesResolver {
|
||||
private static Logger logger = LogManager.getLogger(PluginResourcesResolver.class);
|
||||
|
||||
public Enumeration<URL> getResources(){
|
||||
Enumeration<URL> urls;
|
||||
try {
|
||||
urls = getDefaultClassLoader().getResources("skywalking-plugin.properties");
|
||||
|
||||
if(!urls.hasMoreElements()){
|
||||
logger.info("no plugin files (skywalking-plugin.properties) found");
|
||||
}
|
||||
|
||||
while(urls.hasMoreElements()){
|
||||
URL pluginUrl = urls.nextElement();
|
||||
logger.info("find skywalking plugin define in {}", pluginUrl);
|
||||
}
|
||||
|
||||
return urls;
|
||||
} catch (IOException e) {
|
||||
logger.error("read resources failure.", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ClassLoader getDefaultClassLoader() {
|
||||
ClassLoader cl = null;
|
||||
try {
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// Cannot access thread context ClassLoader - falling back to system class loader...
|
||||
}
|
||||
if (cl == null) {
|
||||
// No thread context class loader -> use class loader of this class.
|
||||
cl = PluginResourcesResolver.class.getClassLoader();
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.ai.cloud.skywalking.plugin;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* 替代应用函数的main函数入口,确保在程序入口处运行 <br/>
|
||||
* 用于替代-javaagent的另一种模式 <br/>
|
||||
*
|
||||
* @author wusheng
|
||||
*
|
||||
*/
|
||||
public class TracingBootstrap {
|
||||
private static Logger logger = LogManager.getLogger(TracingBootstrap.class);
|
||||
|
||||
private TracingBootstrap() {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) {
|
||||
throw new RuntimeException(
|
||||
"bootstrap failure. need args[0] to be main class.");
|
||||
}
|
||||
|
||||
try {
|
||||
PluginBootstrap bootstrap = new PluginBootstrap();
|
||||
bootstrap.start();
|
||||
} catch (Throwable t) {
|
||||
logger.error("PluginBootstrap start failure.", t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.PluginCfg;
|
||||
|
||||
public class EnhanceClazz4Interceptor {
|
||||
private static Logger logger = LogManager
|
||||
.getLogger(EnhanceClazz4Interceptor.class);
|
||||
|
||||
private TypePool typePool;
|
||||
|
||||
public EnhanceClazz4Interceptor() {
|
||||
typePool = TypePool.Default.ofClassPath();
|
||||
}
|
||||
|
||||
public void enhance() {
|
||||
Set<String> interceptorClassList = PluginCfg.CFG
|
||||
.getInterceptorClassList();
|
||||
|
||||
for (String interceptorClassName : interceptorClassList) {
|
||||
try {
|
||||
enhance0(interceptorClassName);
|
||||
} catch (Throwable t) {
|
||||
logger.error("enhance class [{}] for intercept failure.",
|
||||
interceptorClassName, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void enhance0(String interceptorDefineClassName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
InterceptorDefine define = (InterceptorDefine)Class.forName(interceptorDefineClassName).newInstance();
|
||||
|
||||
String enhanceOriginClassName = define.getBeInterceptedClassName();
|
||||
/**
|
||||
* add '$$Origin' at the end of be enhanced classname <br/>
|
||||
* such as: class com.ai.cloud.TestClass to class com.ai.cloud.TestClass$$Origin
|
||||
*/
|
||||
new ByteBuddy()
|
||||
.redefine(typePool.describe(enhanceOriginClassName).resolve(),
|
||||
ClassFileLocator.ForClassLoader.ofClassPath())
|
||||
.name(enhanceOriginClassName + "$$Origin")
|
||||
.make()
|
||||
.load(ClassLoader.getSystemClassLoader(),
|
||||
ClassLoadingStrategy.Default.INJECTION).getLoaded();
|
||||
|
||||
/**
|
||||
* define class as origin class name. and inject to classloader. <br/>
|
||||
* new class need:<br/>
|
||||
* 1.implement com.ai.cloud.skywalking.plugin.interceptor.IEnhancedClassInstanceContext(); <br/>
|
||||
* 2.add field '_$EnhancedClassInstanceContext' of type EnhancedClassInstanceContext
|
||||
* 3.intercept constructor and method if required by interceptorDefineClass
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 被增强的类实例,需扩展的context属性,用于在不同的方法,或者构造函数间保存实例
|
||||
*
|
||||
* @author wusheng
|
||||
*
|
||||
*/
|
||||
public class EnhancedClassInstanceContext {
|
||||
public static final String FIELD_NAME = "_$EnhancedClassInstanceContext";
|
||||
|
||||
private Map<Object, Object> context = new HashMap<Object, Object>();
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
public interface IAroundInterceptor {
|
||||
public void onConstruct(EnhancedClassInstanceContext context);
|
||||
|
||||
public void beforeMethod(EnhancedClassInstanceContext context);
|
||||
|
||||
public void afterMethod(EnhancedClassInstanceContext context);
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
/**
|
||||
* 被增强的类,会实现此接口,用于快速获取实例级属性上下文扩展<br/>
|
||||
* @see com.ai.cloud.skywalking.plugin.interceptor.EnhanceClazz4Interceptor.enhance0()
|
||||
*
|
||||
* @author wusheng
|
||||
*
|
||||
*/
|
||||
public interface IEnhancedClassInstanceContext {
|
||||
public EnhancedClassInstanceContext getEnhancedClassInstanceContext();
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
public interface InterceptorDefine {
|
||||
public String getBeInterceptedClassName();
|
||||
|
||||
public String[] getBeInterceptedMethods();
|
||||
|
||||
public IAroundInterceptor instance();
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import com.ai.cloud.skywalking.conf.Config;
|
|||
import com.ai.cloud.skywalking.util.BuriedPointMachineUtil;
|
||||
|
||||
public class SDKHealthCollector extends Thread {
|
||||
private Logger logger = LogManager.getLogger(SDKHealthCollector.class);
|
||||
private static Logger logger = LogManager.getLogger(SDKHealthCollector.class);
|
||||
|
||||
private static Map<String, HeathReading> heathReadings = new ConcurrentHashMap<String, HeathReading>();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package test.ai.cloud.bytebuddy;
|
||||
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
public class ConstructorInterceptor {
|
||||
@RuntimeType
|
||||
public void intercept(@AllArguments Object[] allArguments) {
|
||||
System.out
|
||||
.println("ConstructorInterceptor size:" + allArguments.length);
|
||||
if(allArguments.length > 0){
|
||||
System.out.println("ConstructorInterceptor param[0]=" + allArguments[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,12 +7,13 @@ import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
|||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
|
||||
public class Interceptor{
|
||||
public class MethodInterceptor{
|
||||
@RuntimeType
|
||||
public Object intercept(@AllArguments Object[] allArguments, @Origin Method method, @SuperCall Callable<?> zuper){
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method, @SuperCall Callable<?> zuper){
|
||||
try {
|
||||
return "intercept_" + zuper.call();
|
||||
return method.getName() + ":intercept_" + zuper.call();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
|
|
@ -1,49 +1,56 @@
|
|||
package test.ai.cloud.bytebuddy;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.SuperMethodCall;
|
||||
import net.bytebuddy.pool.TypePool;
|
||||
|
||||
public class SimulateMain {
|
||||
public static void main(String[] args) throws NoSuchFieldException,
|
||||
SecurityException, InstantiationException, IllegalAccessException {
|
||||
SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
TypePool typePool = TypePool.Default.ofClassPath();
|
||||
|
||||
Object newClazzObj = new ByteBuddy()
|
||||
.redefine(
|
||||
typePool.describe(
|
||||
"test.ai.cloud.bytebuddy.TestClass")
|
||||
.resolve(),
|
||||
ClassFileLocator.ForClassLoader.ofClassPath())
|
||||
.name("test.ai.cloud.bytebuddy.TestClass$$Origin")
|
||||
.make()
|
||||
.load(ClassLoader.getSystemClassLoader(),
|
||||
ClassLoadingStrategy.Default.INJECTION).getLoaded().newInstance();
|
||||
|
||||
TestClass t22 = (TestClass)(new ByteBuddy()
|
||||
.subclass(newClazzObj.getClass())
|
||||
.method(named("testA"))
|
||||
.intercept(MethodDelegation.to(new Interceptor()))
|
||||
Class<?> newClazz = new ByteBuddy()
|
||||
.redefine(
|
||||
typePool.describe("test.ai.cloud.bytebuddy.TestClass")
|
||||
.resolve(),
|
||||
ClassFileLocator.ForClassLoader.ofClassPath())
|
||||
.name("test.ai.cloud.bytebuddy.TestClass$$Origin")
|
||||
.make()
|
||||
.load(ClassLoader.getSystemClassLoader(),
|
||||
ClassLoadingStrategy.Default.INJECTION).getLoaded();
|
||||
|
||||
TestClass t22 = (TestClass) (new ByteBuddy()
|
||||
.subclass(newClazz)
|
||||
.method(isMethod())
|
||||
.intercept(MethodDelegation.to(new MethodInterceptor()))
|
||||
.constructor(isConstructor())
|
||||
.intercept(MethodDelegation.to(new ConstructorInterceptor()).andThen(SuperMethodCall.INSTANCE))
|
||||
.name("test.ai.cloud.bytebuddy.TestClass")
|
||||
.make()
|
||||
.load(ClassLoader.getSystemClassLoader(),
|
||||
ClassLoadingStrategy.Default.INJECTION).getLoaded().newInstance());
|
||||
ClassLoadingStrategy.Default.INJECTION).getLoaded()
|
||||
.newInstance());
|
||||
|
||||
//System.out.println(t22.testA("1"));
|
||||
|
||||
TestClass t = new TestClass();
|
||||
// System.out.println(t22.testA("1"));
|
||||
TestClass t = new TestClass("abc");
|
||||
System.out.println(t.testA("1"));
|
||||
|
||||
TestClass t2 = null;
|
||||
try {
|
||||
t2 = (TestClass)Class.forName("test.ai.cloud.bytebuddy.TestClass").newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println(t2.testA("1"));
|
||||
t = new TestClass("abc");
|
||||
System.out.println(t.testA("1"));
|
||||
|
||||
// TestClass t2 = null;
|
||||
// try {
|
||||
// t2 = (TestClass) Class.forName("test.ai.cloud.bytebuddy.TestClass")
|
||||
// .newInstance();
|
||||
// } catch (ClassNotFoundException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// System.out.println(t2.testA("1"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
package test.ai.cloud.bytebuddy;
|
||||
|
||||
public class TestClass {
|
||||
public TestClass(){
|
||||
//System.out.println("init:" + this.getClass().getName());
|
||||
}
|
||||
|
||||
public TestClass(String tmp){
|
||||
//System.out.println("init:" + this.getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
public String testA(String aa){
|
||||
// throw new RuntimeException("adfasdfas");
|
||||
return "TestClass.testA";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package test.ai.cloud.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.PluginResourcesResolver;
|
||||
|
||||
public class PluginResourceResoverTest {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
PluginResourcesResolver resolver = new PluginResourcesResolver();
|
||||
resolver.getResources();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="debug">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d [%t](%F:%L) %-5level %logger{36} - %msg%n"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="debug">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
Loading…
Reference in New Issue