diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java index 09b1e8880..4b58e86ed 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; @@ -40,9 +39,32 @@ public class MysqlURLParser extends AbstractURLParser { protected URLLocation fetchDatabaseHostsIndexRange() { int hostLabelStartIndex = url.indexOf("//"); int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = url.indexOf("?", hostLabelStartIndex + 2); + } return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); } + protected String fetchDatabaseNameFromURL(int startSize) { + URLLocation hostsLocation = fetchDatabaseNameIndexRange(startSize); + if (hostsLocation == null) { + return ""; + } + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); + } + + protected URLLocation fetchDatabaseNameIndexRange(int startSize) { + int databaseStartTag = url.indexOf("/", startSize); + if (databaseStartTag == -1) { + return null; + } + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + @Override protected URLLocation fetchDatabaseNameIndexRange() { int databaseStartTag = url.lastIndexOf("/"); @@ -71,9 +93,9 @@ public class MysqlURLParser extends AbstractURLParser { } else { String[] hostAndPort = hostSegment[0].split(":"); if (hostAndPort.length != 1) { - return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL(location.endIndex())); } else { - return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + return new ConnectionInfo(ComponentsDefine.MYSQL_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location.endIndex())); } } } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java index cd7352286..bed5f6ba9 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/ConnectionInfo.java @@ -16,7 +16,6 @@ * */ - package org.apache.skywalking.apm.plugin.jdbc.trace; import org.apache.skywalking.apm.network.trace.component.OfficialComponent; @@ -35,7 +34,7 @@ public class ConnectionInfo { /** * Operation database name. */ - private final String databaseName; + private String databaseName; private String databasePeer; @@ -74,4 +73,7 @@ public class ConnectionInfo { return component; } + public void setDatabaseName(String dataBaseName) { + this.databaseName = dataBaseName; + } } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java index 77af8f559..a8d70177a 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -34,6 +34,14 @@ public class URLParserTest { assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); } + @Test + public void testParseMysqlJDBCURLWithoutDB() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost?profileSQL=true"); + assertThat(connectionInfo.getDBType(), is("Mysql")); + assertThat(connectionInfo.getDatabaseName(), is("")); + assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); + } + @Test public void testParseMysqlJDBCURLWithHostAndPort() { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307/test?profileSQL=true"); diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/SetCatalogInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/SetCatalogInterceptor.java new file mode 100644 index 000000000..4f8d2475e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/SetCatalogInterceptor.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + * + */ + +package org.apache.skywalking.apm.plugin.jdbc.mysql; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class SetCatalogInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + Object dynamicField = objInst.getSkyWalkingDynamicField(); + if (dynamicField instanceof ConnectionInfo) { + ((ConnectionInfo)dynamicField).setDatabaseName(String.valueOf(allArguments[0])); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java index b9e2a9edb..78215d0a6 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/define/ConnectionInstrumentation.java @@ -97,6 +97,19 @@ public abstract class ConnectionInstrumentation extends ClassInstanceMethodsEnha return Constants.SERVICE_METHOD_INTERCEPT_CLASS; } + @Override public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named("setCatalog"); + } + + @Override public String getMethodsInterceptor() { + return "org.apache.skywalking.apm.plugin.jdbc.mysql.SetCatalogInterceptor"; + } + @Override public boolean isOverrideArgs() { return false; }