源码分析一插件定义
StatementInstrumentation插件拦截StatementImpl相关方法进行增强 jdbc含包含其他众多插件 其中CONSTRUCTOR_INTERCEPTOR并非skywalking源码,其为笔者私有定制,用于全链路压测场景
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" ;
private static final String CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.mysql.v8.StatementCreateInterceptor" ;
@Override public ConstructorInterceptPoint[ ] getConstructorsInterceptPoints ( ) {
return new ConstructorInterceptPoint [ ] { new ConstructorInterceptPoint ( ) {
@Override
public ElementMatcher< MethodDescription> getConstructorMatcher ( ) {
return any ( ) ;
}
@Override
public String getConstructorInterceptor ( ) {
return CONSTRUCTOR_INTERCEPTOR;
}
} } ;
}
@Override public InstanceMethodsInterceptPoint[ ] getInstanceMethodsInterceptPoints ( ) {
return new InstanceMethodsInterceptPoint [ ] {
new InstanceMethodsInterceptPoint ( ) {
@Override public ElementMatcher< MethodDescription> 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) ;
}
}
源码分析一方法拦截器定义
设置数据库span的相关kv键值对 包含sql语句等
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 ( ) ;
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 ( ) ) ;
String sql = "" ;
if ( allArguments. length > 0 ) {
sql = ( String) allArguments[ 0 ] ;
}
为span设置sql语句
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;
}
private String buildOperationName ( ConnectionInfo connectionInfo, String methodName, String statementName) {
return connectionInfo. getDBType ( ) + "/JDBI/" + statementName + "/" + methodName;
}
}
总结
jdbc插件众多,本文分析的Statement是一个重点,其创建的span持有sql语句,查询参数等信息