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
skywalking使用mysql_聊聊skywalking的mysql-plugin相关推荐
- mysql pool not open_安装 MariaDb 时报错:Could not open mysql.plugin table
安装 MariaDb 时报错 2015-12-10 10:52:31 13f4 InnoDB: Warning: Using innodb_additional_mem_pool_size is DE ...
- Table 'mysql.plugin' doesn't exist引发de血案
2019独角兽企业重金招聘Python工程师标准>>> 回过头想想,一开始查下mysql_install_db这个命令,也不至于承受着巨大的压力折腾两天,不得不说,折腾下来的收获真的 ...
- oem监控mysql_OEM12c 安装配置MySQL Plug-in用来监控MySQL
Plug-in --注册信息 [root@test agent]# /oem/emcli setup -url=https://omsdb.localdomain:7301/em -username= ...
- mysql table plugin_MySQL 启动报错Table 'mysql.plugin' doesn't exis(转载)
安装完成后,按照网上说启动mysql时却报了以下错误: [root@localhost bin]# ./mysqld 2015-10-23 16:54:55 0 [Warning] TIMESTAMP ...
- 处理mysql启动报错Table 'mysql.plugin' doesn't exis
2015-10-23 本来今天工作会比较忙,可惜开发在配置云平台的时候居然出现了各种奇奇怪怪的问题,原来在测试环境好好的,就是配置到云平台后就出问题咯,明天周六了,搞到我要加班了,反正问题我不管了,快 ...
- Mysql :Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
Mysql :Can't open the mysql.plugin table. Please run mysql_upgrade to create it. MySQL 服务正在启动 . MySQ ...
- mysql table plugin,MySql报错Table mysql.plugin doesn’t exist的解决方法
MySql报错Table mysql.plugin doesn't exist的解决方法 一般产生原因是手工更改my.ini的数据库文件存放地址导致的 mysql服务启动时候找不到内置数据库" ...
- MySQL5.7服务无法启动或Table ‘mysql.plugin‘ doesn‘t exist
MySQL部署时提示Table mysql.plugin doesn't exist的解决方法 https://www.jb51.net/article/116604.htm 今天部署了免安装版的My ...
- mysqld: Table ‘mysql.plugin‘ doesn‘t exist
背景是:安装mysql,之前rpm过mysql,然后卸载了 2022-01-23T04:49:31.611319Z 0 [Note] Binlog end 2022-01-23T04:49:31.61 ...
最新文章
- CentOS7.2 安装Docker
- Matlab(一) .jpg转.ppm
- 博客园有人随笔总数10000+?
- python用什么运行环境_使用SAE部署Python运行环境的教程
- simulink中使用memory模块实现变量的累加和(离散积分器)
- 牛客题霸 NC30 数组中未出现的最小正整数
- ChartCtrl源码剖析之——CChartAxis类
- mysql创建表属性引_【学习之Mysql数据库】mysql数据库创建表的属性详解
- XML解析-Dom4j的DOM解析方式更新XML
- 啥是佩奇?爷爷,我用Python给你画一个
- 说说我眼中的IT界加班文化
- nacos 负载策略_Nacos(一):Nacos介绍
- *第七周*数据结构实践项目二【建设链式队列算法库】
- 微信打飞机项目小结-屏幕适配
- Android--高德地图,显示地图,并定位当前的位置
- 家里蹲太孤单?来用python画一只单身狗吧
- 在ros中使用glog
- linux 批量下载fnl,TMS370C356FNL
- LoRaWAN协议-物理层(PHY)详解
- OSPF单区域配置实验
热门文章
- java sax xml文件解析_java解析xml文件-DOM/SAX
- mac mysql密码错误_解决mac 下mysql安装后root用户登录密码错误问题
- mqtt 发送消息过多_阿里云MQTT服务端注解式消息处理分发与同步调用实践小结
- python批量新建文件_python批量处理
- 捧上天的AI落地困难,“ 不懂变通”的华为云如何应付?
- [洛谷P1341]无序字母对
- CSharpGL(49)试水OpenGL软实现
- FloatingActionMenu 向上弹出菜单
- MySQL5.7.17的简单配置文件
- Tomcat 服务器只能存有一个正在运行的项目