Merge pull request #562 from ascrutae/fix/mysql-issue
fix occur ClassCastException when call the method of return generate key
This commit is contained in:
commit
032f4c711f
|
|
@ -27,15 +27,14 @@ 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}.
|
||||
* {@link ConnectionServiceMethodInterceptor} create an exit span when the following methods execute:
|
||||
* 1. close
|
||||
* 2. rollback
|
||||
* 3. releaseSavepoint
|
||||
* 4. commit
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class ConnectionServiceMethodInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
|
@ -45,13 +44,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, "");
|
||||
|
|
|
|||
|
|
@ -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<R> 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());
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<R> 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);
|
||||
|
|
|
|||
|
|
@ -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<R> 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);
|
||||
|
|
|
|||
|
|
@ -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<R> 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);
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
mysql=org.skywalking.apm.plugin.jdbc.mysql.define.DriverInstrumentation
|
||||
mysql=org.skywalking.apm.plugin.jdbc.mysql.define.ConnectionInstrumentation
|
||||
|
|
@ -25,10 +25,10 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-mysql-2.x-plugin</artifactId>
|
||||
<artifactId>apm-mysql-5.x-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>mysql-2.x-plugin</name>
|
||||
<name>mysql-5.x-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>[2.0.14,6.0.6]</version>
|
||||
<version>[5.1.22,6.0.6]</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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();
|
||||
/**
|
||||
* 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 org.skywalking.apm.plugin.jdbc.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());
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@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 <br/>
|
||||
* 2. executeQuery <br/>
|
||||
* 3. executeUpdate <br/>
|
||||
*
|
||||
* @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<MethodDescription> 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 byMultiClassMatch(ENHANCE_CLASS, "com.mysql.jdbc.cj.CallableStatement");
|
||||
}
|
||||
}
|
||||
|
|
@ -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.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@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}. <br/>
|
||||
*
|
||||
* 1. Enhance <code>prepareStatement</code> by <code>org.skywalking.apm.plugin.jdbc.define.JDBCPrepareStatementInterceptor</code>
|
||||
|
|
@ -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 byMultiClassMatch(ENHANCE_CLASS, "com.mysql.cj.jdbc.ConnectionImpl");
|
||||
}
|
||||
}
|
||||
|
|
@ -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.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@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 byMultiClassMatch("com.mysql.jdbc.Driver", "com.mysql.cj.jdbc.Driver");
|
||||
}
|
||||
}
|
||||
|
|
@ -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 class with a given set of classes.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class MultiClassNameMatch implements IndirectMatch {
|
||||
|
||||
private List<String> 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 byMultiClassMatch(String... classNames) {
|
||||
return new MultiClassNameMatch(classNames);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@link PreparedStatementInstrumentation} define that the mysql-2.x plugin intercepts the following methods in the
|
||||
* {@link com.mysql.jdbc.JDBC42PreparedStatement}, {@link com.mysql.jdbc.PreparedStatement} and {@link
|
||||
* com.mysql.cj.jdbc.PreparedStatement} class:
|
||||
* 1. execute <br/>
|
||||
* 2. executeQuery <br/>
|
||||
* 3. executeUpdate <br/>
|
||||
* 4. executeLargeUpdate <br/>
|
||||
* 5. addBatch <br/>
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class PreparedStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String PREPARED_STATEMENT_CLASS_NAME = "com.mysql.jdbc.PreparedStatement";
|
||||
private static final String SERVICE_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor";
|
||||
public static final String MYSQL6_PREPARED_STATEMENT_CLASS_NAME = "com.mysql.cj.jdbc.PreparedStatement";
|
||||
public static final String JDBC42_PREPARED_STATEMENT_CLASS_NAME = "com.mysql.jdbc.JDBC42PreparedStatement";
|
||||
|
||||
@Override protected final ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override protected final 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("addBatch"));
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return SERVICE_METHOD_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override protected ClassMatch enhanceClass() {
|
||||
return byMultiClassMatch(PREPARED_STATEMENT_CLASS_NAME, MYSQL6_PREPARED_STATEMENT_CLASS_NAME, JDBC42_PREPARED_STATEMENT_CLASS_NAME);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
* <code>sql</code> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.byMultiClassMatch;
|
||||
|
||||
/**
|
||||
* {@link StatementInstrumentation} intercepts the following methods in the {@link
|
||||
* com.mysql.jdbc.StatementImpl} and {@link com.mysql.cj.jdbc.StatementImpl}class.
|
||||
* 1. execute <br/>
|
||||
* 2. executeQuery <br/>
|
||||
* 3. executeUpdate <br/>
|
||||
* 4. executeLargeUpdate <br/>
|
||||
* 5. addBatch <br/>
|
||||
* 6. executeBatchInternal <br/>
|
||||
* 7. executeUpdateInternal <br/>
|
||||
* 8. executeQuery <br/>
|
||||
* 9. executeBatch <br/>
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class StatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
private static final String STATEMENT_CLASS_NAME = "com.mysql.jdbc.StatementImpl";
|
||||
private static final String SERVICE_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.jdbc.mysql.StatementExecuteMethodsInterceptor";
|
||||
public static final String MYSQL6_STATEMENT_CLASS_NAME = "com.mysql.cj.jdbc.StatementImpl";
|
||||
|
||||
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override protected 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("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 byMultiClassMatch(STATEMENT_CLASS_NAME, MYSQL6_STATEMENT_CLASS_NAME);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
mysql-5.x=org.skywalking.apm.plugin.jdbc.mysql.define.DriverInstrumentation
|
||||
mysql-5.x=org.skywalking.apm.plugin.jdbc.mysql.define.ConnectionInstrumentation
|
||||
mysql-5.x=org.skywalking.apm.plugin.jdbc.mysql.define.CallableInstrumentation
|
||||
mysql-5.x=org.skywalking.apm.plugin.jdbc.mysql.define.PreparedStatementInstrumentation
|
||||
mysql-5.x=org.skywalking.apm.plugin.jdbc.mysql.define.StatementInstrumentation
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
<module>sharding-jdbc-1.5.x-plugin</module>
|
||||
<module>xmemcached-2.x-plugin</module>
|
||||
<module>grpc-1.x-plugin</module>
|
||||
<module>mysql-2.x-plugin</module>
|
||||
<module>mysql-5.x-plugin</module>
|
||||
<module>h2-1.x-plugin</module>
|
||||
<module>postgresql-8.x-plugin</module>
|
||||
<module>oracle-10.x-plugin</module>
|
||||
|
|
|
|||
Loading…
Reference in New Issue