You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/07/17 09:36:15 UTC

[skywalking] branch master updated: Fix issue 4965 (#5109)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 62f7688  Fix issue 4965 (#5109)
62f7688 is described below

commit 62f76881de990917f229e5121e9094f977599da3
Author: Patrick Jiang(白泽) <pa...@gmail.com>
AuthorDate: Fri Jul 17 17:36:02 2020 +0800

    Fix issue 4965 (#5109)
---
 ...PreparedStatementExecuteMethodsInterceptor.java | 12 ++--
 .../mysql-scenario/config/expectedData.yaml        | 69 +++++++++++++++++++++-
 .../skywalking/apm/testcase/mysql/SQLExecutor.java | 21 ++++++-
 .../testcase/mysql/controller/CaseController.java  |  8 ++-
 4 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
index fa0613a..27f4c6b 100644
--- a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
+++ b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/PreparedStatementExecuteMethodsInterceptor.java
@@ -40,15 +40,15 @@ public class PreparedStatementExecuteMethodsInterceptor implements InstanceMetho
     public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
                                    Class<?>[] argumentsTypes, MethodInterceptResult result) {
         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.
-         *
+         * When invoking prepareCall, cacheObject is null. Because it will determine procedures's parameter types by executing sql in mysql 
+         * before the interceptor sets the statementEnhanceInfos.
          * @see JDBCDriverInterceptor#afterMethod(EnhancedInstance, Method, Object[], Class[], Object)
          */
-        if (connectInfo != null) {
-
+        if (cacheObject != null && cacheObject.getConnectionInfo() != null) {
+            ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
             AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
                     .getStatementName()), connectInfo.getDatabasePeer());
             Tags.DB_TYPE.set(span, "sql");
@@ -73,7 +73,7 @@ public class PreparedStatementExecuteMethodsInterceptor implements InstanceMetho
     public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
                                     Class<?>[] argumentsTypes, Object ret) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
-        if (cacheObject.getConnectionInfo() != null) {
+        if (cacheObject != null && cacheObject.getConnectionInfo() != null) {
             ContextManager.stopSpan();
         }
         return ret;
@@ -83,7 +83,7 @@ public class PreparedStatementExecuteMethodsInterceptor implements InstanceMetho
     public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
                                             Class<?>[] argumentsTypes, Throwable t) {
         StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
-        if (cacheObject.getConnectionInfo() != null) {
+        if (cacheObject != null && cacheObject.getConnectionInfo() != null) {
             ContextManager.activeSpan().errorOccurred().log(t);
         }
     }
diff --git a/test/plugin/scenarios/mysql-scenario/config/expectedData.yaml b/test/plugin/scenarios/mysql-scenario/config/expectedData.yaml
index 9313e79..904004e 100644
--- a/test/plugin/scenarios/mysql-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/mysql-scenario/config/expectedData.yaml
@@ -72,11 +72,78 @@ segmentItems:
       componentId: 33
       peer: mysql-server:3306
       skipAnalysis: 'false'
-    - operationName: Mysql/JDBI/Connection/close
+    - operationName: Mysql/JDBI/Statement/execute
       operationId: eq 0
       parentSpanId: 0
       spanId: 4
       tags:
+        - {key: db.type, value: sql}
+        - {key: db.instance, value: test}
+        - {key: db.statement, value: "create procedure testProcedure(IN id varchar(10)) \n begin \n select id; \n end"}
+      logs: []
+      startTime: nq 0
+      endTime: nq 0
+      isError: false
+      spanLayer: Database
+      spanType: Exit
+      componentId: 33
+      peer: mysql-server:3306
+      skipAnalysis: 'false'  
+    - operationName: Mysql/JDBI/Statement/executeQuery
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 5
+      spanLayer: Database
+      startTime: nq 0
+      endTime: nq 0
+      componentId: 33
+      isError: false
+      spanType: Exit
+      peer: mysql-server:3306
+      skipAnalysis: false
+      tags:
+        - {key: db.type, value: sql}
+        - {key: db.instance, value: test}
+        - {key: db.statement, value: SHOW CREATE PROCEDURE `test`.`testProcedure`}
+    - operationName: Mysql/JDBI/CallableStatement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 6
+      tags:
+        - {key: db.type, value: sql}
+        - {key: db.instance, value: test}
+        - {key: db.statement, value: "call testProcedure( ? )"}
+      logs: []
+      startTime: nq 0
+      endTime: nq 0
+      isError: false
+      spanLayer: Database
+      spanType: Exit
+      componentId: 33
+      peer: mysql-server:3306
+      skipAnalysis: 'false'
+    - operationName: Mysql/JDBI/Statement/execute
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 7
+      tags:
+        - {key: db.type, value: sql}
+        - {key: db.instance, value: test}
+        - {key: db.statement, value: "drop procedure testProcedure"}
+      logs: []
+      startTime: nq 0
+      endTime: nq 0
+      isError: false
+      spanLayer: Database
+      spanType: Exit
+      componentId: 33
+      peer: mysql-server:3306
+      skipAnalysis: 'false'  
+    - operationName: Mysql/JDBI/Connection/close
+      operationId: eq 0
+      parentSpanId: 0
+      spanId: 8
+      tags:
       - {key: db.type, value: sql}
       - {key: db.instance, value: test}
       - {key: db.statement, value: ''}
diff --git a/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java b/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java
index 77e0205..268ef97 100644
--- a/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java
+++ b/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java
@@ -51,11 +51,30 @@ public class SQLExecutor implements AutoCloseable {
     }
 
     public void dropTable(String sql) throws SQLException {
+        executeStatement(sql);
+    }
+    
+    public void createProcedure(String sql) throws SQLException {
+        executeStatement(sql);
+    }
+    
+    public void dropProcedure(String sql) throws SQLException {
+        executeStatement(sql);
+    }
+    
+    public void callProcedure(String sql, String id) throws SQLException {
+        PreparedStatement preparedStatement = connection.prepareCall(sql);
+        preparedStatement.setString(1, id);
+        preparedStatement.execute();
+        preparedStatement.close();
+    }
+    
+    public void executeStatement(String sql) throws SQLException {
         Statement preparedStatement = connection.createStatement();
         preparedStatement.execute(sql);
         preparedStatement.close();
     }
-
+    
     public void closeConnection() throws SQLException {
         if (this.connection != null) {
             this.connection.close();
diff --git a/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java b/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java
index f72b4ef..415c654 100644
--- a/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java
+++ b/test/plugin/scenarios/mysql-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java
@@ -40,7 +40,10 @@ public class CaseController {
     private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_007 WHERE id=?";
     private static final String DELETE_DATA_SQL = "DELETE FROM test_007 WHERE id=?";
     private static final String DROP_TABLE_SQL = "DROP table test_007";
-
+    private static final String CREATE_PROCEDURE_SQL = "create procedure testProcedure(IN id varchar(10)) \n begin \n select id; \n end";
+    private static final String CALL_PROCEDURE_SQL = "call testProcedure( ? )";
+    private static final String DROP_PROCEDURE_SQL = "drop procedure testProcedure";
+    
     @RequestMapping("/mysql-scenario")
     @ResponseBody
     public String testcase() throws Exception {
@@ -48,6 +51,9 @@ public class CaseController {
             sqlExecute.createTable(CREATE_TABLE_SQL);
             sqlExecute.insertData(INSERT_DATA_SQL, "1", "1");
             sqlExecute.dropTable(DROP_TABLE_SQL);
+            sqlExecute.createProcedure(CREATE_PROCEDURE_SQL);
+            sqlExecute.callProcedure(CALL_PROCEDURE_SQL, "nihao");
+            sqlExecute.dropProcedure(DROP_PROCEDURE_SQL);
         } catch (Exception e) {
             logger.error("Failed to execute sql.", e);
             throw e;