diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml
index a55ba6dc0..fe2f46125 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 40031986c..2984813a5 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 000000000..268979f91
--- /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 e31f70606..52e52baf8 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 000000000..ebc927d9a
--- /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 000000000..2e695928a
--- /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 000000000..94d76301e
--- /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 000000000..49aeb3ef8
--- /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 000000000..08353563e
--- /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 12205a7ce..898d02d6b 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -105,6 +105,7 @@
asynchttpclient-2.x-plugindbcp-2.x-pluginmssql-jtds-1.x-plugin
+ mssql-jdbc-pluginpom
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 f6a28bc4b..a57defd71 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 5234c4c5f..9f5b1a24e 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 000000000..154daaf54
--- /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 000000000..c0bef4d7c
--- /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 000000000..5e55a9404
--- /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 000000000..fa83eb9fd
--- /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 000000000..00263c8dd
--- /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 000000000..988b2f429
--- /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 000000000..fe08ca841
--- /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 000000000..f9a770c8e
--- /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 000000000..7faf1e438
--- /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 000000000..1c5bb0201
--- /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 000000000..98cc840aa
--- /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 000000000..9849ed5a8
--- /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 000000000..1f0e85a28
--- /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