From d6c9926e9e7264a1aa5a05c82f269262ccb82016 Mon Sep 17 00:00:00 2001 From: zifeihan Date: Wed, 18 Nov 2020 15:48:18 +0800 Subject: [PATCH] Add the plugin for microsoft mssql-jdbc (#5856) --- .github/workflows/plugins-test.1.yaml | 1 + CHANGES.md | 3 +- .../parser/MssqlJdbcURLParser.java | 110 +++++++++++++ .../jdbc/connectionurl/parser/URLParser.java | 3 + .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 52 ++++++ .../AbstractConnectionInstrumentation.java | 150 ++++++++++++++++++ .../define/ConnectionInstrumentation.java | 35 ++++ .../jdbc/define/DriverInstrumentation.java | 36 +++++ .../src/main/resources/skywalking-plugin.def | 18 +++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 3 +- .../java-agent/Supported-list.md | 1 + .../mssql-jdbc-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 106 +++++++++++++ .../mssql-jdbc-scenario/configuration.yml | 32 ++++ .../scenarios/mssql-jdbc-scenario/pom.xml | 121 ++++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++ .../apm/testcase/mssql/Application.java | 34 ++++ .../apm/testcase/mssql/MssqlConfig.java | 58 +++++++ .../apm/testcase/mssql/SQLExecutor.java | 89 +++++++++++ .../mssql/controller/CaseController.java | 65 ++++++++ .../src/main/resources/application.yaml | 23 +++ .../src/main/resources/jdbc.properties | 18 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../mssql-jdbc-scenario/support-version.list | 23 +++ 25 files changed, 1072 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MssqlJdbcURLParser.java create mode 100644 apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/AbstractConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/ConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/DriverInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/configuration.yml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/pom.xml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/Application.java create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/MssqlConfig.java create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/SQLExecutor.java create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/controller/CaseController.java create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/jdbc.properties create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/mssql-jdbc-scenario/support-version.list diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml index a55ba6dc01..fe2f461255 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -61,6 +61,7 @@ jobs: - netty-socketio-scenario - postgresql-above9.4.1207-scenario - mssql-jtds-scenario + - mssql-jdbc-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 40031986c5..2984813a57 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,7 +18,8 @@ Release Notes. * Add the plugin for async-http-client 2.x * Fix NPE in the nutz plugin. * Provide Apache Commons DBCP 2.x plugin. -* Add the plugin for mssql-jtds 1.x plugin. +* Add the plugin for mssql-jtds 1.x. +* Add the plugin for mssql-jdbc 6.x -> 9.x. * Fix the default ignore mechanism isn't accurate enough bug. #### OAP-Backend diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MssqlJdbcURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MssqlJdbcURLParser.java new file mode 100644 index 0000000000..268979f91c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/MssqlJdbcURLParser.java @@ -0,0 +1,110 @@ +/* + * 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.connectionurl.parser; + +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.network.trace.component.OfficialComponent; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link MssqlJdbcURLParser} parse connection url of mssql. + */ +public class MssqlJdbcURLParser extends AbstractURLParser { + + private static final int DEFAULT_PORT = 1433; + private String dbType = "Mssql"; + private static final String DATABASE_NAME_PROPERTY = "databaseName="; + private OfficialComponent component = ComponentsDefine.MSSQL_JDBC_DRIVER; + private static ILog LOGGER = LogManager.getLogger(MssqlJdbcURLParser.class); + + public MssqlJdbcURLParser(String url) { + super(url); + } + + @Override + 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(); + if (hostsLocation == null) { + return ""; + } + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); + } + + protected URLLocation fetchDatabaseNameIndexRange(int startSize) { + return fetchDatabaseNameIndexRange(); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + String urlTemp = url.toLowerCase(); + int databaseStartTag = urlTemp.indexOf(DATABASE_NAME_PROPERTY.toLowerCase()); + int databaseEndTag = url.indexOf(";", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + DATABASE_NAME_PROPERTY.length(), databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + try { + URLLocation location = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(location.startIndex(), location.endIndex()); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host).append(":").append(DEFAULT_PORT).append(","); + } else { + sb.append(host).append(","); + } + } + return new ConnectionInfo( + component, dbType, sb.substring(0, sb.length() - 1), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo( + component, dbType, hostAndPort[0], Integer.valueOf(hostAndPort[1]), + fetchDatabaseNameFromURL(location.endIndex()) + ); + } else { + return new ConnectionInfo( + component, dbType, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location + .endIndex())); + } + } + } catch (Exception e) { + LOGGER.error(e, "parse mssql connection info error, url:{}", url); + return new ConnectionInfo(component, dbType, url, "UNKNOWN"); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java index e31f70606b..52e52baf88 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java @@ -32,6 +32,7 @@ public class URLParser { private static final String POSTGRESQL_JDBC_URL_PREFIX = "jdbc:postgresql"; private static final String MARIADB_JDBC_URL_PREFIX = "jdbc:mariadb"; private static final String MSSQL_JTDS_URL_PREFIX = "jdbc:jtds:sqlserver:"; + private static final String MSSQL_JDBC_URL_PREFIX = "jdbc:sqlserver:"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -48,6 +49,8 @@ public class URLParser { parser = new MariadbURLParser(url); } else if (lowerCaseUrl.startsWith(MSSQL_JTDS_URL_PREFIX)) { parser = new MssqlJtdsURLParser(url); + } else if (lowerCaseUrl.startsWith(MSSQL_JDBC_URL_PREFIX)) { + parser = new MssqlJdbcURLParser(url); } return parser.parse(); } diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml new file mode 100644 index 0000000000..ebc927d9a3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -0,0 +1,52 @@ + + + + + apm-sdk-plugin + org.apache.skywalking + 8.3.0-SNAPSHOT + + 4.0.0 + + apm-mssql-jdbc-plugin + jar + + mssql-jdbc-plugin + http://maven.apache.org + + + 7.0.0.jre8 + + + + + org.apache.skywalking + apm-jdbc-commons + ${project.version} + provided + + + + com.microsoft.sqlserver + mssql-jdbc + ${mssql-jdbc.version} + provided + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/AbstractConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/AbstractConnectionInstrumentation.java new file mode 100644 index 0000000000..2e695928ab --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/AbstractConnectionInstrumentation.java @@ -0,0 +1,150 @@ +/* + * 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.mssql.jdbc.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.plugin.jdbc.define.Constants; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +/** + * {@link AbstractConnectionInstrumentation} define how to enhance the following methods that the class which extend + * {@link java.sql.Connection}. + *

+ * 1. Enhance prepareStatement by org.apache.skywalking.apm.plugin.jdbc.define.JDBCPrepareStatementInterceptor + * 2. Enhance prepareCall by org.apache.skywalking.apm.plugin.jdbc.define.JDBCPrepareCallInterceptor + * 3. Enhance createStatement by org.apache.skywalking.apm.plugin.jdbc.define.JDBCStatementInterceptor + * 4. Enhance commit, rollback, close, releaseSavepoint by org.apache.skywalking.apm.plugin.jdbc.define.ConnectionServiceMethodInterceptor + */ +public abstract class AbstractConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_STATEMENT_METHOD_NAME).and(takesArguments(1)); + } + + @Override + public String getMethodsInterceptor() { + return Constants.PREPARE_STATEMENT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_STATEMENT_METHOD_NAME).and(takesArguments(3)); + } + + @Override + public String getMethodsInterceptor() { + return Constants.PREPARE_STATEMENT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_STATEMENT_METHOD_NAME).and(takesArguments(4)); + } + + @Override + public String getMethodsInterceptor() { + return Constants.PREPARE_STATEMENT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_CALL_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return Constants.PREPARE_CALL_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.CREATE_STATEMENT_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return Constants.CREATE_STATEMENT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.COMMIT_METHOD_NAME).or(named(Constants.ROLLBACK_METHOD_NAME)) + .or(named(Constants.CLOSE_METHOD_NAME)) + .or(named(Constants.RELEASE_SAVE_POINT_METHOD_NAME)); + } + + @Override + public String getMethodsInterceptor() { + return Constants.SERVICE_METHOD_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/ConnectionInstrumentation.java new file mode 100644 index 0000000000..94d76301e2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/ConnectionInstrumentation.java @@ -0,0 +1,35 @@ +/* + * 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.mssql.jdbc.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ConnectionInstrumentation} presents that skywalking intercepts {@link com.microsoft.sqlserver.jdbc.SQLServerConnection}. + */ +public class ConnectionInstrumentation extends AbstractConnectionInstrumentation { + public static final String ENHANCE_SQL_SERVER_CONNECTION_CLASS = "com.microsoft.sqlserver.jdbc.SQLServerConnection"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_SQL_SERVER_CONNECTION_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/DriverInstrumentation.java new file mode 100644 index 0000000000..49aeb3ef83 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/java/org/apache/skywalking/apm/plugin/mssql/jdbc/define/DriverInstrumentation.java @@ -0,0 +1,36 @@ +/* + * 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.mssql.jdbc.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link DriverInstrumentation} presents that skywalking intercepts {@link com.microsoft.sqlserver.jdbc.SQLServerDriver}. + */ +public class DriverInstrumentation extends AbstractDriverInstrumentation { + private static final String ENHANCE_CLASS = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..08353563e7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# 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. + +mssql-jdbc=org.apache.skywalking.apm.plugin.mssql.jdbc.define.DriverInstrumentation +mssql-jdbc=org.apache.skywalking.apm.plugin.mssql.jdbc.define.ConnectionInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 12205a7ce2..898d02d6bb 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -105,6 +105,7 @@ asynchttpclient-2.x-plugin dbcp-2.x-plugin mssql-jtds-1.x-plugin + mssql-jdbc-plugin pom diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index f6a28bc4b9..a57defd71c 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -109,4 +109,5 @@ - vertx-core-3.x - xxl-job-2.x - zookeeper-3.4.x -- mssql-jtds-1.x \ No newline at end of file +- mssql-jtds-1.x +- mssql-jdbc \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 5234c4c5fd..9f5b1a24e4 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -40,6 +40,7 @@ metrics based on the tracing data. * Mariadb Driver 2.x, 1.8 * [InfluxDB](https://github.com/influxdata/influxdb-java) 2.5 -> 2.17 * [Mssql-Jtds](https://github.com/milesibastos/jTDS) 1.x + * [Mssql-jdbc](https://github.com/microsoft/mssql-jdbc) 6.x -> 8.x * RPC Frameworks * [Dubbo](https://github.com/alibaba/dubbo) 2.5.4 -> 2.6.0 * [Dubbox](https://github.com/dangdangdotcom/dubbox) 2.8.4 diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/bin/startup.sh b/test/plugin/scenarios/mssql-jdbc-scenario/bin/startup.sh new file mode 100644 index 0000000000..154daaf54a --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# 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. + +home="$(cd "$(dirname $0)"; pwd)" + +java -jar ${agent_opts} ${home}/../libs/mssql-jdbc-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/config/expectedData.yaml b/test/plugin/scenarios/mssql-jdbc-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..c0bef4d7cc --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/config/expectedData.yaml @@ -0,0 +1,106 @@ +# 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. +segmentItems: + - serviceName: mssql-jdbc-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: Mssql/JDBI/PreparedStatement/execute + operationId: eq 0 + parentSpanId: 0 + spanId: 1 + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: tempdb} + - key: db.statement + value: "CREATE TABLE test_007(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ + \ NOT NULL)" + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 104 + peer: mssql-server:1433 + skipAnalysis: 'false' + - operationName: Mssql/JDBI/PreparedStatement/execute + operationId: eq 0 + parentSpanId: 0 + spanId: 2 + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: tempdb} + - {key: db.statement, value: 'INSERT INTO test_007(id, value) VALUES(?,?)'} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 104 + peer: mssql-server:1433 + skipAnalysis: 'false' + - operationName: Mssql/JDBI/Statement/execute + operationId: eq 0 + parentSpanId: 0 + spanId: 3 + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: tempdb} + - {key: db.statement, value: DROP table test_007} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 104 + peer: mssql-server:1433 + skipAnalysis: 'false' + - operationName: Mssql/JDBI/Connection/close + operationId: eq 0 + parentSpanId: 0 + spanId: 4 + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: tempdb} + - {key: db.statement, value: ''} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 104 + peer: mssql-server:1433 + skipAnalysis: 'false' + - operationName: /mssql-jdbc-scenario/case/mssql-jdbc-scenario + operationId: eq 0 + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + spanLayer: Http + isError: false + spanType: Entry + componentId: 1 + tags: + - {key: url, value: 'http://localhost:8080/mssql-jdbc-scenario/case/mssql-jdbc-scenario'} + - {key: http.method, value: GET} + logs: [] + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/configuration.yml b/test/plugin/scenarios/mssql-jdbc-scenario/configuration.yml new file mode 100644 index 0000000000..5e55a94046 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/configuration.yml @@ -0,0 +1,32 @@ +# 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. + +type: jvm +entryService: http://localhost:8080/mssql-jdbc-scenario/case/mssql-jdbc-scenario +healthCheck: http://localhost:8080/mssql-jdbc-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - mssql-server +dependencies: + mssql-server: + image: microsoft/mssql-server-linux + hostname: mssql-server + expose: + - "1433" + environment: + - SA_PASSWORD=yourStrong(!)Password + - ACCEPT_EULA=Y \ No newline at end of file diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/pom.xml b/test/plugin/scenarios/mssql-jdbc-scenario/pom.xml new file mode 100644 index 0000000000..fa83eb9fd3 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/pom.xml @@ -0,0 +1,121 @@ + + + + + org.apache.skywalking.apm.testcase + mssql-jdbc-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + + 7.0.0.jre8 + ${test.framework.version} + + 2.1.6.RELEASE + + + skywalking-mssql-jdbc-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot-version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + com.microsoft.sqlserver + mssql-jdbc + ${test.framework.version} + provided + + + + + mssql-jdbc-scenario + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + maven-compiler-plugin + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..00263c8ddc --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/mssql-jdbc-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/Application.java b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/Application.java new file mode 100644 index 0000000000..988b2f4296 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.mssql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/MssqlConfig.java b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/MssqlConfig.java new file mode 100644 index 0000000000..fe08ca8415 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/MssqlConfig.java @@ -0,0 +1,58 @@ +/* + * 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.testcase.mssql; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MssqlConfig { + private static final Logger LOGGER = LogManager.getLogger(MssqlConfig.class); + private static String url; + private static String userName; + private static String password; + + static { + InputStream inputStream = MssqlConfig.class.getClassLoader().getResourceAsStream("jdbc.properties"); + Properties properties = new Properties(); + try { + properties.load(inputStream); + } catch (IOException e) { + LOGGER.error("Failed to load config", e); + } + + url = properties.getProperty("mssql.url"); + userName = properties.getProperty("mssql.username"); + password = properties.getProperty("mssql.password"); + } + + public static String getUrl() { + return url; + } + + public static String getUserName() { + return userName; + } + + public static String getPassword() { + return password; + } +} diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/SQLExecutor.java b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/SQLExecutor.java new file mode 100644 index 0000000000..f9a770c8e3 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/SQLExecutor.java @@ -0,0 +1,89 @@ +/* + * 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.testcase.mssql; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +public class SQLExecutor implements AutoCloseable { + private Connection connection; + + public SQLExecutor() throws SQLException { + try { + Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + connection = DriverManager.getConnection( + MssqlConfig.getUrl(), MssqlConfig.getUserName(), MssqlConfig.getPassword()); + } + + public void createTable(String sql) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void insertData(String sql, String id, String value) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.setString(1, id); + preparedStatement.setString(2, value); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void dropTable(String sql) throws SQLException { + executeStatement(sql); + } + + public void createProcedure(String sql) throws SQLException { + executeStatement(sql); + } + + public void dropProcedure(String sql) throws SQLException { + executeStatement(sql); + } + + public void callProcedure(String sql, String id) throws SQLException { + PreparedStatement preparedStatement = connection.prepareCall(sql); + preparedStatement.setString(1, id); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void executeStatement(String sql) throws SQLException { + Statement preparedStatement = connection.createStatement(); + preparedStatement.execute(sql); + preparedStatement.close(); + } + + public void closeConnection() throws SQLException { + if (this.connection != null) { + this.connection.close(); + } + } + + @Override + public void close() throws Exception { + closeConnection(); + } +} diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/controller/CaseController.java b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/controller/CaseController.java new file mode 100644 index 0000000000..7faf1e4387 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/java/org/apache/skywalking/apm/testcase/mssql/controller/CaseController.java @@ -0,0 +1,65 @@ +/* + * 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.testcase.mssql.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.mssql.SQLExecutor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_007(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(1) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_007(id, value) VALUES(?,?)"; + private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_007 WHERE id=?"; + private static final String DELETE_DATA_SQL = "DELETE FROM test_007 WHERE id=?"; + private static final String DROP_TABLE_SQL = "DROP table test_007"; + + @RequestMapping("/mssql-jdbc-scenario") + @ResponseBody + public String testcase() throws Exception { + try (SQLExecutor sqlExecute = new SQLExecutor()) { + sqlExecute.createTable(CREATE_TABLE_SQL); + sqlExecute.insertData(INSERT_DATA_SQL, "1", "1"); + sqlExecute.dropTable(DROP_TABLE_SQL); + } catch (Exception e) { + LOGGER.error("Failed to execute sql.", e); + throw e; + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + try (SQLExecutor sqlExecutor = new SQLExecutor()) { + // ignore + } + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..1c5bb0201a --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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. +# +# +server: + port: 8080 + servlet: + context-path: /mssql-jdbc-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/jdbc.properties new file mode 100644 index 0000000000..98cc840aa4 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/jdbc.properties @@ -0,0 +1,18 @@ +# 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 +# "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. +mssql.url=jdbc:sqlserver://mssql-server:1433;Databasename=tempdb +mssql.username=SA +mssql.password=yourStrong(!)Password diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/mssql-jdbc-scenario/support-version.list b/test/plugin/scenarios/mssql-jdbc-scenario/support-version.list new file mode 100644 index 0000000000..1f0e85a284 --- /dev/null +++ b/test/plugin/scenarios/mssql-jdbc-scenario/support-version.list @@ -0,0 +1,23 @@ +# 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 +# "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. + +6.2.2.jre8 +6.4.0.jre8 +7.0.0.jre8 +7.2.2.jre8 +7.4.1.jre8 +8.2.2.jre8 +8.4.0.jre8 \ No newline at end of file -- GitLab