/* * Copyright 2014 NAVER Corp. * * 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. */ package com.navercorp.pinpoint.plugin.jdbc.mariadb; import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.jdbc.DefaultDatabaseInfo; import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcUrlParserV2; import com.navercorp.pinpoint.bootstrap.plugin.jdbc.StringMaker; import com.navercorp.pinpoint.bootstrap.plugin.jdbc.UnKnownDatabaseInfo; import com.navercorp.pinpoint.common.trace.ServiceType; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * @author dawidmalina */ public class MariaDBJdbcUrlParser implements JdbcUrlParserV2 { // jdbc:(mysql|mariadb):[replication:|failover|loadbalance:|aurora:]//<hostDescription>[,<hostDescription>]/[database>] // jdbc:mariadb:loadbalance://10.22.33.44:3306,10.22.33.55:3306/MariaDB?characterEncoding=UTF-8 private static final String URL_PREFIX = "jdbc:mariadb:"; private static final String MYSQL_URL_PREFIX = "jdbc:mysql:"; private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); @Override public DatabaseInfo parse(String jdbcUrl) { if (jdbcUrl == null) { logger.info("jdbcUrl may not be null"); return UnKnownDatabaseInfo.INSTANCE; } Type type = Type.findType(jdbcUrl); if (type == null) { logger.info("jdbcUrl has invalid prefix.(url:{}, prefix:{}, {})", jdbcUrl, URL_PREFIX, MYSQL_URL_PREFIX); return UnKnownDatabaseInfo.INSTANCE; } DatabaseInfo result = null; try { result = parse0(jdbcUrl, type); } catch (Exception e) { logger.info("MaridDBJdbcUrl parse error. url: {}, Caused: {}", jdbcUrl, e.getMessage(), e); result = UnKnownDatabaseInfo.createUnknownDataBase(MariaDBConstants.MARIADB, MariaDBConstants.MARIADB_EXECUTE_QUERY, jdbcUrl); } return result; } private DatabaseInfo parse0(String url, Type type) { if (isLoadbalanceUrl(url, type)) { return parseLoadbalancedUrl(url, type); } return parseNormal(url, type); } private boolean isLoadbalanceUrl(String url, Type type) { String loadbalanceUrlPrefix = type.getLoadbalanceUrlPrefix(); return url.regionMatches(true, 0, loadbalanceUrlPrefix, 0, loadbalanceUrlPrefix.length()); } private DatabaseInfo parseLoadbalancedUrl(String url, Type type) { // jdbc:mariadb://1.2.3.4:5678/test_db StringMaker maker = new StringMaker(url); maker.after(type.getUrlPrefix()); // 1.2.3.4:5678 In case of replication driver could have multiple values // We have to consider mm db too. String host = maker.after("//").before('/').value(); // Decided not to cache regex. This is not invoked often so don't waste // memory. String[] parsedHost = host.split(","); List<String> hostList = Arrays.asList(parsedHost); String databaseId = maker.next().afterLast('/').before('?').value(); String normalizedUrl = maker.clear().before('?').value(); return new DefaultDatabaseInfo(MariaDBConstants.MARIADB, MariaDBConstants.MARIADB_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId); } private DatabaseInfo parseNormal(String url, Type type) { // jdbc:mariadb://1.2.3.4:5678/test_db StringMaker maker = new StringMaker(url); maker.after(type.getUrlPrefix()); // 1.2.3.4:5678 In case of replication driver could have multiple values // We have to consider mm db too. String host = maker.after("//").before('/').value(); List<String> hostList = new ArrayList<String>(1); hostList.add(host); // String port = maker.next().after(':').before('/').value(); String databaseId = maker.next().afterLast('/').before('?').value(); String normalizedUrl = maker.clear().before('?').value(); return new DefaultDatabaseInfo(MariaDBConstants.MARIADB, MariaDBConstants.MARIADB_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId); } @Override public ServiceType getServiceType() { return MariaDBConstants.MARIADB; } private static enum Type { MARIA(URL_PREFIX), MYSQL(MYSQL_URL_PREFIX); private final String urlPrefix; private final String loadbalanceUrlPrefix; Type(String urlPrefix) { this.urlPrefix = urlPrefix; this.loadbalanceUrlPrefix = urlPrefix + "loadbalance:"; } private String getUrlPrefix() { return urlPrefix; } private String getLoadbalanceUrlPrefix() { return urlPrefix + "loadbalance:"; } private static Type findType(String jdbcUrl) { for (Type type : Type.values()) { if (jdbcUrl.startsWith(type.urlPrefix)) { return type; } } return null; } } }