skywalking使用mysql_聊聊skywalking的mysql-plugin

本文主要研究一下skywalking的mysql-plugin

skywalking-plugin.def

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/resources/skywalking-plugin.def

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.ConnectionImplCreateInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.ConnectionInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.CallableInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.StatementInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementSetterInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementNullSetterInstrumentation

mysql-8.x=org.apache.skywalking.apm.plugin.jdbc.mysql.v8.define.PreparedStatementIgnoredSetterInstrumentation

skywalking的mysql-plugin提供了ConnectionImplCreateInstrumentation、ConnectionInstrumentation、CallableInstrumentation、PreparedStatementInstrumentation、StatementInstrumentation、PreparedStatementSetterInstrumentation、PreparedStatementNullSetterInstrumentation、PreparedStatementIgnoredSetterInstrumentation这几个增强

AbstractMysqlInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/AbstractMysqlInstrumentation.java

public abstract class AbstractMysqlInstrumentation extends ClassEnhancePluginDefine {

@Override

public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {

return null;

}

@Override

public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {

return null;

}

@Override

public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return null;

}

@Override

protected String[] witnessClasses() {

return new String[]{Constants.WITNESS_MYSQL_8X_CLASS};

}

}

AbstractMysqlInstrumentation继承了ClassEnhancePluginDefine,其witnessClasses返回的是com.mysql.cj.interceptors.QueryInterceptor

ConnectionImplCreateInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/ConnectionImplCreateInstrumentation.java

public class ConnectionImplCreateInstrumentation extends AbstractMysqlInstrumentation {

private static final String JDBC_ENHANCE_CLASS = "com.mysql.cj.jdbc.ConnectionImpl";

private static final String CONNECT_METHOD = "getInstance";

@Override

public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {

return new StaticMethodsInterceptPoint[] {

new StaticMethodsInterceptPoint() {

@Override

public ElementMatcher getMethodsMatcher() {

return named(CONNECT_METHOD);

}

@Override

public String getMethodsInterceptor() {

return "org.apache.skywalking.apm.plugin.jdbc.mysql.v8.ConnectionCreateInterceptor";

}

@Override

public boolean isOverrideArgs() {

return false;

}

}

};

}

@Override

protected ClassMatch enhanceClass() {

return byName(JDBC_ENHANCE_CLASS);

}

}

ConnectionImplCreateInstrumentation继承了AbstractMysqlInstrumentation;它使用org.apache.skywalking.apm.plugin.jdbc.mysql.v8.ConnectionCreateInterceptor增强了com.mysql.cj.jdbc.ConnectionImpl的getInstance方法

ConnectionCreateInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/ConnectionCreateInterceptor.java

public class ConnectionCreateInterceptor implements StaticMethodsAroundInterceptor {

@Override

public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes, MethodInterceptResult result) {

}

@Override

public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes, Object ret) {

if (ret instanceof EnhancedInstance) {

final HostInfo hostInfo = (HostInfo) allArguments[0];

ConnectionInfo connectionInfo = URLParser.parser(hostInfo.getDatabaseUrl());

((EnhancedInstance) ret).setSkyWalkingDynamicField(connectionInfo);

}

return ret;

}

@Override

public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes, Throwable t) {

}

}

ConnectionCreateInterceptor实现了StaticMethodsAroundInterceptor接口,其afterMethod方法提取hostInfo解析为connectionInfo然后设置给ret的skyWalkingDynamicField

ConnectionInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/ConnectionInstrumentation.java

public class ConnectionInstrumentation extends AbstractMysqlInstrumentation {

@Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {

return new ConstructorInterceptPoint[0];

}

@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_STATEMENT_METHOD_NAME);

}

@Override public String getMethodsInterceptor() {

return org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.CREATE_PREPARED_STATEMENT_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

},

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_CALL_METHOD_NAME);

}

@Override public String getMethodsInterceptor() {

return org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.CREATE_CALLABLE_STATEMENT_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

},

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.CREATE_STATEMENT_METHOD_NAME).and(takesArguments(2));

}

@Override public String getMethodsInterceptor() {

return org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.CREATE_STATEMENT_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

},

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.COMMIT_METHOD_NAME).or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.ROLLBACK_METHOD_NAME)).or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.CLOSE_METHOD_NAME)).or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.RELEASE_SAVE_POINT_METHOD_NAME));

}

@Override public String getMethodsInterceptor() {

return org.apache.skywalking.apm.plugin.jdbc.define.Constants.SERVICE_METHOD_INTERCEPT_CLASS;

}

@Override public boolean isOverrideArgs() {

return false;

}

},

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named("setCatalog");

}

@Override public String getMethodsInterceptor() {

return org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.SET_CATALOG_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

}

};

}

@Override protected ClassMatch enhanceClass() {

return byName("com.mysql.cj.jdbc.ConnectionImpl");

}

}

ConnectionInstrumentation继承了AbstractMysqlInstrumentation,它增强的是com.mysql.cj.jdbc.ConnectionImpl类;它使用org.apache.skywalking.apm.plugin.jdbc.mysql.CreatePreparedStatementInterceptor增强其prepareStatement方法;它使用org.apache.skywalking.apm.plugin.jdbc.mysql.CreateCallableStatementInterceptor增强其prepareCall方法;它使用org.apache.skywalking.apm.plugin.jdbc.mysql.CreateStatementInterceptor增强其createStatement方法;它使用org.apache.skywalking.apm.plugin.jdbc.ConnectionServiceMethodInterceptor增强其commit、rollback、close、releaseSavepoint方法;它使用org.apache.skywalking.apm.plugin.jdbc.mysql.SetCatalogInterceptor增强其setCatalog方法

CreatePreparedStatementInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptor.java

public class CreatePreparedStatementInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

}

@Override

public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

Object ret) throws Throwable {

if (ret instanceof EnhancedInstance) {

((EnhancedInstance)ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo)objInst.getSkyWalkingDynamicField(), (String)allArguments[0], "PreparedStatement"));

}

return ret;

}

@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

}

}

CreatePreparedStatementInterceptor实现了InstanceMethodsAroundInterceptor接口,其afterMethod方法会将StatementEnhanceInfos设置给ret的skyWalkingDynamicField

CreateCallableStatementInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptor.java

public class CreateCallableStatementInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

}

@Override

public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

Object ret) throws Throwable {

if (ret instanceof EnhancedInstance) {

((EnhancedInstance)ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo)objInst.getSkyWalkingDynamicField(), (String)allArguments[0], "CallableStatement"));

}

return ret;

}

@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

}

}

CreateCallableStatementInterceptor实现了InstanceMethodsAroundInterceptor接口,其afterMethod方法将StatementEnhanceInfos设置给ret的skyWalkingDynamicField

CreateStatementInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptor.java

public class CreateStatementInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

}

@Override

public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

Object ret) throws Throwable {

if (ret instanceof EnhancedInstance) {

((EnhancedInstance)ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo)objInst.getSkyWalkingDynamicField(), "", "Statement"));

}

return ret;

}

@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

}

}

CreateStatementInterceptor实现了InstanceMethodsAroundInterceptor接口,其afterMethod方法将StatementEnhanceInfos设置给ret的skyWalkingDynamicField

ConnectionServiceMethodInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/ConnectionServiceMethodInterceptor.java

public class ConnectionServiceMethodInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

ConnectionInfo connectInfo = (ConnectionInfo)objInst.getSkyWalkingDynamicField();

if (connectInfo != null) {

AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method.getName(), connectInfo.getDatabasePeer());

Tags.DB_TYPE.set(span, "sql");

Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());

Tags.DB_STATEMENT.set(span, "");

span.setComponent(connectInfo.getComponent());

SpanLayer.asDB(span);

}

}

@Override

public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

Object ret) throws Throwable {

ConnectionInfo connectInfo = (ConnectionInfo)objInst.getSkyWalkingDynamicField();

if (connectInfo != null) {

ContextManager.stopSpan();

}

return ret;

}

@Override public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

ContextManager.activeSpan().errorOccurred().log(t);

}

}

ConnectionServiceMethodInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法设置DB_TYPE、DB_INSTANCE、DB_STATEMENT;其afterMethod方法在connectInfo不为null时执行ContextManager.stopSpan();其handleMethodException方法执行ContextManager.activeSpan().errorOccurred().log(t)

SetCatalogInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/SetCatalogInterceptor.java

public class SetCatalogInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

Object dynamicField = objInst.getSkyWalkingDynamicField();

if (dynamicField instanceof ConnectionInfo) {

((ConnectionInfo)dynamicField).setDatabaseName(String.valueOf(allArguments[0]));

}

}

@Override

public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,

Object ret) throws Throwable {

return ret;

}

@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

}

}

SetCatalogInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法给类型为ConnectionInfo的dynamicField设置databaseName

CallableInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/CallableInstrumentation.java

public class CallableInstrumentation extends AbstractMysqlInstrumentation {

private static final String ENHANCE_CLASS = "com.mysql.cj.jdbc.CallableStatement";

private static final String SERVICE_METHOD_INTERCEPTOR = org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR;

@Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {

return new ConstructorInterceptPoint[0];

}

@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named("execute")

.or(named("executeQuery"))

.or(named("executeUpdate"));

}

@Override public String getMethodsInterceptor() {

return SERVICE_METHOD_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

}

};

}

@Override protected ClassMatch enhanceClass() {

return byName(ENHANCE_CLASS);

}

}

CallableInstrumentation继承了AbstractMysqlInstrumentation,它使用org.apache.skywalking.apm.plugin.jdbc.mysql.PreparedStatementExecuteMethodsInterceptor增强了com.mysql.cj.jdbc.CallableStatement的execute、executeQuery、executeUpdate方法

PreparedStatementExecuteMethodsInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java

public class PreparedStatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

ConnectionInfo connectInfo = cacheObject.getConnectionInfo();

/**

* For avoid NPE. In this particular case, Execute sql inside the {@link com.mysql.jdbc.ConnectionImpl} constructor,

* before the interceptor sets the connectionInfo.

*

* @see JDBCDriverInterceptor#afterMethod(EnhancedInstance, Method, Object[], Class[], Object)

*/

if (connectInfo != null) {

AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject.getStatementName()), connectInfo.getDatabasePeer());

Tags.DB_TYPE.set(span, "sql");

Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());

Tags.DB_STATEMENT.set(span, cacheObject.getSql());

span.setComponent(connectInfo.getComponent());

if (Config.Plugin.MySQL.TRACE_SQL_PARAMETERS) {

final Object[] parameters = cacheObject.getParameters();

if (parameters != null && parameters.length > 0) {

int maxIndex = cacheObject.getMaxIndex();

String parameterString = buildParameterString(parameters, maxIndex);

int sqlParametersMaxLength = Config.Plugin.MySQL.SQL_PARAMETERS_MAX_LENGTH;

if (sqlParametersMaxLength > 0 && parameterString.length() > sqlParametersMaxLength) {

parameterString = parameterString.substring(0, sqlParametersMaxLength) + "...";

}

SQL_PARAMETERS.set(span, parameterString);

}

}

SpanLayer.asDB(span);

}

}

@Override

public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

Object ret) throws Throwable {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

if (cacheObject.getConnectionInfo() != null) {

ContextManager.stopSpan();

}

return ret;

}

@Override public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

if (cacheObject.getConnectionInfo() != null) {

ContextManager.activeSpan().errorOccurred().log(t);

}

}

private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {

return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;

}

private String buildParameterString(Object[] parameters, int maxIndex) {

String parameterString = "[";

boolean first = true;

for (int i = 0; i < maxIndex; i++) {

Object parameter = parameters[i];

if (!first) {

parameterString += ",";

}

parameterString += parameter;

first = false;

}

parameterString += "]";

return parameterString;

}

}

PreparedStatementExecuteMethodsInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法设置DB_TYPE、DB_INSTANCE、DB_STATEMENT、SQL_PARAMETERS(Config.Plugin.MySQL.TRACE_SQL_PARAMETERS为true的话);其afterMethod方法在cacheObject.getConnectionInfo()不为null时执行ContextManager.stopSpan();其handleMethodException方法在cacheObject.getConnectionInfo()不为null时执行ContextManager.activeSpan().errorOccurred().log(t)

PreparedStatementInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/PreparedStatementInstrumentation.java

public class PreparedStatementInstrumentation extends AbstractMysqlInstrumentation {

private static final String PREPARED_STATEMENT_CLASS_NAME = "com.mysql.cj.jdbc.ClientPreparedStatement";

private static final String PREPARED_STATEMENT_SERVER_SIDE_CLASS_NAME = "com.mysql.cj.jdbc.ServerPreparedStatement";

private static final String SERVICE_METHOD_INTERCEPTOR = Constants.PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR;

@Override public final ConstructorInterceptPoint[] getConstructorsInterceptPoints() {

return new ConstructorInterceptPoint[0];

}

@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named("execute")

.or(named("executeQuery"))

.or(named("executeUpdate"))

.or(named("executeLargeUpdate"));

}

@Override public String getMethodsInterceptor() {

return SERVICE_METHOD_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

}

};

}

@Override protected ClassMatch enhanceClass() {

return byMultiClassMatch(PREPARED_STATEMENT_CLASS_NAME, PREPARED_STATEMENT_SERVER_SIDE_CLASS_NAME);

}

}

PreparedStatementInstrumentation继承了AbstractMysqlInstrumentation,它使用org.apache.skywalking.apm.plugin.jdbc.mysql.PreparedStatementExecuteMethodsInterceptor增强了com.mysql.cj.jdbc.ClientPreparedStatement的execute、executeQuery、executeUpdate、executeLargeUpdate方法

StatementInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/StatementInstrumentation.java

public class StatementInstrumentation extends AbstractMysqlInstrumentation {

private static final String SERVICE_METHOD_INTERCEPTOR = org.apache.skywalking.apm.plugin.jdbc.mysql.Constants.STATEMENT_EXECUTE_METHODS_INTERCEPTOR;

public static final String MYSQL8_STATEMENT_CLASS_NAME = "com.mysql.cj.jdbc.StatementImpl";

@Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {

return new ConstructorInterceptPoint[0];

}

@Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new InstanceMethodsInterceptPoint() {

@Override public ElementMatcher getMethodsMatcher() {

return named("execute")

.or(named("executeQuery"))

.or(named("executeUpdate"))

.or(named("executeLargeUpdate"))

.or(named("executeBatchInternal"))

.or(named("executeUpdateInternal"))

.or(named("executeQuery"))

.or(named("executeBatch"));

}

@Override public String getMethodsInterceptor() {

return SERVICE_METHOD_INTERCEPTOR;

}

@Override public boolean isOverrideArgs() {

return false;

}

}

};

}

@Override protected ClassMatch enhanceClass() {

return byName(MYSQL8_STATEMENT_CLASS_NAME);

}

}

StatementInstrumentation继承了AbstractMysqlInstrumentation,它使用org.apache.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor增强了com.mysql.cj.jdbc.StatementImpl的execute、executeQuery、executeUpdate、executeLargeUpdate、executeBatchInternal、executeUpdateInternal、executeQuery、executeBatch方法

StatementExecuteMethodsInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java

public class StatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {

@Override

public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

MethodInterceptResult result) throws Throwable {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

ConnectionInfo connectInfo = cacheObject.getConnectionInfo();

/**

* To protected the code occur NullPointException. because mysql execute system sql when constructor method in

* {@link com.mysql.jdbc.ConnectionImpl} class executed. but the interceptor set the connection Info after

* the constructor method executed.

*

* @see JDBCDriverInterceptor#afterMethod(EnhancedInstance, Method, Object[], Class[], Object)

*/

if (connectInfo != null) {

AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject.getStatementName()), connectInfo.getDatabasePeer());

Tags.DB_TYPE.set(span, "sql");

Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());

/**

* The first argument of all intercept method in `com.mysql.jdbc.StatementImpl` class is SQL, except the

* `executeBatch` method that the jdbc plugin need to trace, because of this method argument size is zero.

*/

String sql = "";

if (allArguments.length > 0) {

sql = (String)allArguments[0];

}

Tags.DB_STATEMENT.set(span, sql);

span.setComponent(connectInfo.getComponent());

SpanLayer.asDB(span);

}

}

@Override

public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes,

Object ret) throws Throwable {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

if (cacheObject.getConnectionInfo() != null) {

ContextManager.stopSpan();

}

return ret;

}

@Override public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,

Class>[] argumentsTypes, Throwable t) {

StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField();

if (cacheObject.getConnectionInfo() != null) {

ContextManager.activeSpan().errorOccurred().log(t);

}

}

private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {

return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;

}

}

StatementExecuteMethodsInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法设置DB_TYPE、DB_INSTANCE、DB_STATEMENT;其afterMethod方法在cacheObject.getConnectionInfo()不为null时执行ContextManager.stopSpan();其handleMethodException方法在cacheObject.getConnectionInfo()不为null时执行ContextManager.activeSpan().errorOccurred().log(t)

PreparedStatementSetterInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/PreparedStatementSetterInstrumentation.java

public class PreparedStatementSetterInstrumentation extends PreparedStatementInstrumentation {

@Override

public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new PSSetterDefinitionOfJDBCInstrumentation(false)

};

}

}

PreparedStatementSetterInstrumentation继承了PreparedStatementInstrumentation,其getInstanceMethodsInterceptPoints方法返回的是PSSetterDefinitionOfJDBCInstrumentation(false)

PSSetterDefinitionOfJDBCInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/PSSetterDefinitionOfJDBCInstrumentation.java

public class PSSetterDefinitionOfJDBCInstrumentation implements InstanceMethodsInterceptPoint {

private final boolean ignorable;

public PSSetterDefinitionOfJDBCInstrumentation(boolean ignorable) {

this.ignorable = ignorable;

}

@Override

public ElementMatcher getMethodsMatcher() {

ElementMatcher.Junction matcher = none();

if (Config.Plugin.MySQL.TRACE_SQL_PARAMETERS || Config.Plugin.POSTGRESQL.TRACE_SQL_PARAMETERS) {

final Set setters = ignorable ? PS_IGNORABLE_SETTERS : PS_SETTERS;

for (String setter : setters) {

matcher = matcher.or(named(setter));

}

}

return matcher;

}

@Override

public String getMethodsInterceptor() {

return ignorable

? Constants.PREPARED_STATEMENT_IGNORABLE_SETTER_METHODS_INTERCEPTOR

: Constants.PREPARED_STATEMENT_SETTER_METHODS_INTERCEPTOR;

}

@Override

public boolean isOverrideArgs() {

return false;

}

}

PSSetterDefinitionOfJDBCInstrumentation实现了InstanceMethodsInterceptPoint接口,其getMethodsMatcher方法根据ignorable使用PS_IGNORABLE_SETTERS还是PS_SETTERS去构造matcher以及methodsInterceptor

PreparedStatementNullSetterInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/PreparedStatementNullSetterInstrumentation.java

public class PreparedStatementNullSetterInstrumentation extends PreparedStatementInstrumentation {

@Override

public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint()

};

}

}

PreparedStatementNullSetterInstrumentation继承了PreparedStatementInstrumentation,其getInstanceMethodsInterceptPoints方法返回的是JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint

JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint.java

public final class JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint implements InstanceMethodsInterceptPoint {

@Override

public ElementMatcher getMethodsMatcher() {

return named("setNull");

}

@Override

public String getMethodsInterceptor() {

return Constants.PREPARED_STATEMENT_NULL_SETTER_METHODS_INTERCEPTOR;

}

@Override

public boolean isOverrideArgs() {

return false;

}

}

JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint实现了InstanceMethodsInterceptPoint接口,它使用org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementNullSetterInterceptor增强setNull方法

PreparedStatementIgnoredSetterInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/v8/define/PreparedStatementIgnoredSetterInstrumentation.java

public class PreparedStatementIgnoredSetterInstrumentation extends PreparedStatementInstrumentation {

@Override

public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

return new InstanceMethodsInterceptPoint[] {

new PSSetterDefinitionOfJDBCInstrumentation(true)

};

}

}

PreparedStatementIgnoredSetterInstrumentation继承了PreparedStatementInstrumentation,其getInstanceMethodsInterceptPoints方法返回的是PSSetterDefinitionOfJDBCInstrumentation(true)

小结

skywalking的mysql-plugin提供了ConnectionImplCreateInstrumentation、ConnectionInstrumentation、CallableInstrumentation、PreparedStatementInstrumentation、StatementInstrumentation、PreparedStatementSetterInstrumentation、PreparedStatementNullSetterInstrumentation、PreparedStatementIgnoredSetterInstrumentation这几个增强

doc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

django使用LDAP验证

1.安装Python-LDAP&#xff08;python_ldap-2.4.25-cp27-none-win_amd64.whl&#xff09;pip install python_ldap-2.4.25-cp27-none-win_amd64.whl 2.安装django-auth-ldap&#xff08;django-auth-ldap-1.2.8.tar.gz&#xff09;&#xff08;下载&#xff1a;https://pypi.py…

风变的python课程怎么样_风的解释|风的意思|汉典“风”字的基本解释

【戌集下】【風】 風康熙筆画&#xff1a;9 部外筆画&#xff1a;0〔古文〕 &#x2064a; &#x20648;凬飌檒【唐韻】方戎切【集韻】方馮切【正韻】方中切&#xff0c; &#x20024;音楓。風以動萬物也。【莊子齊物論】大塊噫氣&#xff0c;其名爲風。【河圖】風者&#x…

收银系统 mysql数据库_某大型超市收银系统数据库成功恢复

SQL数据库表结构成功修复【用户单位】昆明某大型超市【数据恢复故障描述】由于操作系统错误&#xff0c;导致系统无法正常使用&#xff0c;技术员在维护过程中不小心把整个磁盘初始化&#xff0c;磁盘数据全部丢失&#xff0c;导致超市收银系统彻底瘫痪&#xff0c;我们在恢复的…

getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取

在上一篇文章里我们主要介绍了 tomcat io 线程中涉及到的主要核心类&#xff0c;包括 AbstractProcessorLight&#xff0c;Http11Processor&#xff0c;CoyoteAdapter&#xff0c;这里主要介绍对于请求数据的读取。对于 tomcat 请求数据的读取来说&#xff0c;可以分为请求行的…

OC之类方法

#import<Foundation/Foundation.h> /* 1、对象方法 &#xff08;1&#xff09;减号- 开头 &#xff08;2&#xff09;只能由对象来调用 &#xff08;3&#xff09;对象方法中能访问当前对象的成员变量&#xff08;实例变量&#xff09; 2、类方法 &#xff08;1&#xff…

mysql 主机不存在_MySQL 当记录不存在时插入,当记录存在时更新

MySQL 当记录不存在时插入&#xff0c;当记录存在时更新2012-1-30 17:58 Monday分类&#xff1a;MySQL评论(71) 浏览(21592)MySQL 当记录不存在时插入&#xff0c;当记录存在时更新网上基本有三种解决方法。第一种&#xff1a;示例一&#xff1a;插入多条记录假设有一个主键为 …

Autodesk招聘开发咨询顾问(北京或上海),需要内推的扔简历过来啊

Autodesk现招聘两位二次开发技术顾问&#xff0c;为正式编制。享受所有Autodesk优越的福利资源&#xff08;额外商业保险&#xff0c;公积金全部由公司支付&#xff0c;年度奖金&#xff0c;季度礼物, 节日礼物, 15天年假&#xff0c;不定期的培训...)。 Autodesk 是中国的最佳…

企业办公自动化系统_OA系统的核心功能有哪些?分析当下OA系统的缺陷以及相关解决方案...

什么是OA系统&#xff0c;OA是英语Office Automation的简称&#xff0c;字面意思是办公自动化&#xff0c;即将计算机、通信等现代化技术运用到传统办公中&#xff0c;进而形成的一种新型办公方式。它利用现代化设备和信息化技术&#xff0c;代替了办公人员传统的部分手动或重复…

python whl_python whl是什么文件

在安装whl文件之前&#xff0c;我们需要先搞清楚什么是whl文件&#xff0c;whl格式本质上是一个压缩包&#xff0c;里面包含了py文件&#xff0c;以及经过编译的pyd文件。使得可以在不具备编译环境的情况下&#xff0c;选择合适自己的python环境进行安装。在Win7下安装whl文件&…

android activity生命周期_Android岗高频面试题合一集,看你能答出几题?

前言面试季黄金时期来袭&#xff0c;想必许多朋友在这时有找工作、换工作、跳槽涨薪等想法&#xff0c;但你们都有一个相同的过程那就是面试。大家肯定想知道面试时都问哪些面试相关问题&#xff0c;所以就去网上查找题去刷题&#xff0c;为了省去大家找题的时间&#xff0c;小…

java web判断服务器是否是本机

1,如何获取浏览器的ip Java代码 /*** * 获取客户端ip地址(可以穿透代理) * param request * return */ public static String getClientIpAddr(HttpServletRequest request) { String ip request.getHeader("X-Forwarded-For"…

python变量分类_Python 入门系列 —— 5. 三大变量类型介绍

多值赋给多变量Python 允许在一行中将多个值赋给多个变量。x, y, z "Orange", "Banana", "Cherry"print(x)print(y)print(z)---- output ------PS E:\dream\markdown\python> & "C:/Program Files (x86)/Python/python.exe" e…

数据字典简单例子_Python学习100天-Day14(数据分析篇-pandas02)

Day14-读取文件接着上一天的内容&#xff0c;我在学习的过程中发现&#xff0c;DF数据还可以利用几个Series数据组成&#xff0c;具体看一个例子&#xff1a;两种形式&#xff0c;第一种是直接对Series创建DF对象&#xff0c;得出的结果。第二种是通过字典的形式创建DF对象&…

Java基础知识总结

一&#xff1a;java概述&#xff1a; 1991 年Sun公司的James Gosling&#xff08;詹姆斯&middot;高斯林&#xff09;等人开始开发名称为 Oak 的语言&#xff0c;希望用于控制嵌入在有线电视交换盒、PDA等的微处理器&#xff1b; 1994年将Oak语言更名为Java&#xff1b; Jav…

把百度网站设为首页_网站百度推广效果好不好?怎样才能把网站推广到百度首页?...

在移动互联网营销的过程中&#xff0c;有着各式各样的营销手段&#xff0c;也有着丰富多彩的营销平台&#xff0c;而百度平台是大家非常熟悉的&#xff0c;它拥有着亿万用户&#xff0c;几乎小伙伴们每天都需要通过百度查找各种资讯&#xff0c;来满足自己的需求&#xff0c;丰…

ZZULI 1876: 蛤玮的项链 Hash + 二分

Time Limit: 6 Sec Memory Limit: 128 MBSubmit: 153 Solved: 11SubmitStatusWeb BoardDescription 蛤玮向心仪的妹子送了一条项链,这条项链是由小写字母构成的首尾相接的字符串,妹子看了看项链对蛤玮说,"我希望它是对称的",蛤玮想了想之后决定,从项链上截取出一段…

python调用菜单响应事件_Python处理菜单消息操作示例【基于win32ui模块】

本文实例讲述了Python处理菜单消息操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 一、代码 # -*- coding:utf-8 -*- #! python3 import win32ui import win32api from win32con import * from pywin.mfc import window class MyWnd(window.Wnd): def __init__ (…

ucharts 折线 点_ucharts图表引入的两种方式

import uCharts from ../js_sdk/u-charts/u-charts/u-charts.js; //可以优化放全局 uCharts >使用全局const lineCharts {},optionAs {};export default {name: LineChart,props: {dataAs: {//数据type: Object,default: () > ({})},basicAs: {通用基础项设置type: Obj…

VMI和JIT

1&#xff0e;JIT生产方式的含义JIT生产方式的基本思想可用现在已经广为流传的一句话来概括&#xff0c;即“只在需要时&#xff0c;按需要的量&#xff0c;生产所需的产品”&#xff0c;这也就是just in time一词所要表达的本来含义。这种生产方式的核心是追求一种零库存、零浪…

全连接条件随机场_条件随机场CRF简介

作者&#xff1a;Ravish Chawla编译&#xff1a;ronghuaiyang导读一个简单明了的对条件随机场的说明&#xff0c;给大家一个非常直观的印象&#xff0c;CRF到底是个什么东西&#xff0c;能干什么用。条件随机场是一种用于序列预测的判别模型。它们使用来自以前标签的上下文信息…