diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionServiceMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionServiceMethodInterceptor.java index 0ae91f465c9b6edeb4bcaedefed0b45d2bf1278a..b3476192a5f98191b30da9d20667613edf3aea61 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionServiceMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionServiceMethodInterceptor.java @@ -27,15 +27,11 @@ import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; -import org.skywalking.apm.util.StringUtil; /** - * {@link ConnectionServiceMethodInterceptor} create an exit span when the client call the following methods in the class - * that extend {@link java.sql.Connection}. - * 1. close - * 2. rollback - * 3. releaseSavepoint - * 4. commit + * {@link ConnectionServiceMethodInterceptor} create an exit span when the client call the following methods in the + * class that extend {@link java.sql.Connection}. 1. close 2. rollback 3. releaseSavepoint 4. commit + * * @author zhangxin */ public class ConnectionServiceMethodInterceptor implements InstanceMethodsAroundInterceptor { @@ -45,13 +41,7 @@ public class ConnectionServiceMethodInterceptor implements InstanceMethodsAround Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { ConnectionInfo connectInfo = (ConnectionInfo)objInst.getSkyWalkingDynamicField(); - String remotePeer; - if (!StringUtil.isEmpty(connectInfo.getHosts())) { - remotePeer = connectInfo.getHosts(); - } else { - remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort(); - } - AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method.getName(), remotePeer); + 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, ""); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java index d0b25cc94ffa470a1c67357e9b71c7f7b17ca3b8..c0a3fcad43954c41bd93f4d976a95d4a6fc62366 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java @@ -23,7 +23,6 @@ import org.skywalking.apm.agent.core.context.ContextManager; import org.skywalking.apm.agent.core.context.tag.Tags; import org.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.skywalking.apm.util.StringUtil; /** * {@link CallableStatementTracing} create an exit span when the client call the method in the class that extend {@link @@ -37,13 +36,7 @@ public class CallableStatementTracing { ConnectionInfo connectInfo, String method, String sql, Executable exec) throws SQLException { try { - String remotePeer; - if (!StringUtil.isEmpty(connectInfo.getHosts())) { - remotePeer = connectInfo.getHosts(); - } else { - remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort(); - } - AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/CallableStatement/" + method, remotePeer); + AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/CallableStatement/" + method, connectInfo.getDatabasePeer()); Tags.DB_TYPE.set(span, "sql"); SpanLayer.asDB(span); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java index a9ab5e5c41fdd7ee5165192c2d69783fcf3eabca..724afb26db917f17a2a0ee22ef38e52d942caab9 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java @@ -31,22 +31,12 @@ 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; + + private String databasePeer; /** * Component @@ -55,15 +45,14 @@ public class ConnectionInfo { public ConnectionInfo(OfficialComponent component, String dbType, String host, int port, String databaseName) { this.dbType = dbType; - this.host = host; - this.port = port; + this.databasePeer = host + ":" + port; this.databaseName = databaseName; this.component = component; } public ConnectionInfo(OfficialComponent component, String dbType, String hosts, String databaseName) { this.dbType = dbType; - this.hosts = hosts; + this.databasePeer = hosts; this.databaseName = databaseName; this.component = component; } @@ -72,20 +61,12 @@ public class ConnectionInfo { return dbType; } - public String getHost() { - return host; - } - - public int getPort() { - return port; - } - public String getDatabaseName() { return databaseName; } - public String getHosts() { - return hosts; + public String getDatabasePeer() { + return databasePeer; } public OfficialComponent getComponent() { diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java index 66d0f9f168f77450dbcdc2d748394699013cb84c..900366d7146f9cd3cea96ebf067bc4b854c67768 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java @@ -23,7 +23,6 @@ import org.skywalking.apm.agent.core.context.ContextManager; import org.skywalking.apm.agent.core.context.tag.Tags; import org.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.skywalking.apm.util.StringUtil; /** * {@link PreparedStatementTracing} create an exit span when the client call the method in the class that extend {@link @@ -37,14 +36,7 @@ public class PreparedStatementTracing { ConnectionInfo connectInfo, String method, String sql, Executable exec) throws SQLException { try { - String remotePeer; - if (!StringUtil.isEmpty(connectInfo.getHosts())) { - remotePeer = connectInfo.getHosts(); - } else { - remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort(); - } - - AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/PreparedStatement/" + method, remotePeer); + AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/PreparedStatement/" + method, connectInfo.getDatabasePeer()); Tags.DB_TYPE.set(span, "sql"); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/StatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/StatementTracing.java index 20e44032b1fa0787c9831c0218d4f59d95283c87..46ac2da7f2a8557c090fb113e158a3ed9612af5b 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/StatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/trace/StatementTracing.java @@ -23,7 +23,6 @@ import org.skywalking.apm.agent.core.context.ContextManager; import org.skywalking.apm.agent.core.context.tag.Tags; import org.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.skywalking.apm.util.StringUtil; /** * {@link PreparedStatementTracing} create an exit span when the client call the method in the class that extend {@link @@ -36,14 +35,7 @@ public class StatementTracing { ConnectionInfo connectInfo, String method, String sql, Executable exec) throws SQLException { try { - String remotePeer; - if (!StringUtil.isEmpty(connectInfo.getHosts())) { - remotePeer = connectInfo.getHosts(); - } else { - remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort(); - } - - AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Statement/" + method, remotePeer); + AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Statement/" + method, connectInfo.getDatabasePeer()); Tags.DB_TYPE.set(span, "sql"); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java index 8432fd9144ed4a6217af74a1d9ea658ce4f2840b..45fc7c2de271b7fd7b9a6514c51f865e55fd94c8 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java @@ -24,7 +24,6 @@ import org.skywalking.apm.agent.core.context.tag.Tags; import org.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.skywalking.apm.agent.core.context.trace.SpanLayer; import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; -import org.skywalking.apm.util.StringUtil; public class ConnectionTracing { @@ -32,13 +31,7 @@ public class ConnectionTracing { ConnectionInfo connectInfo, String method, String sql, Executable exec) throws SQLException { try { - String remotePeer; - if (!StringUtil.isEmpty(connectInfo.getHosts())) { - remotePeer = connectInfo.getHosts(); - } else { - remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort(); - } - AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method, remotePeer); + AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method, connectInfo.getDatabasePeer()); Tags.DB_TYPE.set(span, "sql"); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); Tags.DB_STATEMENT.set(span, sql); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java index 6d24e76aa04140608b12996fcb5afe2e7c02f068..7f15d3392221c36e291b9996c12a023689724e7c 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -30,8 +30,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost/test"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); - assertThat(connectionInfo.getHost(), is("primaryhost")); - assertThat(connectionInfo.getPort(), is(3306)); + assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); } @Test @@ -39,8 +38,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307/test?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); - assertThat(connectionInfo.getHost(), is("primaryhost")); - assertThat(connectionInfo.getPort(), is(3307)); + assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3307")); } @Test @@ -48,7 +46,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307,secondaryhost1,secondaryhost2/test?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); - assertThat(connectionInfo.getHosts(), is("primaryhost:3307,secondaryhost1:3306,secondaryhost2:3306,")); + assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3307,secondaryhost1:3306,secondaryhost2:3306,")); } @Test @@ -56,7 +54,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql:replication://master,slave1,slave2,slave3/test"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); - assertThat(connectionInfo.getHosts(), is("master:3306,slave1:3306,slave2:3306,slave3:3306,")); + assertThat(connectionInfo.getDatabasePeer(), is("master:3306,slave1:3306,slave2:3306,slave3:3306,")); } @Test @@ -64,8 +62,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(1521)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); } @Test @@ -73,8 +70,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:1522:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(1522)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1522")); } @Test @@ -82,8 +78,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); - assertThat(connectionInfo.getHost(), is("myhost")); - assertThat(connectionInfo.getPort(), is(1521)); + assertThat(connectionInfo.getDatabasePeer(), is("myhost:1521")); } @Test @@ -91,8 +86,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:/data/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("/data/sample")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(-1)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); } @Test @@ -100,8 +94,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:C:/data/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("C:/data/sample")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(-1)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); } @Test @@ -109,8 +102,7 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:mem:test_mem"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("test_mem")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(-1)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); } @Test @@ -118,7 +110,6 @@ public class URLParserTest { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:tcp://localhost:8084/~/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("sample")); - assertThat(connectionInfo.getHost(), is("localhost")); - assertThat(connectionInfo.getPort(), is(8084)); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:8084")); } } diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..5aaa176ab79d849ea6bf8c90a8541cf57d153779 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptor.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.jdbc.mysql.define.StatementEnhanceInfos; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link CreateStatementInterceptor} intercepts the {@link com.mysql.jdbc.ConnectionImpl#createStatement()} method in + * the {@link com.mysql.jdbc.ConnectionImpl} class. + * + * @author zhangxin + */ +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) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..ca4c7deedb4beaef0fd4002894e4bdd385aaf660 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptor.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.jdbc.mysql.define.StatementEnhanceInfos; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link CreateStatementInterceptor} intercepts the {@link com.mysql.jdbc.ConnectionImpl#prepareStatement()} method in + * the {@link com.mysql.jdbc.ConnectionImpl} class. + * + * @author zhangxin + */ +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) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..564254b5cf3834a6bd5304c296a2a7160a515e1a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptor.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.jdbc.mysql.define.StatementEnhanceInfos; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link CreateStatementInterceptor} intercepts the {@link com.mysql.jdbc.ConnectionImpl#createStatement()} method in + * the {@link com.mysql.jdbc.ConnectionImpl} class. + * + * @author zhangxin + */ +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(), "", "CallableStatement")); + } + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..d8fbd58cd96c8b8d543fc92b3f245072f2f59453 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.plugin.jdbc.mysql.define.StatementEnhanceInfos; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link StatementExecuteMethodsInterceptor} create the exit span when the client call the interceptor methods. + * + * @author zhangxin + */ +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()); + Tags.DB_STATEMENT.set(span, cacheObject.getSql()); + 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; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/AbstractPreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/AbstractPreparedStatementInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..bf73036f9c89aae4e62ce2919bfda03d96bcc61b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/AbstractPreparedStatementInstrumentation.java @@ -0,0 +1,69 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractPreparedStatementInstrumentation} define that the mysql-2.x plugin intercepts the following methods in + * the {@link com.mysql.jdbc.JDBC42PreparedStatement} and {@link com.mysql.jdbc.PreparedStatement} class. + * 1. execute
+ * 2. executeQuery
+ * 3. executeUpdate
+ * 4. executeLargeUpdate
+ * 5. addBatch
+ * + * @author zhangxin + */ +public abstract class AbstractPreparedStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String SERVICE_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor"; + + @Override protected final ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected final 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("addBatch")); + } + + @Override public String getMethodsInterceptor() { + return SERVICE_METHOD_INTERCEPTOR; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/CallableInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/CallableInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..f0e2fbb6d4750b61fb1747ffe0283454401d8f9d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/CallableInstrumentation.java @@ -0,0 +1,69 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameMatch.byMultiClassMath; + +/** + * {@link CallableInstrumentation} define that the mysql-2.x plugin intercepts the following methods in the {@link + * com.mysql.jdbc.CallableStatement} by {@link org.skywalking.apm.plugin.jdbc.mysql.CallableStatementInterceptor}. 1. + * execute
2. executeQuery
3. executeUpdate
+ * + * @author zhangxin + */ +public class CallableInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.mysql.jdbc.CallableStatement"; + private static final String SERVICE_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected 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 byMultiClassMath(ENHANCE_CLASS, "com.mysql.jdbc.cj.CallableStatement"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java index 2a952a55db9ee7383e1d343d4efab2214fd1226b..a45048cd1151d68546d88302190101c585bdc680 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java @@ -27,21 +27,18 @@ import org.skywalking.apm.agent.core.plugin.match.ClassMatch; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; -import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; import static org.skywalking.apm.plugin.jdbc.define.Constants.CLOSE_METHOD_NAME; import static org.skywalking.apm.plugin.jdbc.define.Constants.COMMIT_METHOD_NAME; -import static org.skywalking.apm.plugin.jdbc.define.Constants.CREATE_STATEMENT_INTERCEPT_CLASS; import static org.skywalking.apm.plugin.jdbc.define.Constants.CREATE_STATEMENT_METHOD_NAME; -import static org.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_CALL_INTERCEPT_CLASS; import static org.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_CALL_METHOD_NAME; -import static org.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_STATEMENT_INTERCEPT_CLASS; import static org.skywalking.apm.plugin.jdbc.define.Constants.PREPARE_STATEMENT_METHOD_NAME; import static org.skywalking.apm.plugin.jdbc.define.Constants.RELEASE_SAVE_POINT_METHOD_NAME; import static org.skywalking.apm.plugin.jdbc.define.Constants.ROLLBACK_METHOD_NAME; import static org.skywalking.apm.plugin.jdbc.define.Constants.SERVICE_METHOD_INTERCEPT_CLASS; +import static org.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameMatch.byMultiClassMath; /** - * {@link ConnectionInstrumentation} intercept the following methods that the class which extend {@link + * {@link ConnectionInstrumentation} intercepts the following methods that the class which extend {@link * com.mysql.jdbc.ConnectionImpl}.
* * 1. Enhance prepareStatement by org.skywalking.apm.plugin.jdbc.define.JDBCPrepareStatementInterceptor @@ -67,7 +64,7 @@ public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePlugin } @Override public String getMethodsInterceptor() { - return PREPARE_STATEMENT_INTERCEPT_CLASS; + return "org.skywalking.apm.plugin.jdbc.mysql.CreatePreparedStatementInterceptor"; } @Override public boolean isOverrideArgs() { @@ -80,7 +77,7 @@ public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePlugin } @Override public String getMethodsInterceptor() { - return PREPARE_CALL_INTERCEPT_CLASS; + return "org.skywalking.apm.plugin.jdbc.mysql.CreateCallableStatementInterceptor"; } @Override public boolean isOverrideArgs() { @@ -93,7 +90,7 @@ public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePlugin } @Override public String getMethodsInterceptor() { - return CREATE_STATEMENT_INTERCEPT_CLASS; + return "org.skywalking.apm.plugin.jdbc.mysql.CreateStatementInterceptor"; } @Override public boolean isOverrideArgs() { @@ -118,6 +115,6 @@ public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePlugin } @Override protected ClassMatch enhanceClass() { - return byName(ENHANCE_CLASS); + return byMultiClassMath(ENHANCE_CLASS, "com.mysql.cj.jdbc.ConnectionImpl"); } } diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java index daa0413c135ea7f9e9998dee44e0b9e85021fbd6..25d6ce62f2c163e348ef57c9185d0df060590516 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/DriverInstrumentation.java @@ -21,7 +21,7 @@ package org.skywalking.apm.plugin.jdbc.mysql.define; import org.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation; -import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; +import static org.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameMatch.byMultiClassMath; /** * {@link DriverInstrumentation} presents that skywalking intercepts {@link com.mysql.jdbc.Driver}. @@ -31,6 +31,6 @@ import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; public class DriverInstrumentation extends AbstractDriverInstrumentation { @Override protected ClassMatch enhanceClass() { - return byName("com.mysql.jdbc.Driver"); + return byMultiClassMath("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver"); } } diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/JDBC42PreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/JDBC42PreparedStatementInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..04f877fba86ca0b9de366c3e5aacb990eecaf7cc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/JDBC42PreparedStatementInstrumentation.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link JDBC42PreparedStatementInstrumentation} intercepts {@link com.mysql.jdbc.JDBC42PreparedStatement} class. + * + * @author zhangxin + */ +public class JDBC42PreparedStatementInstrumentation extends AbstractPreparedStatementInstrumentation { + private static final String ENHANCE_CLASS = "com.mysql.jdbc.JDBC42PreparedStatement"; + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/MultiClassNameMatch.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/MultiClassNameMatch.java new file mode 100644 index 0000000000000000000000000000000000000000..839b3787584d0f986d58cfbb6abada7a010508b2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/MultiClassNameMatch.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import java.util.Arrays; +import java.util.List; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.skywalking.apm.agent.core.plugin.match.IndirectMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * Match multiple classes name with an explicit class name. + * + * @author zhangxin + */ +public class MultiClassNameMatch implements IndirectMatch { + + private List matchClassNames; + + private MultiClassNameMatch(String[] classNames) { + if (classNames == null || classNames.length == 0) { + throw new IllegalArgumentException("match class names is null"); + } + this.matchClassNames = Arrays.asList(classNames); + } + + @Override + public ElementMatcher.Junction buildJunction() { + ElementMatcher.Junction junction = null; + for (String name : matchClassNames) { + if (junction == null) { + junction = named(name); + } else { + junction = junction.or(named(name)); + } + } + return junction; + } + + @Override + public boolean isMatch(TypeDescription typeDescription) { + return matchClassNames.contains(typeDescription.getTypeName()); + } + + public static ClassMatch byMultiClassMath(String... classNames) { + return new MultiClassNameMatch(classNames); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/PreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/PreparedStatementInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..bf0480f2d7c72d95fe514a6257b176e45a748da4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/PreparedStatementInstrumentation.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameMatch.byMultiClassMath; + +/** + * {@link JDBC42PreparedStatementInstrumentation} intercepts {@link com.mysql.jdbc.PreparedStatement} class. + * + * @author zhangxin + */ +public class PreparedStatementInstrumentation extends AbstractPreparedStatementInstrumentation { + + private static final String ENHANCE_CLASS = "com.mysql.jdbc.PreparedStatement"; + + @Override protected ClassMatch enhanceClass() { + return byMultiClassMath(ENHANCE_CLASS, "com.mysql.cj.jdbc.PreparedStatement"); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementEnhanceInfos.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementEnhanceInfos.java new file mode 100644 index 0000000000000000000000000000000000000000..4a6b8fbc42e7bdb877f5072e60c491ecd23a3e60 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementEnhanceInfos.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link StatementEnhanceInfos} contain the {@link org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo} and + * sql for trace mysql. + * + * @author zhangxin + */ +public class StatementEnhanceInfos { + private ConnectionInfo connectionInfo; + private String statementName; + private String sql; + + public StatementEnhanceInfos(ConnectionInfo connectionInfo, String sql, String statementName) { + this.connectionInfo = connectionInfo; + this.sql = sql; + this.statementName = statementName; + } + + public ConnectionInfo getConnectionInfo() { + return connectionInfo; + } + + public String getSql() { + return sql; + } + + public String getStatementName() { + return statementName; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementInstrumentation.java new file mode 100644 index 0000000000000000000000000000000000000000..0a63878ad600135e46f0a99f1d0342c634a53624 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/mysql/define/StatementInstrumentation.java @@ -0,0 +1,83 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.skywalking.apm.plugin.jdbc.mysql.define.MultiClassNameMatch.byMultiClassMath; + +/** + * {@link JDBC42PreparedStatementInstrumentation} intercepts the following methods in the {@link + * com.mysql.jdbc.JDBC42PreparedStatement} class. + * 1. execute
+ * 2. executeQuery
+ * 3. executeUpdate
+ * 4. executeLargeUpdate
+ * 5. addBatch
+ * 6. executeBatchInternal
+ * 7. executeUpdateInternal
+ * 8. executeQuery
+ * 9. executeBatch
+ * + * @author zhangxin + */ +public class StatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.mysql.jdbc.StatementImpl"; + private static final String SERVICE_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected 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("addBatch")) + .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 byMultiClassMath(ENHANCE_CLASS, "com.mysql.cj.jdbc.StatementImpl"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/resources/skywalking-plugin.def index db4e41ef3b690e9ac8d9da106e3279319c8e1229..622dc29d02608e7d0f98f06f58cd1007184c04ec 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1,6 @@ mysql=org.skywalking.apm.plugin.jdbc.mysql.define.DriverInstrumentation mysql=org.skywalking.apm.plugin.jdbc.mysql.define.ConnectionInstrumentation +mysql=org.skywalking.apm.plugin.jdbc.mysql.define.CallableInstrumentation +mysql=org.skywalking.apm.plugin.jdbc.mysql.define.PreparedStatementInstrumentation +mysql=org.skywalking.apm.plugin.jdbc.mysql.define.JDBC42PreparedStatementInstrumentation +mysql=org.skywalking.apm.plugin.jdbc.mysql.define.StatementInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2e71c7ad7abfd7ae800f7390473dab0adf06113d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateCallableStatementInterceptorTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CreateCallableStatementInterceptorTest { + + private CreateCallableStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreateCallableStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, ret); + verify(ret, times(1)).setSkyWalkingDynamicField(Matchers.any()); + } + + @Test + public void testResultIsNotEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..99c3c45cf2e09ed8c1f481104137af3cd1a9af44 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreatePreparedStatementInterceptorTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CreatePreparedStatementInterceptorTest { + private CreatePreparedStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreatePreparedStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, ret); + verify(ret, times(1)).setSkyWalkingDynamicField(Matchers.any()); + } + + @Test + public void testResultIsNotEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..19e94a425b5ae30523c22888809214e921fd1d7b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/CreateStatementInterceptorTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CreateStatementInterceptorTest { + + private CreateStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreateStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, ret); + verify(ret, times(1)).setSkyWalkingDynamicField(Matchers.any()); + } + + @Test + public void testResultIsNotEnhanceInstance() throws Throwable { + interceptor.afterMethod(objectInstance, null, new Object[] {"SELECT * FROM test"}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8c8425c6f05f2370cadc453eb7c25bfc5ca4925b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-2.x-plugin/src/test/java/org/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.SpanAssert; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.skywalking.apm.network.trace.component.ComponentsDefine; +import org.skywalking.apm.plugin.jdbc.mysql.define.StatementEnhanceInfos; +import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class StatementExecuteMethodsInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + private StatementExecuteMethodsInterceptor serviceMethodInterceptor; + + @Mock + private ConnectionInfo connectionInfo; + @Mock + private EnhancedInstance objectInstance; + @Mock + private Method method; + private StatementEnhanceInfos enhanceRequireCacheObject; + + @Before + public void setUp() { + serviceMethodInterceptor = new StatementExecuteMethodsInterceptor(); + + enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, "SELECT * FROM test", "CallableStatement"); + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject); + when(method.getName()).thenReturn("executeQuery"); + when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.H2); + when(connectionInfo.getDBType()).thenReturn("H2"); + when(connectionInfo.getDatabaseName()).thenReturn("test"); + when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3307"); + } + + @Test + public void testCreateDatabaseSpan() throws Throwable { + serviceMethodInterceptor.beforeMethod(objectInstance, method, null, null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, null, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("H2/JDBI/CallableStatement/")); + SpanAssert.assertTag(span, 0, "sql"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, "SELECT * FROM test"); + } + +}