diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/AbstractURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/AbstractURLParser.java index 74a897dc6f7c594516146577f524df9928856d23..2d5d69419351db9e234af67cb7f154a2ae0170cb 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/AbstractURLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/AbstractURLParser.java @@ -31,14 +31,14 @@ public abstract class AbstractURLParser implements ConnectionURLParser { * * @return index range that database hosts. */ - protected abstract int[] fetchDatabaseHostsIndexRange(); + protected abstract URLLocation fetchDatabaseHostsIndexRange(); /** * Fetch the index range that database name from connection url. * * @return index range that database name. */ - protected abstract int[] fetchDatabaseNameIndexRange(); + protected abstract URLLocation fetchDatabaseNameIndexRange(); /** * Fetch database host(s) from connection url. @@ -46,8 +46,8 @@ public abstract class AbstractURLParser implements ConnectionURLParser { * @return database host(s). */ protected String fetchDatabaseHostsFromURL() { - int[] indexRange = fetchDatabaseHostsIndexRange(); - return url.substring(indexRange[0], indexRange[1]); + URLLocation hostsLocation = fetchDatabaseHostsIndexRange(); + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); } /** @@ -56,8 +56,8 @@ public abstract class AbstractURLParser implements ConnectionURLParser { * @return database name. */ protected String fetchDatabaseNameFromURL() { - int[] indexRange = fetchDatabaseNameIndexRange(); - return url.substring(indexRange[0], indexRange[1]); + URLLocation hostsLocation = fetchDatabaseNameIndexRange(); + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); } /** diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/H2URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/H2URLParser.java index 416b486984a9f13221e0c75e3f435653170973d0..1e79d8e026d72a9ecb4be7d9c7c263b92114729e 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/H2URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/H2URLParser.java @@ -55,20 +55,20 @@ public class H2URLParser extends AbstractURLParser { } @Override - protected int[] fetchDatabaseHostsIndexRange() { + protected URLLocation fetchDatabaseHostsIndexRange() { int hostLabelStartIndex = url.indexOf("//"); int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); - return new int[] {hostLabelStartIndex + 2, hostLabelEndIndex}; + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); } @Override - protected int[] fetchDatabaseNameIndexRange() { + protected URLLocation fetchDatabaseNameIndexRange() { int databaseStartTag = url.lastIndexOf("/"); int databaseEndTag = url.indexOf(";"); if (databaseEndTag == -1) { databaseEndTag = url.length(); } - return new int[] {databaseStartTag + 1, databaseEndTag}; + return new URLLocation(databaseStartTag + 1, databaseEndTag); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java index 0f71dd8c56a814a7d94256986e91b1b07f11e0ef..d463c0568c4dc324ff35578f601cfdbeee4817c8 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/MysqlURLParser.java @@ -41,26 +41,26 @@ public class MysqlURLParser extends AbstractURLParser { } @Override - protected int[] fetchDatabaseHostsIndexRange() { + protected URLLocation fetchDatabaseHostsIndexRange() { int hostLabelStartIndex = url.indexOf("//"); int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); - return new int[] {hostLabelStartIndex + 2, hostLabelEndIndex}; + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); } @Override - protected int[] fetchDatabaseNameIndexRange() { + protected URLLocation fetchDatabaseNameIndexRange() { int databaseStartTag = url.lastIndexOf("/"); int databaseEndTag = url.indexOf("?", databaseStartTag); if (databaseEndTag == -1) { databaseEndTag = url.length(); } - return new int[] {databaseStartTag + 1, databaseEndTag}; + return new URLLocation(databaseStartTag + 1, databaseEndTag); } @Override public ConnectionInfo parse() { - int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); - String hosts = url.substring(hostRangeIndex[0], hostRangeIndex[1]); + URLLocation location = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(location.startIndex(), location.endIndex()); String[] hostSegment = hosts.split(","); if (hostSegment.length > 1) { StringBuilder sb = new StringBuilder(); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/OracleURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/OracleURLParser.java index 78523dab4a801e18c355c5ce6f97c608884975f3..bf3c91e22ee4380cf1eb3ed6c119e277cccac16a 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/OracleURLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/OracleURLParser.java @@ -18,8 +18,11 @@ package org.skywalking.apm.plugin.jdbc.connectionurl.parser; +import java.util.ArrayList; +import java.util.List; import org.skywalking.apm.network.trace.component.ComponentsDefine; import org.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.skywalking.apm.util.StringUtil; /** * {@link OracleURLParser} presents that how to parse oracle connection url. @@ -38,29 +41,61 @@ public class OracleURLParser extends AbstractURLParser { private static final String DB_TYPE = "Oracle"; private static final int DEFAULT_PORT = 1521; + public static final String SERVICE_NAME_FLAG = "@//"; + public static final String TNSNAME_URL_FLAG = "DESCRIPTION"; public OracleURLParser(String url) { super(url); } @Override - protected int[] fetchDatabaseHostsIndexRange() { - int hostLabelStartIndex = url.indexOf("@"); + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex; + if (isServiceNameURL()) { + hostLabelStartIndex = url.indexOf(SERVICE_NAME_FLAG) + 3; + } else { + hostLabelStartIndex = url.indexOf("@") + 1; + } int hostLabelEndIndex = url.lastIndexOf(":"); - return new int[] {hostLabelStartIndex + 1, hostLabelEndIndex}; + return new URLLocation(hostLabelStartIndex, hostLabelEndIndex); } @Override - protected int[] fetchDatabaseNameIndexRange() { - return new int[0]; + protected URLLocation fetchDatabaseNameIndexRange() { + int hostLabelStartIndex; + int hostLabelEndIndex = url.length(); + if (isServiceNameURL()) { + hostLabelStartIndex = url.lastIndexOf("/") + 1; + } else if (isTNSNameURL()) { + hostLabelStartIndex = url.indexOf("=", url.indexOf("SERVICE_NAME")) + 1; + hostLabelEndIndex = url.indexOf(")", hostLabelStartIndex); + } else { + hostLabelStartIndex = url.lastIndexOf(":") + 1; + } + return new URLLocation(hostLabelStartIndex, hostLabelEndIndex); + } + + private boolean isServiceNameURL() { + return url.contains(SERVICE_NAME_FLAG); + } + + private boolean isTNSNameURL() { + return url.contains(TNSNAME_URL_FLAG); } @Override public ConnectionInfo parse() { - int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + if (isTNSNameURL()) { + return tnsNameURLParse(); + } else { + return commonsURLParse(); + } + } + + private ConnectionInfo commonsURLParse() { String host = fetchDatabaseHostsFromURL(); String[] hostSegment = splitDatabaseAddress(host); - String databaseName = url.substring(hostRangeIndex[1] + 1); + String databaseName = fetchDatabaseNameFromURL(); if (hostSegment.length == 1) { return new ConnectionInfo(ComponentsDefine.ORACLE, DB_TYPE, host, DEFAULT_PORT, databaseName); } else { @@ -68,6 +103,40 @@ public class OracleURLParser extends AbstractURLParser { } } + private ConnectionInfo tnsNameURLParse() { + String host = parseDatabaseHostsFromURL(); + String databaseName = fetchDatabaseNameFromURL(); + return new ConnectionInfo(ComponentsDefine.ORACLE, DB_TYPE, host, databaseName); + } + + private String parseDatabaseHostsFromURL() { + int beginIndex = url.indexOf("DESCRIPTION"); + List hosts = new ArrayList(); + do { + int hostStartIndex = url.indexOf("HOST", beginIndex); + if (hostStartIndex == -1) { + break; + } + int equalStartIndex = url.indexOf("=", hostStartIndex); + int hostEndIndex = url.indexOf(")", hostStartIndex); + String host = url.substring(equalStartIndex + 1, hostEndIndex); + + int port = DEFAULT_PORT; + int portStartIndex = url.indexOf("PORT", hostEndIndex); + int portEndIndex = url.length(); + if (portStartIndex != -1) { + int portEqualStartIndex = url.indexOf("=", portStartIndex); + portEndIndex = url.indexOf(")", portEqualStartIndex); + port = Integer.parseInt(url.substring(portEqualStartIndex + 1, portEndIndex).trim()); + } + hosts.add(host.trim() + ":" + port); + beginIndex = portEndIndex; + } + while (true); + + return StringUtil.join(',', hosts.toArray(new String[0])); + } + private String[] splitDatabaseAddress(String address) { String[] hostSegment = address.split(":"); return hostSegment; diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java index 2b2451aecd2ec6e388c7058d871a9eabb8f02efa..4509d732d2b1c62937b365d286d574bfaa1e0ef3 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/PostgreSQLURLParser.java @@ -41,26 +41,26 @@ public class PostgreSQLURLParser extends AbstractURLParser { } @Override - protected int[] fetchDatabaseHostsIndexRange() { + protected URLLocation fetchDatabaseHostsIndexRange() { int hostLabelStartIndex = url.indexOf("//"); int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); - return new int[] {hostLabelStartIndex + 2, hostLabelEndIndex}; + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); } @Override - protected int[] fetchDatabaseNameIndexRange() { + protected URLLocation fetchDatabaseNameIndexRange() { int databaseStartTag = url.lastIndexOf("/"); int databaseEndTag = url.indexOf("?", databaseStartTag); if (databaseEndTag == -1) { databaseEndTag = url.length(); } - return new int[] {databaseStartTag + 1, databaseEndTag}; + return new URLLocation(databaseStartTag + 1, databaseEndTag); } @Override public ConnectionInfo parse() { - int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); - String hosts = url.substring(hostRangeIndex[0], hostRangeIndex[1]); + URLLocation location = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(location.startIndex(), location.endIndex()); String[] hostSegment = hosts.split(","); if (hostSegment.length > 1) { StringBuilder sb = new StringBuilder(); diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLLocation.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLLocation.java new file mode 100644 index 0000000000000000000000000000000000000000..689087916b0de7b6981568f811bc6cc8e5f207ca --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/skywalking/apm/plugin/jdbc/connectionurl/parser/URLLocation.java @@ -0,0 +1,37 @@ +/* + * 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.connectionurl.parser; + +public class URLLocation { + private final int startIndex; + private final int endIndex; + + public URLLocation(int startIndex, int endIndex) { + this.startIndex = startIndex; + this.endIndex = endIndex; + } + + public int startIndex() { + return startIndex; + } + + public int endIndex() { + return endIndex; + } +} 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 7f15d3392221c36e291b9996c12a023689724e7c..2f7598847486a4cc6fc972d462fb5ff4fdf6ba34 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 @@ -73,6 +73,30 @@ public class URLParserTest { assertThat(connectionInfo.getDatabasePeer(), is("localhost:1522")); } + @Test + public void testParseOracleServiceName() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@//localhost:1521/orcl"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); + } + + @Test + public void testParseOracleTNSName() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= localhost )(PORT= 1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); + } + + @Test + public void testParseOracleTNSNameWithMultiAddress() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL= TCP)(HOST=hostA)(PORT= 1523 ))(ADDRESS=(PROTOCOL=TCP)(HOST=hostB)(PORT= 1521 )))(SOURCE_ROUTE=yes)(CONNECT_DATA=(SERVICE_NAME=orcl)))"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getDatabasePeer(), is("hostA:1523,hostB:1521")); + } + @Test public void testParseOracleJDBCURLWithUserNameAndPassword() { ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl");