1.调整拦截器接口,增加interceptPoint描述,重构拦截器接口。重构增强逻辑
2.移除jdbc-plugin 3.新增mysql-plugin,新增插件skywalking-mysql-plugin。插件将在包引用后自动生效。(本地测试完成,待集成测试)
This commit is contained in:
parent
4f606cabfe
commit
ef07b16457
|
|
@ -44,7 +44,7 @@ public class LocalBuriedPointSender extends ApplicationExceptionHandler implemen
|
|||
|
||||
if (Config.BuriedPoint.PRINTF) {
|
||||
logger.debug("TraceId:" + spanData.getTraceId() + "\tviewpointId:" + spanData.getViewPointId() + "\tParentLevelId:" + spanData.
|
||||
getParentLevel() + "\tLevelId:" + spanData.getLevelId());
|
||||
getParentLevel() + "\tLevelId:" + spanData.getLevelId() + "\tbusinessKey:" + spanData.getBusinessKey());
|
||||
}
|
||||
|
||||
// 存放到本地发送进程中
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.ai.cloud.skywalking.plugin;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ public class 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());
|
||||
String interceptorDefineClassName = null;
|
||||
while((interceptorDefineClassName = reader.readLine()) != null){
|
||||
if(!StringUtil.isEmpty(interceptorDefineClassName)){
|
||||
interceptorClassList.add(interceptorDefineClassName.trim());
|
||||
}
|
||||
}
|
||||
}finally{
|
||||
|
|
|
|||
|
|
@ -48,7 +48,15 @@ public class ClassMethodInterceptor {
|
|||
Object ret = null;
|
||||
try {
|
||||
ret = zuper.call();
|
||||
} finally {
|
||||
} catch(Throwable t){
|
||||
try {
|
||||
interceptor.handleMethodException(t, instanceContext, interceptorContext, ret);
|
||||
throw t;
|
||||
} catch (Throwable t2) {
|
||||
logger.error("class[{}] handle method[{}] exception failue:{}",
|
||||
obj.getClass(), method.getName(), t2.getMessage(), t2);
|
||||
}
|
||||
}finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(instanceContext, interceptorContext, ret);
|
||||
} catch (Throwable t) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.ai.cloud.skywalking.plugin.interceptor;
|
|||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.any;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -80,8 +82,8 @@ public class EnhanceClazz4Interceptor {
|
|||
* 1.add field '_$EnhancedClassInstanceContext' of type
|
||||
* EnhancedClassInstanceContext <br/>
|
||||
*
|
||||
* 2.intercept constructor by default, and intercept method which it's required by
|
||||
* interceptorDefineClass. <br/>
|
||||
* 2.intercept constructor by default, and intercept method which it's
|
||||
* required by interceptorDefineClass. <br/>
|
||||
*/
|
||||
IAroundInterceptor interceptor = define.instance();
|
||||
|
||||
|
|
@ -90,7 +92,7 @@ public class EnhanceClazz4Interceptor {
|
|||
newClassBuilder = newClassBuilder
|
||||
.defineField(contextAttrName,
|
||||
EnhancedClassInstanceContext.class)
|
||||
.constructor(isConstructor())
|
||||
.constructor(any())
|
||||
.intercept(
|
||||
SuperMethodCall.INSTANCE.andThen(MethodDelegation.to(
|
||||
new ClassConstructorInterceptor(interceptor))
|
||||
|
|
@ -99,12 +101,27 @@ public class EnhanceClazz4Interceptor {
|
|||
FieldGetter.class,
|
||||
FieldSetter.class))));
|
||||
|
||||
String[] methodNameList = define.getBeInterceptedMethods();
|
||||
for (String methodName : methodNameList) {
|
||||
newClassBuilder = newClassBuilder.method(named(methodName))
|
||||
.intercept(
|
||||
MethodDelegation.to(new ClassMethodInterceptor(
|
||||
interceptor)));
|
||||
InterceptPoint[] methodNameList = define.getBeInterceptedMethods();
|
||||
ClassMethodInterceptor classMethodInterceptor = new ClassMethodInterceptor(
|
||||
interceptor);
|
||||
for (InterceptPoint method : methodNameList) {
|
||||
logger.debug("prepare to enhance class {} method [{}] ",
|
||||
enhanceOriginClassName, method.getMethodName());
|
||||
if (method.getArgTypeArray() != null) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
named(method.getMethodName()).and(
|
||||
takesArguments(method.getArgTypeArray()))).intercept(
|
||||
MethodDelegation.to(classMethodInterceptor));
|
||||
} else if (method.getArgNum() > -1) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
named(method.getMethodName()).and(
|
||||
takesArguments(method.getArgNum()))).intercept(
|
||||
MethodDelegation.to(classMethodInterceptor));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
named(method.getMethodName())).intercept(
|
||||
MethodDelegation.to(classMethodInterceptor));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ public interface IAroundInterceptor {
|
|||
|
||||
public Object afterMethod(EnhancedClassInstanceContext context, MethodInvokeContext interceptorContext, Object ret);
|
||||
|
||||
|
||||
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, MethodInvokeContext interceptorContext, Object ret);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package com.ai.cloud.skywalking.plugin.interceptor;
|
||||
|
||||
|
||||
public class InterceptPoint {
|
||||
private String methodName;
|
||||
|
||||
private int argNum = -1;
|
||||
|
||||
private Class<?>[] argTypeArray;
|
||||
|
||||
public InterceptPoint(String methodName) {
|
||||
super();
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public InterceptPoint(String methodName, int argNum) {
|
||||
this(methodName);
|
||||
this.argNum = argNum;
|
||||
}
|
||||
|
||||
public InterceptPoint(String methodName, Class<?>... args) {
|
||||
this(methodName);
|
||||
this.argTypeArray = args;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public int getArgNum() {
|
||||
return argNum;
|
||||
}
|
||||
|
||||
public Class<?>[] getArgTypeArray() {
|
||||
return argTypeArray;
|
||||
}
|
||||
|
||||
public void setArgNum(int argNum) {
|
||||
this.argNum = argNum;
|
||||
}
|
||||
|
||||
public void setArgTypeList(Class<?>... args){
|
||||
argTypeArray = args;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ public interface InterceptorDefine {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public String[] getBeInterceptedMethods();
|
||||
public InterceptPoint[] getBeInterceptedMethods();
|
||||
|
||||
/**
|
||||
* 返回增强拦截器的实现<br/>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,11 @@ public class PluginMainTest {
|
|||
.main(new String[] { "test.ai.cloud.plugin.PluginMainTest" });
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
BeInterceptedClass inst = new BeInterceptedClass();
|
||||
|
||||
BeInterceptedClass inst = (BeInterceptedClass) Class.forName("test.ai.cloud.plugin.BeInterceptedClass").newInstance();
|
||||
inst.printabc();
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println(end - start + "ms");
|
||||
|
|
|
|||
|
|
@ -24,4 +24,11 @@ public class TestAroundInterceptor implements IAroundInterceptor {
|
|||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context,
|
||||
MethodInvokeContext interceptorContext, Object ret) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package test.ai.cloud.plugin;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.IAroundInterceptor;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.InterceptPoint;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.InterceptorDefine;
|
||||
|
||||
public class TestInterceptorDefine implements InterceptorDefine {
|
||||
|
|
@ -11,8 +12,8 @@ public class TestInterceptorDefine implements InterceptorDefine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String[] getBeInterceptedMethods() {
|
||||
return new String[] { "printabc" };
|
||||
public InterceptPoint[] getBeInterceptedMethods() {
|
||||
return new InterceptPoint[] { new InterceptPoint("printabc") };
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,326 +0,0 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Clob;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.NClob;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLClientInfoException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Struct;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.ConnectionTracing;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.ConnectionTracing.Executable;
|
||||
|
||||
public class SWConnection implements java.sql.Connection {
|
||||
private String connectInfo;
|
||||
|
||||
private final java.sql.Connection realConnection;
|
||||
|
||||
public SWConnection(String url, Properties info,
|
||||
java.sql.Connection realConnection) {
|
||||
super();
|
||||
this.connectInfo = url + "(" + info.getProperty("user") + ")";
|
||||
this.realConnection = realConnection;
|
||||
}
|
||||
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
return realConnection.unwrap(iface);
|
||||
}
|
||||
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return realConnection.isWrapperFor(iface);
|
||||
}
|
||||
|
||||
public Statement createStatement() throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(),
|
||||
this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return new SWPreparedStatement(this,
|
||||
realConnection.prepareStatement(sql), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql),
|
||||
this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public String nativeSQL(String sql) throws SQLException {
|
||||
return ConnectionTracing.execute(realConnection, connectInfo,
|
||||
"nativeSQL", sql, new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
return realConnection.nativeSQL(sql);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setAutoCommit(boolean autoCommit) throws SQLException {
|
||||
realConnection.setAutoCommit(autoCommit);
|
||||
}
|
||||
|
||||
public boolean getAutoCommit() throws SQLException {
|
||||
return realConnection.getAutoCommit();
|
||||
}
|
||||
|
||||
public void commit() throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo, "commit", "",
|
||||
new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.commit();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void rollback() throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo, "rollback", "",
|
||||
new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.rollback();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo, "close", "",
|
||||
new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
return realConnection.isClosed();
|
||||
}
|
||||
|
||||
public DatabaseMetaData getMetaData() throws SQLException {
|
||||
return realConnection.getMetaData();
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) throws SQLException {
|
||||
realConnection.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
return realConnection.isReadOnly();
|
||||
}
|
||||
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
realConnection.setCatalog(catalog);
|
||||
}
|
||||
|
||||
public String getCatalog() throws SQLException {
|
||||
return realConnection.getCatalog();
|
||||
}
|
||||
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
realConnection.setTransactionIsolation(level);
|
||||
}
|
||||
|
||||
public int getTransactionIsolation() throws SQLException {
|
||||
return realConnection.getTransactionIsolation();
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return realConnection.getWarnings();
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {
|
||||
realConnection.clearWarnings();
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(
|
||||
resultSetType, resultSetConcurrency), this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType,
|
||||
int resultSetConcurrency) throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, resultSetType, resultSetConcurrency), this.connectInfo,
|
||||
sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType,
|
||||
int resultSetConcurrency) throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql,
|
||||
resultSetType, resultSetConcurrency), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public Map<String, Class<?>> getTypeMap() throws SQLException {
|
||||
return realConnection.getTypeMap();
|
||||
}
|
||||
|
||||
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
|
||||
realConnection.setTypeMap(map);
|
||||
}
|
||||
|
||||
public void setHoldability(int holdability) throws SQLException {
|
||||
realConnection.setHoldability(holdability);
|
||||
}
|
||||
|
||||
public int getHoldability() throws SQLException {
|
||||
return realConnection.getHoldability();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
return realConnection.setSavepoint();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint(String name) throws SQLException {
|
||||
return realConnection.setSavepoint(name);
|
||||
}
|
||||
|
||||
public void rollback(final Savepoint savepoint) throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo,
|
||||
"rollback to savepoint", "", new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.rollback(savepoint);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo,
|
||||
"releaseSavepoint savepoint", "", new Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.releaseSavepoint(savepoint);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(
|
||||
resultSetType, resultSetConcurrency, resultSetHoldability),
|
||||
this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this,
|
||||
realConnection.prepareStatement(sql, resultSetType,
|
||||
resultSetConcurrency, resultSetHoldability),
|
||||
this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql,
|
||||
resultSetType, resultSetConcurrency, resultSetHoldability), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, autoGeneratedKeys), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, columnIndexes), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, String[] columnNames)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, columnNames), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public Clob createClob() throws SQLException {
|
||||
return realConnection.createClob();
|
||||
}
|
||||
|
||||
public Blob createBlob() throws SQLException {
|
||||
return realConnection.createBlob();
|
||||
}
|
||||
|
||||
public NClob createNClob() throws SQLException {
|
||||
return realConnection.createNClob();
|
||||
}
|
||||
|
||||
public SQLXML createSQLXML() throws SQLException {
|
||||
return realConnection.createSQLXML();
|
||||
}
|
||||
|
||||
public boolean isValid(int timeout) throws SQLException {
|
||||
return realConnection.isValid(timeout);
|
||||
}
|
||||
|
||||
public void setClientInfo(String name, String value)
|
||||
throws SQLClientInfoException {
|
||||
realConnection.setClientInfo(name, value);
|
||||
}
|
||||
|
||||
public void setClientInfo(Properties properties)
|
||||
throws SQLClientInfoException {
|
||||
realConnection.setClientInfo(properties);
|
||||
}
|
||||
|
||||
public String getClientInfo(String name) throws SQLException {
|
||||
return realConnection.getClientInfo(name);
|
||||
}
|
||||
|
||||
public Properties getClientInfo() throws SQLException {
|
||||
return realConnection.getClientInfo();
|
||||
}
|
||||
|
||||
public Array createArrayOf(String typeName, Object[] elements)
|
||||
throws SQLException {
|
||||
return realConnection.createArrayOf(typeName, elements);
|
||||
}
|
||||
|
||||
public Struct createStruct(String typeName, Object[] attributes)
|
||||
throws SQLException {
|
||||
return realConnection.createStruct(typeName, attributes);
|
||||
}
|
||||
|
||||
public void setSchema(String schema) throws SQLException {
|
||||
realConnection.setSchema(schema);
|
||||
}
|
||||
|
||||
public String getSchema() throws SQLException {
|
||||
return realConnection.getSchema();
|
||||
}
|
||||
|
||||
public void abort(Executor executor) throws SQLException {
|
||||
realConnection.abort(executor);
|
||||
}
|
||||
|
||||
public void setNetworkTimeout(Executor executor, int milliseconds)
|
||||
throws SQLException {
|
||||
realConnection.setNetworkTimeout(executor, milliseconds);
|
||||
}
|
||||
|
||||
public int getNetworkTimeout() throws SQLException {
|
||||
return realConnection.getNetworkTimeout();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.ai.cloud.skywalking.conf.AuthDesc;
|
||||
|
||||
public abstract class TracingDriver implements Driver {
|
||||
private static final String TRACING_SIGN = "tracing:";
|
||||
|
||||
private Driver realDriver;
|
||||
|
||||
protected TracingDriver() {
|
||||
this.realDriver = this.registerTracingDriver();
|
||||
}
|
||||
|
||||
protected abstract Driver registerTracingDriver();
|
||||
|
||||
public java.sql.Connection connect(String url, Properties info) throws SQLException {
|
||||
java.sql.Connection conn = this.realDriver.connect(this.getRealUrl(url), info);
|
||||
if(!AuthDesc.isAuth()){
|
||||
return conn;
|
||||
}else{
|
||||
return new SWConnection(url, info, conn);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean acceptsURL(String url) throws SQLException {
|
||||
return this.realDriver.acceptsURL(this.getRealUrl(url));
|
||||
}
|
||||
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
|
||||
throws SQLException {
|
||||
return this.realDriver.getPropertyInfo(this.getRealUrl(url), info);
|
||||
}
|
||||
|
||||
private String getRealUrl(String url) throws SQLException {
|
||||
if(url.toLowerCase().startsWith(TRACING_SIGN)){
|
||||
return url.substring(TRACING_SIGN.length());
|
||||
}else{
|
||||
throw new SQLException("tracing jdbc url must start with 'tracing:'");
|
||||
}
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
return safeIntParse("1");
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return safeIntParse("0");
|
||||
}
|
||||
|
||||
public boolean jdbcCompliant() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int safeIntParse(String intAsString) {
|
||||
try {
|
||||
return Integer.parseInt(intAsString);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc.mysql;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.TracingDriver;
|
||||
|
||||
public class MySQLTracingDriver extends TracingDriver {
|
||||
static {
|
||||
try {
|
||||
DriverManager.registerDriver(new MySQLTracingDriver());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("register "
|
||||
+ MySQLTracingDriver.class.getName() + " driver failure.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 继承自TracingDriver,返回真实的Driver
|
||||
*/
|
||||
@Override
|
||||
protected Driver registerTracingDriver() {
|
||||
try {
|
||||
return new com.mysql.jdbc.Driver();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException("create com.mysql.jdbc.Driver failure.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc.tracing;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.ai.cloud.skywalking.buriedpoint.RPCBuriedPointSender;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.model.Identification;
|
||||
|
||||
/**
|
||||
* 连接级追踪,用于追踪用于Connection的操作追踪
|
||||
*
|
||||
* @author wusheng
|
||||
*
|
||||
*/
|
||||
public class ConnectionTracing {
|
||||
private static RPCBuriedPointSender sender = new RPCBuriedPointSender();
|
||||
|
||||
public static <R> R execute(java.sql.Connection realConnection,
|
||||
String connectInfo, String method, String sql, Executable<R> exec)
|
||||
throws SQLException {
|
||||
try {
|
||||
sender.beforeSend(Identification
|
||||
.newBuilder()
|
||||
.viewPoint(connectInfo)
|
||||
.businessKey(
|
||||
"connection."
|
||||
+ method
|
||||
+ (sql == null || sql.length() == 0 ? ""
|
||||
: ":" + sql)).spanType(JDBCBuriedPointType.instance()).build());
|
||||
return exec.exe(realConnection, sql);
|
||||
} catch (SQLException e) {
|
||||
sender.handleException(e);
|
||||
throw e;
|
||||
} finally {
|
||||
sender.afterSend();
|
||||
}
|
||||
}
|
||||
|
||||
public interface Executable<R> {
|
||||
public R exe(java.sql.Connection realConnection, String sql)
|
||||
throws SQLException;
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>skywalking-jdbc-plugin</artifactId>
|
||||
<artifactId>skywalking-mysql-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>jdbc-plugin</name>
|
||||
|
|
@ -29,6 +29,19 @@
|
|||
<version>5.1.36</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.ai.cloud.skywalking.buriedpoint.RPCBuriedPointSender;
|
||||
import com.ai.cloud.skywalking.model.Identification;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.ConstructorInvokeContext;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.EnhancedClassInstanceContext;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.IAroundInterceptor;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.MethodInvokeContext;
|
||||
|
||||
public class ConnectionInterceptor implements IAroundInterceptor {
|
||||
private static final String CONNECTION_INFO_KEY = "connectInfo";
|
||||
|
||||
private static RPCBuriedPointSender sender = new RPCBuriedPointSender();
|
||||
|
||||
@Override
|
||||
public void onConstruct(EnhancedClassInstanceContext context,
|
||||
ConstructorInvokeContext interceptorContext) {
|
||||
String url = (String) interceptorContext.allArguments()[4];
|
||||
Properties info = (Properties) interceptorContext.allArguments()[2];
|
||||
context.set(CONNECTION_INFO_KEY, url + "(" + info.getProperty("user")
|
||||
+ ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedClassInstanceContext context,
|
||||
MethodInvokeContext interceptorContext) {
|
||||
if(context == null){
|
||||
// be intercepted method could be called in constructor, ignore.
|
||||
return;
|
||||
}
|
||||
String connectInfo = context.get(CONNECTION_INFO_KEY, String.class);
|
||||
String method = interceptorContext.methodName();
|
||||
String sql = "";
|
||||
switch (method) {
|
||||
case "commit":
|
||||
this.beforeSend(connectInfo, method, sql);
|
||||
break;
|
||||
case "rollback":
|
||||
this.beforeSend(connectInfo, method, sql);
|
||||
break;
|
||||
case "close":
|
||||
this.beforeSend(connectInfo, method, sql);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void beforeSend(String connectInfo, String method, String sql) {
|
||||
sender.beforeSend(Identification
|
||||
.newBuilder()
|
||||
.viewPoint(connectInfo)
|
||||
.businessKey(
|
||||
"connection."
|
||||
+ method
|
||||
+ (sql == null || sql.length() == 0 ? "" : ":"
|
||||
+ sql))
|
||||
.spanType(JDBCBuriedPointType.instance()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedClassInstanceContext context,
|
||||
MethodInvokeContext interceptorContext, Object ret) {
|
||||
if(context == null){
|
||||
// be intercepted method could be called in constructor, ignore.
|
||||
return ret;
|
||||
}
|
||||
String connectInfo = context.get(CONNECTION_INFO_KEY, String.class);
|
||||
switch (interceptorContext.methodName()) {
|
||||
case "createStatement":
|
||||
return new SWStatement((Connection) interceptorContext.inst(),
|
||||
(Statement) ret, connectInfo);
|
||||
case "prepareStatement":
|
||||
String sql = (String) interceptorContext.allArguments()[0];
|
||||
return new SWPreparedStatement(
|
||||
(Connection) interceptorContext.inst(),
|
||||
(PreparedStatement) ret, connectInfo, sql);
|
||||
case "prepareCall":
|
||||
String callableSql = (String) interceptorContext.allArguments()[0];
|
||||
return new SWCallableStatement(
|
||||
(Connection) interceptorContext.inst(),
|
||||
(CallableStatement) ret, connectInfo, callableSql);
|
||||
case "commit":
|
||||
case "rollback":
|
||||
case "close":
|
||||
sender.afterSend();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(Throwable t,
|
||||
EnhancedClassInstanceContext context,
|
||||
MethodInvokeContext interceptorContext, Object ret) {
|
||||
switch (interceptorContext.methodName()) {
|
||||
case "commit":
|
||||
case "rollback":
|
||||
case "close":
|
||||
sender.handleException(t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.IAroundInterceptor;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.InterceptPoint;
|
||||
import com.ai.cloud.skywalking.plugin.interceptor.InterceptorDefine;
|
||||
|
||||
public class ConnectionPluginDefine implements InterceptorDefine {
|
||||
|
||||
@Override
|
||||
public String getBeInterceptedClassName() {
|
||||
return "com.mysql.jdbc.JDBC4Connection";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterceptPoint[] getBeInterceptedMethods() {
|
||||
return new InterceptPoint[] { new InterceptPoint("createStatement", 2),
|
||||
new InterceptPoint("prepareStatement", 3),
|
||||
new InterceptPoint("prepareCall", 3),
|
||||
new InterceptPoint("commit"), new InterceptPoint("rollback"),
|
||||
new InterceptPoint("close") };
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAroundInterceptor instance() {
|
||||
return new ConnectionInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import com.ai.cloud.skywalking.api.IBuriedPointType;
|
||||
import com.ai.cloud.skywalking.protocol.CallType;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
|
@ -24,16 +24,16 @@ import java.sql.Timestamp;
|
|||
import java.util.Calendar;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.CallableStatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.CallableStatementTracing.Executable;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.CallableStatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.CallableStatementTracing.Executable;
|
||||
|
||||
public class SWCallableStatement implements CallableStatement {
|
||||
private SWConnection realConnection;
|
||||
private Connection realConnection;
|
||||
private java.sql.CallableStatement realStatement;
|
||||
private String connectInfo;
|
||||
private String sql;
|
||||
|
||||
SWCallableStatement(SWConnection realConnection,
|
||||
SWCallableStatement(Connection realConnection,
|
||||
java.sql.CallableStatement realStatement, String connectInfo,
|
||||
String sql) {
|
||||
this.realConnection = realConnection;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
|
@ -23,16 +23,16 @@ import java.sql.Time;
|
|||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.PreparedStatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.PreparedStatementTracing.Executable;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.PreparedStatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.PreparedStatementTracing.Executable;
|
||||
|
||||
public class SWPreparedStatement implements PreparedStatement {
|
||||
private SWConnection realConnection;
|
||||
private Connection realConnection;
|
||||
private java.sql.PreparedStatement realStatement;
|
||||
private String connectInfo;
|
||||
private String sql;
|
||||
|
||||
SWPreparedStatement(SWConnection realConnection,
|
||||
SWPreparedStatement(Connection realConnection,
|
||||
java.sql.PreparedStatement realStatement, String connectInfo,
|
||||
String sql) {
|
||||
this.realConnection = realConnection;
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc;
|
||||
package com.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.StatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.tracing.StatementTracing.Executable;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.StatementTracing;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.tracing.StatementTracing.Executable;
|
||||
|
||||
|
||||
public class SWStatement implements java.sql.Statement {
|
||||
private SWConnection realConnection;
|
||||
private Connection realConnection;
|
||||
private java.sql.Statement realStatement;
|
||||
private String connectInfo;
|
||||
|
||||
SWStatement(SWConnection realConnection, java.sql.Statement realStatement, String connectInfo){
|
||||
SWStatement(Connection realConnection, java.sql.Statement realStatement, String connectInfo){
|
||||
this.realConnection = realConnection;
|
||||
this.realStatement = realStatement;
|
||||
this.connectInfo = connectInfo;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc.tracing;
|
||||
package com.ai.cloud.skywalking.plugin.mysql.tracing;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.ai.cloud.skywalking.buriedpoint.RPCBuriedPointSender;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.model.Identification;
|
||||
|
||||
/**
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc.tracing;
|
||||
package com.ai.cloud.skywalking.plugin.mysql.tracing;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.ai.cloud.skywalking.buriedpoint.RPCBuriedPointSender;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.model.Identification;
|
||||
|
||||
/**
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.ai.cloud.skywalking.plugin.jdbc.tracing;
|
||||
package com.ai.cloud.skywalking.plugin.mysql.tracing;
|
||||
|
||||
import com.ai.cloud.skywalking.buriedpoint.RPCBuriedPointSender;
|
||||
import com.ai.cloud.skywalking.plugin.jdbc.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.plugin.mysql.JDBCBuriedPointType;
|
||||
import com.ai.cloud.skywalking.model.Identification;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="error">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d [%t](%F:%L) %-5level %logger{36} - %msg%n" />
|
||||
</Console>
|
||||
<Console name="Console2" 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>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#skyWalking用户ID
|
||||
skywalking.user_id=123
|
||||
#skyWalking应用编码
|
||||
skywalking.application_code=test
|
||||
#skywalking auth的环境变量名字
|
||||
skywalking.auth_system_env_name=SKYWALKING_RUN
|
||||
#skywalking数据编码
|
||||
skywalking.charset=UTF-8
|
||||
|
||||
#是否打印数据
|
||||
buriedpoint.printf=true
|
||||
#埋点异常的最大长度
|
||||
buriedpoint.max_exception_stack_length=4000
|
||||
#业务字段的最大长度
|
||||
buriedpoint.businesskey_max_length=300
|
||||
#过滤异常
|
||||
buriedpoint.exclusive_exceptions=java.lang.RuntimeException
|
||||
|
||||
#最大发送者的连接数阀比例
|
||||
sender.connect_percent=100
|
||||
#发送服务端配置
|
||||
sender.servers_addr=127.0.0.1:34000
|
||||
#最大发送的副本数量
|
||||
sender.max_copy_num=2
|
||||
#发送的最大长度
|
||||
sender.max_send_length=20000
|
||||
#当没有Sender时,尝试获取sender的等待周期
|
||||
sender.retry_get_sender_wait_interval=2000
|
||||
#是否开启发送消息
|
||||
sender.is_off=false
|
||||
|
||||
|
||||
#最大消费线程数
|
||||
consumer.max_consumer=2
|
||||
#消费者最大等待时间
|
||||
consumer.max_wait_time=5
|
||||
#发送失败等待时间
|
||||
consumer.consumer_fail_retry_wait_interval=50
|
||||
|
||||
#每个Buffer的最大个数
|
||||
buffer.buffer_max_size=18000
|
||||
#Buffer池的最大长度
|
||||
buffer.pool_size=5
|
||||
|
||||
#发送检查线程检查周期
|
||||
senderchecker.check_polling_time=200
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
com.ai.cloud.skywalking.plugin.mysql.ConnectionPluginDefine
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package test.ai.cloud.skywalking.plugin.mysql;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ai.cloud.skywalking.plugin.TracingBootstrap;
|
||||
|
||||
public class TestMySQLDriver {
|
||||
@Test
|
||||
public void testsql() throws IllegalAccessException,
|
||||
IllegalArgumentException, InvocationTargetException,
|
||||
NoSuchMethodException, SecurityException, ClassNotFoundException {
|
||||
TracingBootstrap
|
||||
.main(new String[] { "test.ai.cloud.skywalking.plugin.mysql.TestMySQLDriver" });
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws ClassNotFoundException, SQLException, InterruptedException {
|
||||
Class.forName("com.mysql.jdbc.Driver");
|
||||
String url="jdbc:mysql://10.1.228.202:31316/test?user=devrdbusr21&password=devrdbusr21";
|
||||
|
||||
Connection con = DriverManager.getConnection(url);
|
||||
Statement state = con.createStatement();
|
||||
con.setAutoCommit(false);
|
||||
state.execute("select 1 from dual");
|
||||
|
||||
PreparedStatement p0 = con.prepareStatement("select 1 from dual where 1=?");
|
||||
p0.setInt(1, 1);
|
||||
p0.execute();
|
||||
con.commit();
|
||||
con.close();
|
||||
|
||||
Thread.sleep(5* 1000);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<modules>
|
||||
<module>dubbo-plugin</module>
|
||||
<module>spring-plugin</module>
|
||||
<module>jdbc-plugin</module>
|
||||
<module>mysql-plugin</module>
|
||||
<module>web-plugin</module>
|
||||
<module>httpclient-4.2.x-plugin</module>
|
||||
<module>httpclient-4.3.x-plugin</module>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
Loading…
Reference in New Issue