Fix compile issue.
This commit is contained in:
parent
b543fac778
commit
9654b01c30
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<br/>
|
||||
* public final HttpResponse execute(HttpHost target, HttpRequest request,
|
||||
* HttpContext context)<br/>
|
||||
*/
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("doExecute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return getInstanceMethodsInterceptor();
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -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.<br/>
|
||||
* usually use in version 4.0-4.2<br/>
|
||||
* 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<MethodDescription> getMethodsMatcher() {
|
||||
return named("execute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return getInstanceMethodsInterceptor();
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MethodDescription> getMethodsMatcher() {
|
||||
return named("doExecute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return getInstanceMethodsInterceptor();
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MethodDescription> getMethodsMatcher() {
|
||||
return named("doExecute");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return getInstanceMethodsInterceptor();
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -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> R execute(java.sql.CallableStatement realStatement,
|
||||
ConnectionInfo connectInfo, String method, String sql, Executable<R> 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> {
|
||||
R exe(java.sql.CallableStatement realConnection, String sql)
|
||||
throws SQLException;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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> R execute(java.sql.Connection realConnection,
|
||||
ConnectionInfo connectInfo, String method, String sql, Executable<R> 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> {
|
||||
R exe(java.sql.Connection realConnection, String sql)
|
||||
throws SQLException;
|
||||
}
|
||||
}
|
||||
|
|
@ -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> R execute(java.sql.PreparedStatement realStatement,
|
||||
ConnectionInfo connectInfo, String method, String sql, Executable<R> 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> {
|
||||
R exe(java.sql.PreparedStatement realConnection, String sql)
|
||||
throws SQLException;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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> T unwrap(Class<T> iface) throws SQLException {
|
||||
return realConnection.unwrap(iface);
|
||||
}
|
||||
|
||||
public boolean isWrapperFor(Class<?> iface) throws SQLException {
|
||||
return realConnection.isWrapperFor(iface);
|
||||
}
|
||||
|
||||
public Statement createStatement() throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(),
|
||||
this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return new SWPreparedStatement(this,
|
||||
realConnection.prepareStatement(sql), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql),
|
||||
this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public String nativeSQL(String sql) throws SQLException {
|
||||
return 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<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.commit();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void rollback() throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo, "rollback", "",
|
||||
new ConnectionTracing.Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.rollback();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo, "close", "",
|
||||
new ConnectionTracing.Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.close();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
return realConnection.isClosed();
|
||||
}
|
||||
|
||||
public DatabaseMetaData getMetaData() throws SQLException {
|
||||
return realConnection.getMetaData();
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) throws SQLException {
|
||||
realConnection.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
return realConnection.isReadOnly();
|
||||
}
|
||||
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
realConnection.setCatalog(catalog);
|
||||
}
|
||||
|
||||
public String getCatalog() throws SQLException {
|
||||
return realConnection.getCatalog();
|
||||
}
|
||||
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
realConnection.setTransactionIsolation(level);
|
||||
}
|
||||
|
||||
public int getTransactionIsolation() throws SQLException {
|
||||
return realConnection.getTransactionIsolation();
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return realConnection.getWarnings();
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {
|
||||
realConnection.clearWarnings();
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(
|
||||
resultSetType, resultSetConcurrency), this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType,
|
||||
int resultSetConcurrency) throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, resultSetType, resultSetConcurrency), this.connectInfo,
|
||||
sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType,
|
||||
int resultSetConcurrency) throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql,
|
||||
resultSetType, resultSetConcurrency), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public Map<String, Class<?>> getTypeMap() throws SQLException {
|
||||
return realConnection.getTypeMap();
|
||||
}
|
||||
|
||||
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
|
||||
realConnection.setTypeMap(map);
|
||||
}
|
||||
|
||||
public void setHoldability(int holdability) throws SQLException {
|
||||
realConnection.setHoldability(holdability);
|
||||
}
|
||||
|
||||
public int getHoldability() throws SQLException {
|
||||
return realConnection.getHoldability();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
return realConnection.setSavepoint();
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint(String name) throws SQLException {
|
||||
return realConnection.setSavepoint(name);
|
||||
}
|
||||
|
||||
public void rollback(final Savepoint savepoint) throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo,
|
||||
"rollback to savepoint", "", new ConnectionTracing.Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.rollback(savepoint);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
|
||||
ConnectionTracing.execute(realConnection, connectInfo,
|
||||
"releaseSavepoint savepoint", "", new ConnectionTracing.Executable<String>() {
|
||||
public String exe(java.sql.Connection realConnection,
|
||||
String sql) throws SQLException {
|
||||
realConnection.releaseSavepoint(savepoint);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Statement createStatement(int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWStatement(this, realConnection.createStatement(
|
||||
resultSetType, resultSetConcurrency, resultSetHoldability),
|
||||
this.connectInfo);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this,
|
||||
realConnection.prepareStatement(sql, resultSetType,
|
||||
resultSetConcurrency, resultSetHoldability),
|
||||
this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int resultSetType,
|
||||
int resultSetConcurrency, int resultSetHoldability)
|
||||
throws SQLException {
|
||||
return new SWCallableStatement(this, realConnection.prepareCall(sql,
|
||||
resultSetType, resultSetConcurrency, resultSetHoldability), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, autoGeneratedKeys), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, columnIndexes), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, String[] columnNames)
|
||||
throws SQLException {
|
||||
return new SWPreparedStatement(this, realConnection.prepareStatement(
|
||||
sql, columnNames), this.connectInfo, sql);
|
||||
}
|
||||
|
||||
public Clob createClob() throws SQLException {
|
||||
return realConnection.createClob();
|
||||
}
|
||||
|
||||
public Blob createBlob() throws SQLException {
|
||||
return realConnection.createBlob();
|
||||
}
|
||||
|
||||
public NClob createNClob() throws SQLException {
|
||||
return realConnection.createNClob();
|
||||
}
|
||||
|
||||
public SQLXML createSQLXML() throws SQLException {
|
||||
return realConnection.createSQLXML();
|
||||
}
|
||||
|
||||
public boolean isValid(int timeout) throws SQLException {
|
||||
return realConnection.isValid(timeout);
|
||||
}
|
||||
|
||||
public void setClientInfo(String name, String value)
|
||||
throws SQLClientInfoException {
|
||||
realConnection.setClientInfo(name, value);
|
||||
}
|
||||
|
||||
public void setClientInfo(Properties properties)
|
||||
throws SQLClientInfoException {
|
||||
realConnection.setClientInfo(properties);
|
||||
}
|
||||
|
||||
public String getClientInfo(String name) throws SQLException {
|
||||
return realConnection.getClientInfo(name);
|
||||
}
|
||||
|
||||
public Properties getClientInfo() throws SQLException {
|
||||
return realConnection.getClientInfo();
|
||||
}
|
||||
|
||||
public Array createArrayOf(String typeName, Object[] elements)
|
||||
throws SQLException {
|
||||
return realConnection.createArrayOf(typeName, elements);
|
||||
}
|
||||
|
||||
public Struct createStruct(String typeName, Object[] attributes)
|
||||
throws SQLException {
|
||||
return realConnection.createStruct(typeName, attributes);
|
||||
}
|
||||
|
||||
public void setSchema(String schema) throws SQLException {
|
||||
realConnection.setSchema(schema);
|
||||
}
|
||||
|
||||
public String getSchema() throws SQLException {
|
||||
return realConnection.getSchema();
|
||||
}
|
||||
|
||||
public void abort(Executor executor) throws SQLException {
|
||||
realConnection.abort(executor);
|
||||
}
|
||||
|
||||
public void setNetworkTimeout(Executor executor, int milliseconds)
|
||||
throws SQLException {
|
||||
realConnection.setNetworkTimeout(executor, milliseconds);
|
||||
}
|
||||
|
||||
public int getNetworkTimeout() throws SQLException {
|
||||
return realConnection.getNetworkTimeout();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<ResultSet>() {
|
||||
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<Integer>() {
|
||||
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<Boolean>() {
|
||||
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<int[]>() {
|
||||
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<Integer>() {
|
||||
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<Integer>() {
|
||||
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<Integer>() {
|
||||
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<Boolean>() {
|
||||
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<Boolean>() {
|
||||
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<Boolean>() {
|
||||
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> T unwrap(Class<T> 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<ResultSet>() {
|
||||
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<Integer>() {
|
||||
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<Boolean>() {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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> T unwrap(Class<T> 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<ResultSet>() {
|
||||
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<Integer>() {
|
||||
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<Boolean>() {
|
||||
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<int[]>() {
|
||||
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<Integer>() {
|
||||
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<Integer>() {
|
||||
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<Integer>() {
|
||||
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<Boolean>() {
|
||||
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<Boolean>() {
|
||||
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<Boolean>() {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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> R execute(java.sql.Statement realStatement,
|
||||
ConnectionInfo connectInfo, String method, String sql, Executable<R> 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> {
|
||||
R exe(java.sql.Statement realStatement, String sql)
|
||||
throws SQLException;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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: <code>jdbc:oracle:<drivertype>:@<database></code>,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MethodDescription> getMethodsMatcher() {
|
||||
return named("connect");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return INTERCEPT_CLASS;
|
||||
}
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.a.eye.skywalking.plugin.jdbc.define;
|
||||
|
||||
/**
|
||||
* {@link OracleInstrumentation} presents that skywalking will intercept the class <code>oracle.jdbc.OracleDriver
|
||||
* </code>.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class OracleInstrumentation extends AbstractDatabaseInstrumentation {
|
||||
@Override
|
||||
protected String enhanceClassName() {
|
||||
return "oracle.jdbc.OracleDriver";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue