diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..335065b19131127027c83dc841d2176b1f1c1019 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -0,0 +1,84 @@ +package com.a.eye.skywalking.plugin.httpClient.v4; + + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; + +/** + * {@link HttpClientExecuteInterceptor} create span and set the serialized context + * data to {@link HttpRequest#setHeader(Header)} by using {@link #HEADER_NAME_OF_CONTEXT_DATA} for the header key. + * + * @author zhangxin + */ +public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { + public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA"; + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { + Object[] allArguments = interceptorContext.allArguments(); + if (allArguments[0] == null || allArguments[1] == null) { + // illegal args, can't trace. ignore. + return; + } + HttpHost httpHost = (HttpHost) allArguments[0]; + HttpRequest httpRequest = (HttpRequest) allArguments[1]; + + Span span = ContextManager.INSTANCE.createSpan(httpRequest.getRequestLine().getUri()); + Tags.PEER_PORT.set(span, httpHost.getPort()); + Tags.PEER_HOST.set(span, httpHost.getHostName()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); + Tags.URL.set(span, generateURL(httpHost, httpRequest)); + Tags.SPAN_LAYER.asHttp(span); + + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.INSTANCE.inject(contextCarrier); + httpRequest.setHeader(HEADER_NAME_OF_CONTEXT_DATA, contextCarrier.serialize()); + } + + /** + * Generate request URL by using {@link HttpRequest} and {@link HttpHost} + * + * @return request URL + */ + private String generateURL(HttpHost httpHost, HttpRequest httpRequest) { + return httpHost.getSchemeName() + "://" + httpHost.getHostName() + ":" + httpHost.getPort() + httpRequest.getRequestLine().getUri(); + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext, Object ret) { + Object[] allArguments = interceptorContext.allArguments(); + if (allArguments[0] == null || allArguments[1] == null) { + return ret; + } + + HttpResponse response = (HttpResponse) ret; + int statusCode = response.getStatusLine().getStatusCode(); + Span span = ContextManager.INSTANCE.activeSpan(); + if (statusCode != 200) { + Tags.ERROR.set(span, true); + } + + Tags.STATUS_CODE.set(span, statusCode); + ContextManager.INSTANCE.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { + ContextManager.INSTANCE.activeSpan().log(t); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..5a2a8eb23f26eaae1b546738d39cc65370154f16 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java @@ -0,0 +1,53 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking will intercept + * {@link org.apache.http.impl.client.AbstractHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class AbstractHttpClientInstrumentation extends HttpClientInstrumentation { + + /** + * enhance class. + */ + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.AbstractHttpClient"; + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + /** + * version 4.2, intercept method: execute, intercept
+ * public final HttpResponse execute(HttpHost target, HttpRequest request, + * HttpContext context)
+ */ + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("doExecute"); + } + + @Override + public String getMethodsInterceptor() { + return getInstanceMethodsInterceptor(); + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..d0fb67722dca74749e4a3b9c4d53c6e65e936c8e --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java @@ -0,0 +1,53 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking will intercept + * {@link org.apache.http.impl.client.DefaultRequestDirector#execute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class DefaultRequestDirectorInstrumentation extends HttpClientInstrumentation { + + /** + * Enhance class. + */ + private static final String enhanceClass = "org.apache.http.impl.client.DefaultRequestDirector"; + + /** + * DefaultRequestDirector is default implement.
+ * usually use in version 4.0-4.2
+ * since 4.3, this class is Deprecated. + */ + @Override + public String enhanceClassName() { + return enhanceClass; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("execute"); + } + + @Override + public String getMethodsInterceptor() { + return getInstanceMethodsInterceptor(); + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..8d7214427fa7855a07b2ee7b5d87e28ae636d2e6 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java @@ -0,0 +1,28 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; + +/** + * {@link HttpClientInstrumentation} present that skywalking will intercept {@link HttpClientInstrumentation#enhanceClassName()} + * by using {@link com.a.eye.skywalking.plugin.httpClient.v4.HttpClientExecuteInterceptor} + * + * @author zhangxin + */ +public abstract class HttpClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * Intercept class. + */ + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.httpClient.v4.HttpClientExecuteInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + protected String getInstanceMethodsInterceptor() { + return INTERCEPT_CLASS; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..b0ea0c262fc9282ede8a2af6ef1fbf4c22d51196 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java @@ -0,0 +1,47 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking will intercept {@link org.apache.http.impl.client.InternalHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class InternalHttpClientInstrumentation extends HttpClientInstrumentation { + + /** + * Enhance class. + */ + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.InternalHttpClient"; + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("doExecute"); + } + + @Override + public String getMethodsInterceptor() { + return getInstanceMethodsInterceptor(); + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..95b98d86797106bf570b1d905777756ef6ada80f --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java @@ -0,0 +1,48 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking will + * intercept {@link org.apache.http.impl.client.MinimalHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class MinimalHttpClientInstrumentation extends HttpClientInstrumentation { + + /** + * Enhance class. + */ + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.MinimalHttpClient"; + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("doExecute"); + } + + @Override + public String getMethodsInterceptor() { + return getInstanceMethodsInterceptor(); + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java new file mode 100644 index 0000000000000000000000000000000000000000..c295c3676c9e04974cb01e7d6f15fa23d7ce5309 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java @@ -0,0 +1,51 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link CallableStatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/CallableStatement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class CallableStatementTracing { + + public static R execute(java.sql.CallableStatement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/CallableStatement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.CallableStatement realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..3cf0a3d28ca412308126d58de88cfac8c4eba0ab --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java @@ -0,0 +1,63 @@ +package com.a.eye.skywalking.plugin.jdbc; + +/** + * {@link ConnectionInfo} stored the jdbc connection info, the connection info contains db type, host, port, database name. + * The {@link #hosts} be null if {@link #host} is not null. + * + * @author zhangxin + */ +public class ConnectionInfo { + /** + * DB type, such as mysql, oracle, h2. + */ + private final String dbType; + /** + * Database host name. + */ + private String host; + /** + * Database port. + */ + private int port; + /** + * Operation database name. + */ + private final String databaseName; + /** + * Database hosts. + */ + private String hosts; + + public ConnectionInfo(String dbType, String host, int port, String databaseName) { + this.dbType = dbType; + this.host = host; + this.port = port; + this.databaseName = databaseName; + } + + public ConnectionInfo(String dbType, String hosts, String databaseName) { + this.dbType = dbType; + this.hosts = hosts; + this.databaseName = databaseName; + } + + public String getDBType() { + return dbType; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getDatabaseName() { + return databaseName; + } + + public String getHosts() { + return hosts; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java new file mode 100755 index 0000000000000000000000000000000000000000..35d7417e41096f8d2d936b13ca6728189661138d --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java @@ -0,0 +1,51 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link ConnectionTracing} create span with the {@link Span#operationName} start with + * "JDBC/Connection/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class ConnectionTracing { + + public static R execute(java.sql.Connection realConnection, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/Connection/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realConnection, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.Connection realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java new file mode 100644 index 0000000000000000000000000000000000000000..ed181b94a139e2a626e7a7f5353402e8ac2411a5 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java @@ -0,0 +1,50 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link PreparedStatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/PreparedStatement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class PreparedStatementTracing { + + public static R execute(java.sql.PreparedStatement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/PreparedStatement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.PreparedStatement realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java new file mode 100644 index 0000000000000000000000000000000000000000..6b9fa5a6fdc9bac5f2925b57639f0f31655d4e96 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java @@ -0,0 +1,1039 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; +import java.util.Map; + +public class SWCallableStatement implements CallableStatement { + private Connection realConnection; + private CallableStatement realStatement; + private ConnectionInfo connectInfo; + private String sql; + + SWCallableStatement(Connection realConnection, + CallableStatement realStatement, ConnectionInfo connectInfo, + String sql) { + this.realConnection = realConnection; + this.realStatement = realStatement; + this.connectInfo = connectInfo; + this.sql = sql; + } + + public ResultSet executeQuery() throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeQuery", sql, new CallableStatementTracing.Executable() { + public ResultSet exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeQuery(); + } + }); + } + + public int executeUpdate() throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeUpdate", sql, new CallableStatementTracing.Executable() { + public Integer exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(); + } + }); + } + + public void setNull(int parameterIndex, int sqlType) throws SQLException { + realStatement.setNull(parameterIndex, sqlType); + } + + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + realStatement.setBoolean(parameterIndex, x); + } + + public void setByte(int parameterIndex, byte x) throws SQLException { + realStatement.setByte(parameterIndex, x); + } + + public void setShort(int parameterIndex, short x) throws SQLException { + realStatement.setShort(parameterIndex, x); + } + + public void setInt(int parameterIndex, int x) throws SQLException { + realStatement.setInt(parameterIndex, x); + } + + public void setLong(int parameterIndex, long x) throws SQLException { + realStatement.setLong(parameterIndex, x); + } + + public void setFloat(int parameterIndex, float x) throws SQLException { + realStatement.setFloat(parameterIndex, x); + } + + public void setDouble(int parameterIndex, double x) throws SQLException { + realStatement.setDouble(parameterIndex, x); + } + + public void setBigDecimal(int parameterIndex, BigDecimal x) + throws SQLException { + realStatement.setBigDecimal(parameterIndex, x); + } + + public void setString(int parameterIndex, String x) throws SQLException { + realStatement.setString(parameterIndex, x); + } + + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + realStatement.setBytes(parameterIndex, x); + } + + public void setDate(int parameterIndex, Date x) throws SQLException { + realStatement.setDate(parameterIndex, x); + } + + public void setTime(int parameterIndex, Time x) throws SQLException { + realStatement.setTime(parameterIndex, x); + } + + public void setTimestamp(int parameterIndex, Timestamp x) + throws SQLException { + realStatement.setTimestamp(parameterIndex, x); + } + + public void setAsciiStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x, length); + } + + @Deprecated + public void setUnicodeStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setUnicodeStream(parameterIndex, x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x, length); + } + + public void clearParameters() throws SQLException { + realStatement.clearParameters(); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType) + throws SQLException { + realStatement.setObject(parameterIndex, x, targetSqlType); + } + + public void setObject(int parameterIndex, Object x) throws SQLException { + realStatement.setObject(parameterIndex, x); + } + + public boolean execute() throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "execute", sql, new CallableStatementTracing.Executable() { + public Boolean exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(); + } + }); + } + + public void addBatch() throws SQLException { + realStatement.addBatch(); + } + + public void setCharacterStream(int parameterIndex, Reader reader, int length) + throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader, length); + } + + public void setRef(int parameterIndex, Ref x) throws SQLException { + realStatement.setRef(parameterIndex, x); + } + + public void setBlob(int parameterIndex, Blob x) throws SQLException { + realStatement.setBlob(parameterIndex, x); + } + + public void setClob(int parameterIndex, Clob x) throws SQLException { + realStatement.setClob(parameterIndex, x); + } + + public void setArray(int parameterIndex, Array x) throws SQLException { + realStatement.setArray(parameterIndex, x); + } + + public ResultSetMetaData getMetaData() throws SQLException { + return realStatement.getMetaData(); + } + + public void setDate(int parameterIndex, Date x, Calendar cal) + throws SQLException { + realStatement.setDate(parameterIndex, x, cal); + } + + public void setTime(int parameterIndex, Time x, Calendar cal) + throws SQLException { + realStatement.setTime(parameterIndex, x, cal); + } + + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) + throws SQLException { + realStatement.setTimestamp(parameterIndex, x, cal); + } + + public void setNull(int parameterIndex, int sqlType, String typeName) + throws SQLException { + realStatement.setNull(parameterIndex, sqlType, typeName); + } + + public void setURL(int parameterIndex, URL x) throws SQLException { + realStatement.setURL(parameterIndex, x); + } + + public ParameterMetaData getParameterMetaData() throws SQLException { + return realStatement.getParameterMetaData(); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + realStatement.setRowId(parameterIndex, x); + } + + public void setNString(int parameterIndex, String value) + throws SQLException { + realStatement.setNString(parameterIndex, value); + } + + public void setNCharacterStream(int parameterIndex, Reader value, + long length) throws SQLException { + realStatement.setNCharacterStream(parameterIndex, value, length); + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + realStatement.setNClob(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader, long length) + throws SQLException { + realStatement.setClob(parameterIndex, reader, length); + } + + public void setBlob(int parameterIndex, InputStream inputStream, long length) + throws SQLException { + realStatement.setBlob(parameterIndex, inputStream, length); + } + + public void setNClob(int parameterIndex, Reader reader, long length) + throws SQLException { + realStatement.setNClob(parameterIndex, reader, length); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + realStatement.setSQLXML(parameterIndex, xmlObject); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType, + int scaleOrLength) throws SQLException { + realStatement + .setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x, length); + } + + public void setCharacterStream(int parameterIndex, Reader reader, + long length) throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader, length); + } + + public void setAsciiStream(int parameterIndex, InputStream x) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x); + } + + public void setBinaryStream(int parameterIndex, InputStream x) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x); + } + + public void setCharacterStream(int parameterIndex, Reader reader) + throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader); + } + + public void setNCharacterStream(int parameterIndex, Reader value) + throws SQLException { + realStatement.setNCharacterStream(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException { + realStatement.setClob(parameterIndex, reader); + } + + public void setBlob(int parameterIndex, InputStream inputStream) + throws SQLException { + realStatement.setBlob(parameterIndex, inputStream); + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + realStatement.setNClob(parameterIndex, reader); + } + + public ResultSet executeQuery(String sql) throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeQuery", sql, new CallableStatementTracing.Executable() { + public ResultSet exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeQuery(sql); + } + }); + } + + public int executeUpdate(String sql) throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeUpdate", sql, new CallableStatementTracing.Executable() { + public Integer exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql); + } + }); + } + + public void close() throws SQLException { + realStatement.close(); + } + + public int getMaxFieldSize() throws SQLException { + return realStatement.getMaxFieldSize(); + } + + public void setMaxFieldSize(int max) throws SQLException { + realStatement.setMaxFieldSize(max); + } + + public int getMaxRows() throws SQLException { + return realStatement.getMaxRows(); + } + + public void setMaxRows(int max) throws SQLException { + realStatement.setMaxRows(max); + } + + public void setEscapeProcessing(boolean enable) throws SQLException { + realStatement.setEscapeProcessing(enable); + } + + public int getQueryTimeout() throws SQLException { + return realStatement.getQueryTimeout(); + } + + public void setQueryTimeout(int seconds) throws SQLException { + realStatement.setQueryTimeout(seconds); + } + + public void cancel() throws SQLException { + realStatement.cancel(); + } + + public SQLWarning getWarnings() throws SQLException { + return realStatement.getWarnings(); + } + + public void clearWarnings() throws SQLException { + realStatement.clearWarnings(); + } + + public void setCursorName(String name) throws SQLException { + realStatement.setCursorName(name); + } + + public boolean execute(String sql) throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "execute", sql, new CallableStatementTracing.Executable() { + public Boolean exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql); + } + }); + } + + public ResultSet getResultSet() throws SQLException { + return realStatement.getResultSet(); + } + + public int getUpdateCount() throws SQLException { + return realStatement.getUpdateCount(); + } + + public boolean getMoreResults() throws SQLException { + return realStatement.getMoreResults(); + } + + public void setFetchDirection(int direction) throws SQLException { + realStatement.setFetchDirection(direction); + } + + public int getFetchDirection() throws SQLException { + return realStatement.getFetchDirection(); + } + + public void setFetchSize(int rows) throws SQLException { + realStatement.setFetchSize(rows); + } + + public int getFetchSize() throws SQLException { + return realStatement.getFetchSize(); + } + + public int getResultSetConcurrency() throws SQLException { + return realStatement.getResultSetConcurrency(); + } + + public int getResultSetType() throws SQLException { + return realStatement.getResultSetType(); + } + + public void addBatch(String sql) throws SQLException { + realStatement.addBatch(); + } + + public void clearBatch() throws SQLException { + realStatement.clearBatch(); + } + + public int[] executeBatch() throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeBatch", "", new CallableStatementTracing.Executable() { + public int[] exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeBatch(); + } + }); + } + + public Connection getConnection() throws SQLException { + return this.realConnection; + } + + public boolean getMoreResults(int current) throws SQLException { + return realStatement.getMoreResults(current); + } + + public ResultSet getGeneratedKeys() throws SQLException { + return realStatement.getGeneratedKeys(); + } + + public int executeUpdate(String sql, final int autoGeneratedKeys) + throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeUpdate", sql, new CallableStatementTracing.Executable() { + public Integer exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, autoGeneratedKeys); + } + }); + } + + public int executeUpdate(String sql, final int[] columnIndexes) + throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeUpdate", sql, new CallableStatementTracing.Executable() { + public Integer exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnIndexes); + } + }); + } + + public int executeUpdate(String sql, final String[] columnNames) + throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "executeUpdate", sql, new CallableStatementTracing.Executable() { + public Integer exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnNames); + } + }); + } + + public boolean execute(String sql, final int autoGeneratedKeys) + throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "execute", sql, new CallableStatementTracing.Executable() { + public Boolean exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, autoGeneratedKeys); + } + }); + } + + public boolean execute(String sql, final int[] columnIndexes) throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "execute", sql, new CallableStatementTracing.Executable() { + public Boolean exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnIndexes); + } + }); + } + + public boolean execute(String sql, final String[] columnNames) + throws SQLException { + return CallableStatementTracing.execute(realStatement, connectInfo, + "execute", sql, new CallableStatementTracing.Executable() { + public Boolean exe( + CallableStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnNames); + } + }); + } + + public int getResultSetHoldability() throws SQLException { + return realStatement.getResultSetHoldability(); + } + + public boolean isClosed() throws SQLException { + return realStatement.isClosed(); + } + + public void setPoolable(boolean poolable) throws SQLException { + realStatement.setPoolable(poolable); + } + + public boolean isPoolable() throws SQLException { + return realStatement.isPoolable(); + } + + public void closeOnCompletion() throws SQLException { + realStatement.closeOnCompletion(); + } + + public boolean isCloseOnCompletion() throws SQLException { + return realStatement.isCloseOnCompletion(); + } + + public T unwrap(Class iface) throws SQLException { + return realStatement.unwrap(iface); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + return realStatement.isWrapperFor(iface); + } + + public void registerOutParameter(int parameterIndex, int sqlType) + throws SQLException { + realStatement.registerOutParameter(parameterIndex, sqlType); + } + + public void registerOutParameter(int parameterIndex, int sqlType, int scale) + throws SQLException { + realStatement.registerOutParameter(parameterIndex, sqlType, scale); + } + + public boolean wasNull() throws SQLException { + return realStatement.wasNull(); + } + + public String getString(int parameterIndex) throws SQLException { + return realStatement.getString(parameterIndex); + } + + public boolean getBoolean(int parameterIndex) throws SQLException { + return realStatement.getBoolean(parameterIndex); + } + + public byte getByte(int parameterIndex) throws SQLException { + return realStatement.getByte(parameterIndex); + } + + public short getShort(int parameterIndex) throws SQLException { + return realStatement.getShort(parameterIndex); + } + + public int getInt(int parameterIndex) throws SQLException { + return realStatement.getInt(parameterIndex); + } + + public long getLong(int parameterIndex) throws SQLException { + return realStatement.getLong(parameterIndex); + } + + public float getFloat(int parameterIndex) throws SQLException { + return realStatement.getFloat(parameterIndex); + } + + public double getDouble(int parameterIndex) throws SQLException { + return realStatement.getDouble(parameterIndex); + } + + @Deprecated + public BigDecimal getBigDecimal(int parameterIndex, int scale) + throws SQLException { + return realStatement.getBigDecimal(parameterIndex, scale); + } + + public byte[] getBytes(int parameterIndex) throws SQLException { + return realStatement.getBytes(parameterIndex); + } + + public Date getDate(int parameterIndex) throws SQLException { + return realStatement.getDate(parameterIndex); + } + + public Time getTime(int parameterIndex) throws SQLException { + return realStatement.getTime(parameterIndex); + } + + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + return realStatement.getTimestamp(parameterIndex); + } + + public Object getObject(int parameterIndex) throws SQLException { + return realStatement.getObject(parameterIndex); + } + + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + return realStatement.getBigDecimal(parameterIndex); + } + + public Object getObject(int parameterIndex, Map> map) + throws SQLException { + return realStatement.getObject(parameterIndex, map); + } + + public Ref getRef(int parameterIndex) throws SQLException { + return realStatement.getRef(parameterIndex); + } + + public Blob getBlob(int parameterIndex) throws SQLException { + return realStatement.getBlob(parameterIndex); + } + + public Clob getClob(int parameterIndex) throws SQLException { + return realStatement.getClob(parameterIndex); + } + + public Array getArray(int parameterIndex) throws SQLException { + return realStatement.getArray(parameterIndex); + } + + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { + return realStatement.getDate(parameterIndex, cal); + } + + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { + return realStatement.getTime(parameterIndex, cal); + } + + public Timestamp getTimestamp(int parameterIndex, Calendar cal) + throws SQLException { + return realStatement.getTimestamp(parameterIndex, cal); + } + + public void registerOutParameter(int parameterIndex, int sqlType, + String typeName) throws SQLException { + realStatement.registerOutParameter(parameterIndex, sqlType, typeName); + } + + public void registerOutParameter(String parameterName, int sqlType) + throws SQLException { + realStatement.registerOutParameter(parameterName, sqlType); + } + + public void registerOutParameter(String parameterName, int sqlType, + int scale) throws SQLException { + realStatement.registerOutParameter(parameterName, sqlType, scale); + } + + public void registerOutParameter(String parameterName, int sqlType, + String typeName) throws SQLException { + realStatement.registerOutParameter(parameterName, sqlType, typeName); + } + + public URL getURL(int parameterIndex) throws SQLException { + return realStatement.getURL(parameterIndex); + } + + public void setURL(String parameterName, URL val) throws SQLException { + realStatement.setURL(parameterName, val); + } + + public void setNull(String parameterName, int sqlType) throws SQLException { + realStatement.setNull(parameterName, sqlType); + } + + public void setBoolean(String parameterName, boolean x) throws SQLException { + realStatement.setBoolean(parameterName, x); + } + + public void setByte(String parameterName, byte x) throws SQLException { + realStatement.setByte(parameterName, x); + } + + public void setShort(String parameterName, short x) throws SQLException { + realStatement.setShort(parameterName, x); + } + + public void setInt(String parameterName, int x) throws SQLException { + realStatement.setInt(parameterName, x); + } + + public void setLong(String parameterName, long x) throws SQLException { + realStatement.setLong(parameterName, x); + } + + public void setFloat(String parameterName, float x) throws SQLException { + realStatement.setFloat(parameterName, x); + } + + public void setDouble(String parameterName, double x) throws SQLException { + realStatement.setDouble(parameterName, x); + } + + public void setBigDecimal(String parameterName, BigDecimal x) + throws SQLException { + realStatement.setBigDecimal(parameterName, x); + } + + public void setString(String parameterName, String x) throws SQLException { + realStatement.setString(parameterName, x); + } + + public void setBytes(String parameterName, byte[] x) throws SQLException { + realStatement.setBytes(parameterName, x); + } + + public void setDate(String parameterName, Date x) throws SQLException { + realStatement.setDate(parameterName, x); + } + + public void setTime(String parameterName, Time x) throws SQLException { + realStatement.setTime(parameterName, x); + } + + public void setTimestamp(String parameterName, Timestamp x) + throws SQLException { + realStatement.setTimestamp(parameterName, x); + } + + public void setAsciiStream(String parameterName, InputStream x, int length) + throws SQLException { + realStatement.setAsciiStream(parameterName, x, length); + } + + public void setBinaryStream(String parameterName, InputStream x, int length) + throws SQLException { + realStatement.setBinaryStream(parameterName, x, length); + } + + public void setObject(String parameterName, Object x, int targetSqlType, + int scale) throws SQLException { + realStatement.setObject(parameterName, x, targetSqlType, scale); + } + + public void setObject(String parameterName, Object x, int targetSqlType) + throws SQLException { + realStatement.setObject(parameterName, x, targetSqlType); + } + + public void setObject(String parameterName, Object x) throws SQLException { + realStatement.setObject(parameterName, x); + } + + public void setCharacterStream(String parameterName, Reader reader, + int length) throws SQLException { + realStatement.setCharacterStream(parameterName, reader, length); + } + + public void setDate(String parameterName, Date x, Calendar cal) + throws SQLException { + realStatement.setDate(parameterName, x, cal); + } + + public void setTime(String parameterName, Time x, Calendar cal) + throws SQLException { + realStatement.setTime(parameterName, x, cal); + } + + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) + throws SQLException { + realStatement.setTimestamp(parameterName, x, cal); + } + + public void setNull(String parameterName, int sqlType, String typeName) + throws SQLException { + realStatement.setNull(parameterName, sqlType, typeName); + } + + public String getString(String parameterName) throws SQLException { + return realStatement.getString(parameterName); + } + + public boolean getBoolean(String parameterName) throws SQLException { + return realStatement.getBoolean(parameterName); + } + + public byte getByte(String parameterName) throws SQLException { + return realStatement.getByte(parameterName); + } + + public short getShort(String parameterName) throws SQLException { + return realStatement.getShort(parameterName); + } + + public int getInt(String parameterName) throws SQLException { + return realStatement.getInt(parameterName); + } + + public long getLong(String parameterName) throws SQLException { + return realStatement.getLong(parameterName); + } + + public float getFloat(String parameterName) throws SQLException { + return realStatement.getFloat(parameterName); + } + + public double getDouble(String parameterName) throws SQLException { + return realStatement.getDouble(parameterName); + } + + public byte[] getBytes(String parameterName) throws SQLException { + return realStatement.getBytes(parameterName); + } + + public Date getDate(String parameterName) throws SQLException { + return realStatement.getDate(parameterName); + } + + public Time getTime(String parameterName) throws SQLException { + return realStatement.getTime(parameterName); + } + + public Timestamp getTimestamp(String parameterName) throws SQLException { + return realStatement.getTimestamp(parameterName); + } + + public Object getObject(String parameterName) throws SQLException { + return realStatement.getObject(parameterName); + } + + public BigDecimal getBigDecimal(String parameterName) throws SQLException { + return realStatement.getBigDecimal(parameterName); + } + + public Object getObject(String parameterName, Map> map) + throws SQLException { + return realStatement.getObject(parameterName, map); + } + + public Ref getRef(String parameterName) throws SQLException { + return realStatement.getRef(parameterName); + } + + public Blob getBlob(String parameterName) throws SQLException { + return realStatement.getBlob(parameterName); + } + + public Clob getClob(String parameterName) throws SQLException { + return realStatement.getClob(parameterName); + } + + public Array getArray(String parameterName) throws SQLException { + return realStatement.getArray(parameterName); + } + + public Date getDate(String parameterName, Calendar cal) throws SQLException { + return realStatement.getDate(parameterName, cal); + } + + public Time getTime(String parameterName, Calendar cal) throws SQLException { + return realStatement.getTime(parameterName, cal); + } + + public Timestamp getTimestamp(String parameterName, Calendar cal) + throws SQLException { + return realStatement.getTimestamp(parameterName, cal); + } + + public URL getURL(String parameterName) throws SQLException { + return realStatement.getURL(parameterName); + } + + public RowId getRowId(int parameterIndex) throws SQLException { + return realStatement.getRowId(parameterIndex); + } + + public RowId getRowId(String parameterName) throws SQLException { + return realStatement.getRowId(parameterName); + } + + public void setRowId(String parameterName, RowId x) throws SQLException { + realStatement.setRowId(parameterName, x); + } + + public void setNString(String parameterName, String value) + throws SQLException { + realStatement.setNString(parameterName, value); + } + + public void setNCharacterStream(String parameterName, Reader value, + long length) throws SQLException { + realStatement.setNCharacterStream(parameterName, value, length); + } + + public void setNClob(String parameterName, NClob value) throws SQLException { + realStatement.setNClob(parameterName, value); + } + + public void setClob(String parameterName, Reader reader, long length) + throws SQLException { + realStatement.setClob(parameterName, reader, length); + } + + public void setBlob(String parameterName, InputStream inputStream, + long length) throws SQLException { + realStatement.setBlob(parameterName, inputStream, length); + } + + public void setNClob(String parameterName, Reader reader, long length) + throws SQLException { + realStatement.setNClob(parameterName, reader, length); + } + + public NClob getNClob(int parameterIndex) throws SQLException { + return realStatement.getNClob(parameterIndex); + } + + public NClob getNClob(String parameterName) throws SQLException { + return realStatement.getNClob(parameterName); + } + + public void setSQLXML(String parameterName, SQLXML xmlObject) + throws SQLException { + realStatement.setSQLXML(parameterName, xmlObject); + } + + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + return realStatement.getSQLXML(parameterIndex); + } + + public SQLXML getSQLXML(String parameterName) throws SQLException { + return realStatement.getSQLXML(parameterName); + } + + public String getNString(int parameterIndex) throws SQLException { + return realStatement.getNString(parameterIndex); + } + + public String getNString(String parameterName) throws SQLException { + return realStatement.getNString(parameterName); + } + + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + return realStatement.getNCharacterStream(parameterIndex); + } + + public Reader getNCharacterStream(String parameterName) throws SQLException { + return realStatement.getNCharacterStream(parameterName); + } + + public Reader getCharacterStream(int parameterIndex) throws SQLException { + return realStatement.getCharacterStream(parameterIndex); + } + + public Reader getCharacterStream(String parameterName) throws SQLException { + return realStatement.getCharacterStream(parameterName); + } + + public void setBlob(String parameterName, Blob x) throws SQLException { + realStatement.setBlob(parameterName, x); + } + + public void setClob(String parameterName, Clob x) throws SQLException { + realStatement.setClob(parameterName, x); + } + + public void setAsciiStream(String parameterName, InputStream x, long length) + throws SQLException { + realStatement.setAsciiStream(parameterName, x, length); + } + + public void setBinaryStream(String parameterName, InputStream x, long length) + throws SQLException { + realStatement.setBinaryStream(parameterName, x, length); + } + + public void setCharacterStream(String parameterName, Reader reader, + long length) throws SQLException { + realStatement.setCharacterStream(parameterName, reader, length); + } + + public void setAsciiStream(String parameterName, InputStream x) + throws SQLException { + realStatement.setAsciiStream(parameterName, x); + } + + public void setBinaryStream(String parameterName, InputStream x) + throws SQLException { + realStatement.setBinaryStream(parameterName, x); + } + + public void setCharacterStream(String parameterName, Reader reader) + throws SQLException { + realStatement.setCharacterStream(parameterName, reader); + } + + public void setNCharacterStream(String parameterName, Reader value) + throws SQLException { + realStatement.setNCharacterStream(parameterName, value); + } + + public void setClob(String parameterName, Reader reader) + throws SQLException { + realStatement.setClob(parameterName, reader); + } + + public void setBlob(String parameterName, InputStream inputStream) + throws SQLException { + realStatement.setBlob(parameterName, inputStream); + } + + public void setNClob(String parameterName, Reader reader) + throws SQLException { + realStatement.setNClob(parameterName, reader); + } + + public T getObject(int parameterIndex, Class type) + throws SQLException { + return realStatement.getObject(parameterIndex, type); + } + + public T getObject(String parameterName, Class type) + throws SQLException { + return realStatement.getObject(parameterName, type); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java new file mode 100755 index 0000000000000000000000000000000000000000..919927cd7beefaedded1e89f184ecc59ea845eaa --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java @@ -0,0 +1,318 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.plugin.jdbc.connectionurl.parser.URLParser; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +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; + +public class SWConnection implements Connection { + private ConnectionInfo connectInfo; + private final Connection realConnection; + + public SWConnection(String url, Properties info, Connection realConnection) { + super(); + this.connectInfo = URLParser.parser(url); + this.realConnection = realConnection; + } + + public T unwrap(Class 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 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 ConnectionTracing.Executable() { + 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 ConnectionTracing.Executable() { + 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 ConnectionTracing.Executable() { + 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> getTypeMap() throws SQLException { + return realConnection.getTypeMap(); + } + + public void setTypeMap(Map> 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 ConnectionTracing.Executable() { + 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 ConnectionTracing.Executable() { + 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(); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java new file mode 100644 index 0000000000000000000000000000000000000000..57186d0ce3deba05fb348b8a14fe19e8f457e8ea --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java @@ -0,0 +1,518 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; + +public class SWPreparedStatement implements PreparedStatement { + private Connection realConnection; + private PreparedStatement realStatement; + private ConnectionInfo connectInfo; + private String sql; + + SWPreparedStatement(Connection realConnection, + PreparedStatement realStatement, ConnectionInfo connectInfo, + String sql) { + this.realConnection = realConnection; + this.realStatement = realStatement; + this.connectInfo = connectInfo; + this.sql = sql; + } + + public ResultSet executeQuery(String sql) throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeQuery", sql, new PreparedStatementTracing.Executable() { + public ResultSet exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeQuery(sql); + } + }); + } + + public int executeUpdate(String sql) throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Integer exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql); + } + }); + } + + public void close() throws SQLException { + realStatement.close(); + } + + public int getMaxFieldSize() throws SQLException { + return realStatement.getMaxFieldSize(); + } + + public void setMaxFieldSize(int max) throws SQLException { + realStatement.setMaxFieldSize(max); + } + + public int getMaxRows() throws SQLException { + return realStatement.getMaxRows(); + } + + public void setMaxRows(int max) throws SQLException { + realStatement.setMaxRows(max); + } + + public void setEscapeProcessing(boolean enable) throws SQLException { + realStatement.setEscapeProcessing(enable); + } + + public int getQueryTimeout() throws SQLException { + return realStatement.getQueryTimeout(); + } + + public void setQueryTimeout(int seconds) throws SQLException { + realStatement.setQueryTimeout(seconds); + } + + public void cancel() throws SQLException { + realStatement.cancel(); + } + + public SQLWarning getWarnings() throws SQLException { + return realStatement.getWarnings(); + } + + public void clearWarnings() throws SQLException { + realStatement.clearWarnings(); + } + + public void setCursorName(String name) throws SQLException { + realStatement.setCursorName(name); + } + + public boolean execute(String sql) throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "execute", sql, new PreparedStatementTracing.Executable() { + public Boolean exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql); + } + }); + } + + public ResultSet getResultSet() throws SQLException { + return realStatement.getResultSet(); + } + + public int getUpdateCount() throws SQLException { + return realStatement.getUpdateCount(); + } + + public boolean getMoreResults() throws SQLException { + return realStatement.getMoreResults(); + } + + public void setFetchDirection(int direction) throws SQLException { + realStatement.setFetchDirection(direction); + } + + public int getFetchDirection() throws SQLException { + return realStatement.getFetchDirection(); + } + + public void setFetchSize(int rows) throws SQLException { + realStatement.setFetchSize(rows); + } + + public int getFetchSize() throws SQLException { + return realStatement.getFetchSize(); + } + + public int getResultSetConcurrency() throws SQLException { + return realStatement.getResultSetConcurrency(); + } + + public int getResultSetType() throws SQLException { + return realStatement.getResultSetType(); + } + + public void addBatch(String sql) throws SQLException { + realStatement.addBatch(sql); + } + + public void clearBatch() throws SQLException { + realStatement.clearBatch(); + } + + public int[] executeBatch() throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeBatch", "", new PreparedStatementTracing.Executable() { + public int[] exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeBatch(); + } + }); + } + + public Connection getConnection() throws SQLException { + return realConnection; + } + + public boolean getMoreResults(int current) throws SQLException { + return realStatement.getMoreResults(current); + } + + public ResultSet getGeneratedKeys() throws SQLException { + return realStatement.getGeneratedKeys(); + } + + public int executeUpdate(String sql, final int autoGeneratedKeys) + throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Integer exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, autoGeneratedKeys); + } + }); + } + + public int executeUpdate(String sql, final int[] columnIndexes) + throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Integer exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnIndexes); + } + }); + } + + public int executeUpdate(String sql, final String[] columnNames) + throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Integer exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnNames); + } + }); + } + + public boolean execute(String sql, final int autoGeneratedKeys) + throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "execute", sql, new PreparedStatementTracing.Executable() { + public Boolean exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, autoGeneratedKeys); + } + }); + } + + public boolean execute(String sql, final int[] columnIndexes) throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "execute", sql, new PreparedStatementTracing.Executable() { + public Boolean exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnIndexes); + } + }); + } + + public boolean execute(String sql, final String[] columnNames) + throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "execute", sql, new PreparedStatementTracing.Executable() { + public Boolean exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnNames); + } + }); + } + + public int getResultSetHoldability() throws SQLException { + return realStatement.getResultSetHoldability(); + } + + public boolean isClosed() throws SQLException { + return realStatement.isClosed(); + } + + public void setPoolable(boolean poolable) throws SQLException { + realStatement.setPoolable(poolable); + } + + public boolean isPoolable() throws SQLException { + return realStatement.isPoolable(); + } + + public void closeOnCompletion() throws SQLException { + realStatement.closeOnCompletion(); + } + + public boolean isCloseOnCompletion() throws SQLException { + return realStatement.isCloseOnCompletion(); + } + + public T unwrap(Class iface) throws SQLException { + return realStatement.unwrap(iface); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + return realStatement.isWrapperFor(iface); + } + + public ResultSet executeQuery() throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeQuery", sql, new PreparedStatementTracing.Executable() { + public ResultSet exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeQuery(); + } + }); + } + + public int executeUpdate() throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Integer exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(); + } + }); + } + + public void setNull(int parameterIndex, int sqlType) throws SQLException { + realStatement.setNull(parameterIndex, sqlType); + } + + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + realStatement.setBoolean(parameterIndex, x); + } + + public void setByte(int parameterIndex, byte x) throws SQLException { + realStatement.setByte(parameterIndex, x); + } + + public void setShort(int parameterIndex, short x) throws SQLException { + realStatement.setShort(parameterIndex, x); + } + + public void setInt(int parameterIndex, int x) throws SQLException { + realStatement.setInt(parameterIndex, x); + } + + public void setLong(int parameterIndex, long x) throws SQLException { + realStatement.setLong(parameterIndex, x); + } + + public void setFloat(int parameterIndex, float x) throws SQLException { + realStatement.setFloat(parameterIndex, x); + } + + public void setDouble(int parameterIndex, double x) throws SQLException { + realStatement.setDouble(parameterIndex, x); + } + + public void setBigDecimal(int parameterIndex, BigDecimal x) + throws SQLException { + realStatement.setBigDecimal(parameterIndex, x); + } + + public void setString(int parameterIndex, String x) throws SQLException { + realStatement.setString(parameterIndex, x); + } + + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + realStatement.setBytes(parameterIndex, x); + } + + public void setDate(int parameterIndex, Date x) throws SQLException { + realStatement.setDate(parameterIndex, x); + } + + public void setTime(int parameterIndex, Time x) throws SQLException { + realStatement.setTime(parameterIndex, x); + } + + public void setTimestamp(int parameterIndex, Timestamp x) + throws SQLException { + realStatement.setTimestamp(parameterIndex, x); + } + + public void setAsciiStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x, length); + } + + @Deprecated + public void setUnicodeStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setUnicodeStream(parameterIndex, x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, int length) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x, length); + } + + public void clearParameters() throws SQLException { + realStatement.clearParameters(); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType) + throws SQLException { + realStatement.setObject(parameterIndex, x, targetSqlType); + } + + public void setObject(int parameterIndex, Object x) throws SQLException { + realStatement.setObject(parameterIndex, x); + } + + public boolean execute() throws SQLException { + return PreparedStatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new PreparedStatementTracing.Executable() { + public Boolean exe(PreparedStatement realStatement, String sql) + throws SQLException { + return realStatement.execute(); + } + }); + } + + public void addBatch() throws SQLException { + realStatement.addBatch(); + } + + public void setCharacterStream(int parameterIndex, Reader reader, int length) + throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader, length); + } + + public void setRef(int parameterIndex, Ref x) throws SQLException { + realStatement.setRef(parameterIndex, x); + } + + public void setBlob(int parameterIndex, Blob x) throws SQLException { + realStatement.setBlob(parameterIndex, x); + } + + public void setClob(int parameterIndex, Clob x) throws SQLException { + realStatement.setClob(parameterIndex, x); + } + + public void setArray(int parameterIndex, Array x) throws SQLException { + realStatement.setArray(parameterIndex, x); + } + + public ResultSetMetaData getMetaData() throws SQLException { + return realStatement.getMetaData(); + } + + public void setDate(int parameterIndex, Date x, Calendar cal) + throws SQLException { + realStatement.setDate(parameterIndex, x, cal); + } + + public void setTime(int parameterIndex, Time x, Calendar cal) + throws SQLException { + realStatement.setTime(parameterIndex, x, cal); + } + + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) + throws SQLException { + realStatement.setTimestamp(parameterIndex, x, cal); + } + + public void setNull(int parameterIndex, int sqlType, String typeName) + throws SQLException { + realStatement.setNull(parameterIndex, sqlType, typeName); + } + + public void setURL(int parameterIndex, URL x) throws SQLException { + realStatement.setURL(parameterIndex, x); + } + + public ParameterMetaData getParameterMetaData() throws SQLException { + return realStatement.getParameterMetaData(); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + realStatement.setRowId(parameterIndex, x); + } + + public void setNString(int parameterIndex, String value) + throws SQLException { + realStatement.setNString(parameterIndex, value); + } + + public void setNCharacterStream(int parameterIndex, Reader value, + long length) throws SQLException { + realStatement.setNCharacterStream(parameterIndex, value, length); + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + realStatement.setNClob(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader, long length) + throws SQLException { + realStatement.setClob(parameterIndex, reader, length); + } + + public void setBlob(int parameterIndex, InputStream inputStream, long length) + throws SQLException { + realStatement.setBlob(parameterIndex, inputStream, length); + } + + public void setNClob(int parameterIndex, Reader reader, long length) + throws SQLException { + realStatement.setNClob(parameterIndex, reader, length); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) + throws SQLException { + realStatement.setSQLXML(parameterIndex, xmlObject); + } + + public void setObject(int parameterIndex, Object x, int targetSqlType, + int scaleOrLength) throws SQLException { + realStatement.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x, length); + } + + public void setCharacterStream(int parameterIndex, Reader reader, + long length) throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader, length); + } + + public void setAsciiStream(int parameterIndex, InputStream x) + throws SQLException { + realStatement.setAsciiStream(parameterIndex, x); + } + + public void setBinaryStream(int parameterIndex, InputStream x) + throws SQLException { + realStatement.setBinaryStream(parameterIndex, x); + } + + public void setCharacterStream(int parameterIndex, Reader reader) + throws SQLException { + realStatement.setCharacterStream(parameterIndex, reader); + } + + public void setNCharacterStream(int parameterIndex, Reader value) + throws SQLException { + realStatement.setNCharacterStream(parameterIndex, value); + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException { + realStatement.setClob(parameterIndex, reader); + } + + public void setBlob(int parameterIndex, InputStream inputStream) + throws SQLException { + realStatement.setBlob(parameterIndex, inputStream); + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + realStatement.setNClob(parameterIndex, reader); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java new file mode 100644 index 0000000000000000000000000000000000000000..2d212b7a5e266b1e19adf36421164452a0b5ee63 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java @@ -0,0 +1,251 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; + + +public class SWStatement implements java.sql.Statement { + private Connection realConnection; + private java.sql.Statement realStatement; + private ConnectionInfo connectInfo; + + SWStatement(Connection realConnection, java.sql.Statement realStatement, ConnectionInfo connectInfo) { + this.realConnection = realConnection; + this.realStatement = realStatement; + this.connectInfo = connectInfo; + } + + public T unwrap(Class iface) throws SQLException { + return realStatement.unwrap(iface); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + return realStatement.isWrapperFor(iface); + } + + public ResultSet executeQuery(String sql) throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeQuery", sql, new StatementTracing.Executable() { + public ResultSet exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeQuery(sql); + } + }); + } + + public int executeUpdate(String sql) throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new StatementTracing.Executable() { + public Integer exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql); + } + }); + } + + public void close() throws SQLException { + realStatement.close(); + } + + public int getMaxFieldSize() throws SQLException { + return realStatement.getMaxFieldSize(); + } + + public void setMaxFieldSize(int max) throws SQLException { + realStatement.setMaxFieldSize(max); + } + + public int getMaxRows() throws SQLException { + return realStatement.getMaxRows(); + } + + public void setMaxRows(int max) throws SQLException { + realStatement.setMaxRows(max); + } + + public void setEscapeProcessing(boolean enable) throws SQLException { + realStatement.setEscapeProcessing(enable); + } + + public int getQueryTimeout() throws SQLException { + return realStatement.getQueryTimeout(); + } + + public void setQueryTimeout(int seconds) throws SQLException { + realStatement.setQueryTimeout(seconds); + } + + public void cancel() throws SQLException { + realStatement.cancel(); + } + + public SQLWarning getWarnings() throws SQLException { + return realStatement.getWarnings(); + } + + public void clearWarnings() throws SQLException { + realStatement.clearWarnings(); + } + + public void setCursorName(String name) throws SQLException { + realStatement.setCursorName(name); + } + + public boolean execute(String sql) throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "execute", sql, new StatementTracing.Executable() { + public Boolean exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql); + } + }); + } + + public ResultSet getResultSet() throws SQLException { + return realStatement.getResultSet(); + } + + public int getUpdateCount() throws SQLException { + return realStatement.getUpdateCount(); + } + + public boolean getMoreResults() throws SQLException { + return realStatement.getMoreResults(); + } + + public void setFetchDirection(int direction) throws SQLException { + realStatement.setFetchDirection(direction); + } + + public int getFetchDirection() throws SQLException { + return realStatement.getFetchDirection(); + } + + public void setFetchSize(int rows) throws SQLException { + realStatement.setFetchSize(rows); + } + + public int getFetchSize() throws SQLException { + return realStatement.getFetchSize(); + } + + public int getResultSetConcurrency() throws SQLException { + return realStatement.getResultSetConcurrency(); + } + + public int getResultSetType() throws SQLException { + return realStatement.getResultSetType(); + } + + public void addBatch(String sql) throws SQLException { + realStatement.addBatch(sql); + } + + public void clearBatch() throws SQLException { + realStatement.clearBatch(); + } + + public int[] executeBatch() throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeBatch", "", new StatementTracing.Executable() { + public int[] exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeBatch(); + } + }); + } + + public Connection getConnection() throws SQLException { + return this.realConnection; + } + + public boolean getMoreResults(int current) throws SQLException { + return realStatement.getMoreResults(current); + } + + public ResultSet getGeneratedKeys() throws SQLException { + return realStatement.getGeneratedKeys(); + } + + public int executeUpdate(String sql, final int autoGeneratedKeys) + throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new StatementTracing.Executable() { + public Integer exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, autoGeneratedKeys); + } + }); + } + + public int executeUpdate(String sql, final int[] columnIndexes) + throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new StatementTracing.Executable() { + public Integer exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnIndexes); + } + }); + } + + public int executeUpdate(String sql, final String[] columnNames) + throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "executeUpdate", sql, new StatementTracing.Executable() { + public Integer exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.executeUpdate(sql, columnNames); + } + }); + } + + public boolean execute(String sql, final int autoGeneratedKeys) + throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "execute", sql, new StatementTracing.Executable() { + public Boolean exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, autoGeneratedKeys); + } + }); + } + + public boolean execute(String sql, final int[] columnIndexes) throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "execute", sql, new StatementTracing.Executable() { + public Boolean exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnIndexes); + } + }); + } + + public boolean execute(String sql, final String[] columnNames) + throws SQLException { + return StatementTracing.execute(realStatement, connectInfo, "execute", sql, new StatementTracing.Executable() { + public Boolean exe(java.sql.Statement realStatement, String sql) + throws SQLException { + return realStatement.execute(sql, columnNames); + } + }); + } + + public int getResultSetHoldability() throws SQLException { + return realStatement.getResultSetHoldability(); + } + + public boolean isClosed() throws SQLException { + return realStatement.isClosed(); + } + + public void setPoolable(boolean poolable) throws SQLException { + realStatement.setPoolable(poolable); + } + + public boolean isPoolable() throws SQLException { + return realStatement.isPoolable(); + } + + public void closeOnCompletion() throws SQLException { + realStatement.closeOnCompletion(); + } + + public boolean isCloseOnCompletion() throws SQLException { + return realStatement.isCloseOnCompletion(); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java new file mode 100644 index 0000000000000000000000000000000000000000..4e4e4f3163ec43f8e54ec4c253587487699e9620 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java @@ -0,0 +1,50 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link StatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/Statement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class StatementTracing { + public static R execute(java.sql.Statement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/Statement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.Statement realStatement, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractConnectionURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractConnectionURLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..1ed4fa846ea723a1dfb57b50c3ad98f9646f5a06 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractConnectionURLParser.java @@ -0,0 +1,65 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +/** + * {@link AbstractConnectionURLParser} is abstract class that the class that parse jdbc url. + * + * @author zhangxin + */ +public abstract class AbstractConnectionURLParser implements ConnectionURLParser { + + /** + * Connection url + */ + protected String url; + + public AbstractConnectionURLParser(String url) { + this.url = url; + } + + /** + * Fetch the index range that database host and port from connection url. + * + * @return index range that database hosts. + */ + protected abstract int[] fetchDatabaseHostsIndexRange(); + + /** + * Fetch the index range that database name from connection url. + * + * @return index range that database name. + */ + protected abstract int[] fetchDatabaseNameIndexRange(); + + /** + * Fetch database host(s) from connection url. + * + * @return database host(s). + */ + protected String fetchDatabaseHostsFromURL() { + int[] indexRange = fetchDatabaseHostsIndexRange(); + return url.substring(indexRange[0], indexRange[1]); + } + + /** + * Fetch database name from connection url. + * + * @return database name. + */ + protected String fetchDatabaseNameFromURL() { + int[] indexRange = fetchDatabaseNameIndexRange(); + return url.substring(indexRange[0], indexRange[1]); + } + + /** + * Fetch database name from connection url. + * + * @return database name. + */ + protected String fetchDatabaseNameFromURL(int[] indexRange) { + return url.substring(indexRange[0], indexRange[1]); + } + + public String getConnectionURL() { + return this.url; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..0576492eda1ad378d59fc31f7117e0a386cf5ba9 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java @@ -0,0 +1,14 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + + +public interface ConnectionURLParser { + /** + * The class that extend {@link ConnectionURLParser} spilt + * the database name , the database host(s) from connection url. + * + * @return connection info. + */ + ConnectionInfo parse(); +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..81b992501dd474ec60e3e91a1a83c7068ca637e5 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java @@ -0,0 +1,118 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link H2URLParser} presents that skywalking how to parse the connection url of H2 database. + * {@link ConnectionInfo#host} will return localhost and {@link ConnectionInfo#port} will return + * -1 if H2 running with memory mode or file mode, or it will return the host and the port. + * + * {@link H2URLParser} check the connection url if contains "file" or "mem". if yes. the database + * name substring the connection url from the index after "file" index or the "mem" index to the + * index of first charset ";". + * + * The {@link ConnectionInfo#host} be set the string between charset "//" and the first charset "/" after + * the charset "//", and {@link ConnectionInfo#databaseName} be set the string between the last index of "/" and + * the first charset ";". + * + * @author zhangxin + */ +public class H2URLParser extends AbstractConnectionURLParser { + + private static final String LOCALHOST = "localhost"; + /** + * Default port that H2 running with mix mode. + */ + private static final int DEFAULT_PORT = 8084; + /** + * Flag that H2 running with file mode. + */ + private static final String FILE_MODE_FLAG = "file"; + /** + * Flag that H2 running with memory mode. + */ + private static final String MEMORY_MODE_FLAG = "mem"; + /** + * H2 data type. + */ + private static final String H2_DB_TYPE = "H2"; + + public H2URLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new int[]{hostLabelStartIndex + 2, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf(";"); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new int[]{databaseStartTag + 1, databaseEndTag}; + } + + @Override + public ConnectionInfo parse() { + int[] databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2FileMode(); + if (databaseNameRangeIndex != null) { + return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex)); + } + + databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2MemMode(); + if (databaseNameRangeIndex != null) { + return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex)); + } + + String[] hostAndPort = fetchDatabaseHostsFromURL().split(":"); + if (hostAndPort.length == 1) { + return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + } + } + + /** + * Fetch range index that the database name from connection url if H2 database running with file mode. + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexFromURLForH2FileMode() { + int fileLabelIndex = url.indexOf(FILE_MODE_FLAG); + int parameterLabelIndex = url.indexOf(";", fileLabelIndex); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + return new int[]{fileLabelIndex + FILE_MODE_FLAG.length() + 1, parameterLabelIndex}; + } else { + return null; + } + } + + /** + * Fetch range index that the database name from connection url if H2 database running with memory mode. + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexFromURLForH2MemMode() { + int fileLabelIndex = url.indexOf(MEMORY_MODE_FLAG); + int parameterLabelIndex = url.indexOf(";", fileLabelIndex); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + return new int[]{fileLabelIndex + MEMORY_MODE_FLAG.length() + 1, parameterLabelIndex}; + } else { + return null; + } + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..604d115ef65454e2aeedcbec62a794c7e31920ef --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java @@ -0,0 +1,72 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link MysqlURLParser} presents that how to parse mysql connection url. + * + * The {@link ConnectionInfo#host} be set the string between charset "//" and the first + * charset "/" after the charset "//", and {@link ConnectionInfo#databaseName} be set the + * string between the last index of "/" and the first charset "?". but one more thing, the + * {@link ConnectionInfo#hosts} be set if the host container multiple host. + * + * @author zhangxin + */ +public class MysqlURLParser extends AbstractConnectionURLParser { + + /** + * Mysql default port. + */ + private static final int DEFAULT_PORT = 3306; + /** + * Mysql db type. + */ + private static final String MYSQL_DB_TYPE = "Mysql"; + + public MysqlURLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new int[]{hostLabelStartIndex + 2, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new int[]{databaseStartTag + 1, databaseEndTag}; + } + + @Override + public ConnectionInfo parse() { + int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(hostRangeIndex[0], hostRangeIndex[1]); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host + ":" + DEFAULT_PORT + ","); + } else { + sb.append(host + ","); + } + } + return new ConnectionInfo(MYSQL_DB_TYPE, sb.toString(), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo(MYSQL_DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo(MYSQL_DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } + } + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..eecd7c2422740566935bbd6edda19d2252644e6a --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java @@ -0,0 +1,62 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link OracleURLParser} presents that how to parse oracle connection url. + * + * The {@link ConnectionInfo#host} be set the string between charset "@" and the last + * charset ":" after the charset "@", and {@link ConnectionInfo#databaseName} be set the + * string that after the last index of ":". + * + * Note: {@link OracleURLParser} can parse the commons connection url. the commons + * connection url is of the form: jdbc:oracle::@,the other + * the form of connection url cannot be parsed success. + * + * @author zhangxin + */ +public class OracleURLParser extends AbstractConnectionURLParser { + + /** + * Oracle db type. + */ + private static final String ORACLE_DB_TYPE = "Oracle"; + /** + * Oracle default port + */ + private static final int DEFAULT_PORT = 1521; + + public OracleURLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("@"); + int hostLabelEndIndex = url.lastIndexOf(":"); + return new int[]{hostLabelStartIndex + 1, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + return new int[0]; + } + + @Override + public ConnectionInfo parse() { + int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + String host = fetchDatabaseHostsFromURL(); + String[] hostSegment = splitDatabaseAddress(host); + String databaseName = url.substring(hostRangeIndex[1] + 1); + if (hostSegment.length == 1) { + return new ConnectionInfo(ORACLE_DB_TYPE, host, DEFAULT_PORT, databaseName); + } else { + return new ConnectionInfo(ORACLE_DB_TYPE, hostSegment[0], Integer.valueOf(hostSegment[1]), databaseName); + } + } + + private String[] splitDatabaseAddress(String address) { + String[] hostSegment = address.split(":"); + return hostSegment; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java new file mode 100644 index 0000000000000000000000000000000000000000..c6912a8f64d86d0a03cf115634a2e16d1a6c2233 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java @@ -0,0 +1,23 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link URLParser#parser(String)} support parse the connection url, such as Mysql, Oracle, H2 Database. + * But there are some url cannot be parsed, such as Oracle connection url with multiple host. + * + * @author zhangxin + */ +public class URLParser { + public static ConnectionInfo parser(String url) { + ConnectionURLParser parser = null; + if (url.startsWith("jdbc:mysql")) { + parser = new MysqlURLParser(url); + } else if (url.startsWith("jdbc:oracle")) { + parser = new OracleURLParser(url); + } else if (url.startsWith("jdbc:h2")) { + parser = new H2URLParser(url); + } + return parser.parse(); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..e9d9e4a9b52a82c3c3e3680d2df893b6ef13ebf9 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java @@ -0,0 +1,53 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.jdbc.SWConnection; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.Properties; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * JDBC plugin using {@link JDBCDriverInterceptor} to intercept all the class that extend {@link java.sql.Driver#connect(String, Properties)}, + * and change the return object to {@link com.a.eye.skywalking.plugin.jdbc.SWConnection}, All the method of {@link com.a.eye.skywalking.plugin.jdbc.SWConnection} + * is delete to the real JDBC Driver Connection object. + * It will return {@link com.a.eye.skywalking.plugin.jdbc.SWStatement} when {@link java.sql.Driver} to create {@link java.sql.Statement}, return + * {@link com.a.eye.skywalking.plugin.jdbc.SWPreparedStatement} when {@link java.sql.Driver} to create {@link java.sql.PreparedStatement} and return + * {@link com.a.eye.skywalking.plugin.jdbc.SWCallableStatement} when {@link java.sql.Driver} to create {@link java.sql.CallableStatement}. + * of course, {@link com.a.eye.skywalking.plugin.jdbc.SWStatement}, {@link com.a.eye.skywalking.plugin.jdbc.SWPreparedStatement} and + * {@link com.a.eye.skywalking.plugin.jdbc.SWCallableStatement} are same as {@link SWConnection}. + * + * @author zhangxin + */ +public abstract class AbstractDatabaseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * Intercept class + */ + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jdbc.define.JDBCDriverInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("connect"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..6b44b91fd7705feddd159b8e7d7ed2a50cc515f8 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java @@ -0,0 +1,19 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link H2Instrumentation} presents that skywalking will intercept {@link org.h2.Driver}. + * + * @author zhangxin + */ +public class H2Instrumentation extends AbstractDatabaseInstrumentation { + + /** + * Class of intercept H2 driver + */ + private static final String CLASS_OF_INTERCEPT_H2_DRIVER = "org.h2.Driver"; + + @Override + protected String enhanceClassName() { + return CLASS_OF_INTERCEPT_H2_DRIVER; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..f5439c7b409c5ee46b0b15f0868f52a9995469d8 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java @@ -0,0 +1,38 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.plugin.jdbc.SWConnection; + +import java.sql.Connection; +import java.util.Properties; + +/** + * {@link JDBCDriverInterceptor} will return {@link SWConnection} when {@link java.sql.Driver#connect(String, Properties)}, + * instead of the instance that extend {@link Connection}. + * + * @author zhangxin + */ +public class JDBCDriverInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + // do nothing + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + return new SWConnection((String) interceptorContext.allArguments()[0], + (Properties) interceptorContext.allArguments()[1], (Connection) ret); + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + // do nothing. + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..56808851053044d075e00daeae7a5f92142fcaf8 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java @@ -0,0 +1,13 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link MysqlInstrumentation} presents that skywalking will intercept {@link com.mysql.jdbc.Driver}. + * + * @author zhangxin + */ +public class MysqlInstrumentation extends AbstractDatabaseInstrumentation { + @Override + protected String enhanceClassName() { + return "com.mysql.jdbc.Driver"; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..221f114ec226e7b42512cad622f8f4962ae9e391 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java @@ -0,0 +1,14 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link OracleInstrumentation} presents that skywalking will intercept the class oracle.jdbc.OracleDriver + * . + * + * @author zhangxin + */ +public class OracleInstrumentation extends AbstractDatabaseInstrumentation { + @Override + protected String enhanceClassName() { + return "oracle.jdbc.OracleDriver"; + } +}