diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml
index 620d09a10..da18a1243 100644
--- a/.github/workflows/plugins-test.3.yaml
+++ b/.github/workflows/plugins-test.3.yaml
@@ -91,6 +91,7 @@ jobs:
- druid-1.x-scenario
- hikaricp-scenario
- clickhouse-0.3.x-scenario
+ - kylin-jdbc-2.6.x-3.x-4.x-scenario
steps:
- uses: actions/checkout@v2
with:
diff --git a/CHANGES.md b/CHANGES.md
index a684394a5..28b587b1d 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -35,6 +35,7 @@ Release Notes.
* Fix the bug that httpasyncclient-4.x-plugin does not take effect every time.
* Add plugin to support ClickHouse JDBC driver.
* Fix version compatibility for JsonRPC4J plugin.
+* Add plugin to support Apache Kylin-jdbc 2.6.x 3.x 4.x
#### Documentation
diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index d84ae5403..d23cf2ef5 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -216,4 +216,6 @@ public class ComponentsDefine {
public static final OfficialComponent JACKSON = new OfficialComponent(118, "Jackson");
public static final OfficialComponent CLICKHOUSE_JDBC_DRIVER = new OfficialComponent(119, "ClickHouse-jdbc-driver");
+
+ public static final OfficialComponent APACHE_KYLIN_JDBC_DRIVER = new OfficialComponent(121, "apache-kylin-jdbc-driver");
}
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/KylinJdbcURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/KylinJdbcURLParser.java
new file mode 100644
index 000000000..d4e6ebb7e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/KylinJdbcURLParser.java
@@ -0,0 +1,27 @@
+/*
+ * 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.network.trace.component.ComponentsDefine;
+
+public class KylinJdbcURLParser extends MysqlURLParser {
+ public KylinJdbcURLParser(String url) {
+ super(url, "kylin", ComponentsDefine.APACHE_KYLIN_JDBC_DRIVER);
+ }
+}
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 52e52baf8..19b088679 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
@@ -33,6 +33,7 @@ public class URLParser {
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:";
+ private static final String KYLIN_JDBC_URK_PREFIX = "jdbc:kylin";
public static ConnectionInfo parser(String url) {
ConnectionURLParser parser = null;
@@ -51,6 +52,8 @@ public class URLParser {
parser = new MssqlJtdsURLParser(url);
} else if (lowerCaseUrl.startsWith(MSSQL_JDBC_URL_PREFIX)) {
parser = new MssqlJdbcURLParser(url);
+ } else if (lowerCaseUrl.startsWith(KYLIN_JDBC_URK_PREFIX)) {
+ parser = new KylinJdbcURLParser(url);
}
return parser.parse();
}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml
new file mode 100644
index 000000000..582f45527
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+ apm-sdk-plugin
+ org.apache.skywalking
+ 8.8.0-SNAPSHOT
+
+ 4.0.0
+
+ apm-kylin-jdbc-2.6.x-3.x-4.x-plugin
+ jar
+ kylin-jdbc-2.6.x-3.x-4.x-plugin
+ http://maven.apache.org
+
+
+ UTF-8
+ 2.6.3
+
+
+
+
+ org.apache.kylin
+ kylin-jdbc
+ ${kylin-jdbc}
+ provided
+
+
+ org.apache.skywalking
+ apm-jdbc-commons
+ ${project.version}
+ provided
+
+
+
+
+
+
+ maven-deploy-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/Constants.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/Constants.java
new file mode 100644
index 000000000..4fe0fffef
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/Constants.java
@@ -0,0 +1,25 @@
+/*
+ * 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.kylin;
+
+import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
+
+public class Constants {
+ public static final StringTag SQL_PARAMETERS = new StringTag("db.sql.parameters");
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptor.java
new file mode 100644
index 000000000..76aece9ce
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptor.java
@@ -0,0 +1,48 @@
+/*
+ * 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.kylin;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class CreateCallableStatementInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) {
+ if (ret instanceof EnhancedInstance) {
+ ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "CallableStatement"));
+ }
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptor.java
new file mode 100644
index 000000000..3a41dcaaa
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.kylin;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class CreatePreparedStatementInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) {
+ if (ret instanceof EnhancedInstance) {
+ ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "PreparedStatement"));
+ }
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptor.java
new file mode 100644
index 000000000..f461c28ae
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.kylin;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class CreateStatementInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) {
+ if (ret instanceof EnhancedInstance) {
+ ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), "", "Statement"));
+ }
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptor.java
new file mode 100644
index 000000000..cc02689ab
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptor.java
@@ -0,0 +1,94 @@
+/*
+ * 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.kylin;
+
+import static org.apache.skywalking.apm.plugin.jdbc.kylin.Constants.SQL_PARAMETERS;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig;
+import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder;
+import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class PreparedStatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, MethodInterceptResult result) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
+ if (connectInfo == null) {
+ return;
+ }
+ AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
+ .getStatementName()), connectInfo.getDatabasePeer());
+ Tags.DB_TYPE.set(span, "sql");
+ Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
+ Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(cacheObject.getSql()));
+ span.setComponent(connectInfo.getComponent());
+
+ if (JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS) {
+ final Object[] parameters = cacheObject.getParameters();
+ if (parameters != null && parameters.length > 0) {
+ int maxIndex = cacheObject.getMaxIndex();
+ SQL_PARAMETERS.set(span, getParameterString(parameters, maxIndex));
+ }
+ }
+
+ SpanLayer.asDB(span);
+ }
+
+ @Override
+ public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Object ret) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ if (cacheObject.getConnectionInfo() != null) {
+ ContextManager.stopSpan();
+ }
+ return ret;
+ }
+
+ @Override
+ public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ if (cacheObject.getConnectionInfo() != null) {
+ ContextManager.activeSpan().log(t);
+ }
+ }
+
+ private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {
+ return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
+ }
+
+ private String getParameterString(Object[] parameters, int maxIndex) {
+ return new PreparedStatementParameterBuilder()
+ .setParameters(parameters)
+ .setMaxIndex(maxIndex)
+ .build();
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/SetCatalogInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/SetCatalogInterceptor.java
new file mode 100644
index 000000000..f9ab430c0
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/SetCatalogInterceptor.java
@@ -0,0 +1,47 @@
+/*
+ * 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.kylin;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class SetCatalogInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) {
+ Object dynamicField = objInst.getSkyWalkingDynamicField();
+ if (dynamicField instanceof ConnectionInfo) {
+ ((ConnectionInfo) dynamicField).setDatabaseName(String.valueOf(allArguments[0]));
+ }
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) {
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptor.java
new file mode 100644
index 000000000..be6947a8c
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.kylin;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+
+public class StatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, MethodInterceptResult result) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ ConnectionInfo connectInfo = cacheObject.getConnectionInfo();
+ if (connectInfo != null) {
+ AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject
+ .getStatementName()), connectInfo.getDatabasePeer());
+ Tags.DB_TYPE.set(span, "sql");
+ Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
+ String sql = allArguments.length > 0 ? (String) allArguments[0] : "";
+ sql = SqlBodyUtil.limitSqlBodySize(sql);
+ Tags.DB_STATEMENT.set(span, sql);
+ span.setComponent(connectInfo.getComponent());
+ SpanLayer.asDB(span);
+ }
+ }
+
+ @Override
+ public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Object ret) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ if (cacheObject.getConnectionInfo() != null) {
+ ContextManager.stopSpan();
+ }
+ return ret;
+ }
+
+ @Override
+ public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField();
+ if (cacheObject.getConnectionInfo() != null) {
+ ContextManager.activeSpan().log(t);
+ }
+ }
+
+ private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) {
+ return connectionInfo.getDBType() + "/JDBI/" + statementName + "/" + methodName;
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/ConnectionInstrumentation.java
new file mode 100644
index 000000000..4313ef973
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/ConnectionInstrumentation.java
@@ -0,0 +1,139 @@
+/*
+ * 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.kylin.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+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.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.plugin.jdbc.define.Constants;
+
+public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String ENHANCE_CLASS = "org.apache.kylin.jdbc.KylinConnection";
+ private static final String CREATE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.kylin.CreateStatementInterceptor";
+ private static final String CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.kylin.CreatePreparedStatementInterceptor";
+ private static final String CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.kylin.CreateCallableStatementInterceptor";
+ private static final String SET_CATALOG_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.kylin.SetCatalogInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named(Constants.CREATE_STATEMENT_METHOD_NAME);
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return CREATE_STATEMENT_INTERCEPTOR_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named(Constants.PREPARE_STATEMENT_METHOD_NAME);
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return CREATE_PREPARED_STATEMENT_INTERCEPTOR_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 CREATE_CALLABLE_STATEMENT_INTERCEPTOR_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;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("setCatalog");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return SET_CATALOG_INTERCEPTOR_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/DriverInstrumentation.java
new file mode 100644
index 000000000..680f425b6
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/DriverInstrumentation.java
@@ -0,0 +1,37 @@
+/*
+ * 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.kylin.define;
+
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation;
+
+/**
+ * {@link DriverInstrumentation} presents that skywalking intercepts {@link org.apache.kylin.jdbc.Driver}.
+ */
+public class DriverInstrumentation extends AbstractDriverInstrumentation {
+
+ private static final String ENHANCE_CLASS = "org.apache.kylin.jdbc.Driver";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementIgnoredSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementIgnoredSetterInstrumentation.java
new file mode 100644
index 000000000..7f51de046
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementIgnoredSetterInstrumentation.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.plugin.jdbc.kylin.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation;
+
+public class PreparedStatementIgnoredSetterInstrumentation extends
+ org.apache.skywalking.apm.plugin.jdbc.kylin.define.PreparedStatementInstrumentation {
+
+ @Override
+ public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new PSSetterDefinitionOfJDBCInstrumentation(true)
+ };
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementInstrumentation.java
new file mode 100644
index 000000000..e2f57c84d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementInstrumentation.java
@@ -0,0 +1,72 @@
+/*
+ * 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.kylin.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch;
+
+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.agent.core.plugin.match.ClassMatch;
+
+public class PreparedStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String KYLIN_PREPARED_STATEMENT_CLASS = "org.apache.kylin.jdbc.KylinPreparedStatement";
+ private static final String PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.kylin.PreparedStatementExecuteMethodsInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byMultiClassMatch(
+ KYLIN_PREPARED_STATEMENT_CLASS
+ );
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("execute")
+ .or(named("executeQuery"))
+ .or(named("executeUpdate"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementNullSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementNullSetterInstrumentation.java
new file mode 100644
index 000000000..5a74d069e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementNullSetterInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * 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.kylin.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint;
+
+public class PreparedStatementNullSetterInstrumentation extends PreparedStatementInstrumentation {
+
+ @Override
+ public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint()
+ };
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementSetterInstrumentation.java
new file mode 100644
index 000000000..a6c9d9506
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/PreparedStatementSetterInstrumentation.java
@@ -0,0 +1,33 @@
+/*
+ * 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.kylin.define;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation;
+
+public class PreparedStatementSetterInstrumentation extends PreparedStatementInstrumentation {
+
+ @Override
+ public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new PSSetterDefinitionOfJDBCInstrumentation(false)
+ };
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/StatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/StatementInstrumentation.java
new file mode 100644
index 000000000..be5ef25ca
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/kylin/define/StatementInstrumentation.java
@@ -0,0 +1,71 @@
+/*
+ * 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.kylin.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+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.agent.core.plugin.match.ClassMatch;
+
+public class StatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String KYLIN_STATEMENT_CLASS_NAME = "org.apache.kylin.jdbc.KylinStatement";
+ private static final String STATEMENT_EXECUTE_METHODS_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.kylin.StatementExecuteMethodsInterceptor";
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("execute")
+ .or(named("executeQuery"))
+ .or(named("executeUpdate"))
+ .or(named("executeLargeUpdate"))
+ .or(named("executeBatch"))
+ .or(named("executeLargeBatch"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return STATEMENT_EXECUTE_METHODS_INTERCEPTOR;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName(KYLIN_STATEMENT_CLASS_NAME);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..a3fa6437d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/main/resources/skywalking-plugin.def
@@ -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.
+
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.DriverInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.ConnectionInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.StatementInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.PreparedStatementInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.PreparedStatementSetterInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.PreparedStatementNullSetterInstrumentation
+kylin-jdbc-2.6.x-3.x-4.x=org.apache.skywalking.apm.plugin.jdbc.kylin.define.PreparedStatementIgnoredSetterInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptorTest.java
new file mode 100644
index 000000000..f44f2c2e4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateCallableStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.kylin;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreateCallableStatementInterceptorTest {
+
+ private static final String SQL = "Select * from test";
+
+ private CreateCallableStatementInterceptor interceptor;
+
+ @Mock
+ private EnhancedInstance ret;
+
+ @Mock
+ private EnhancedInstance objectInstance;
+
+ @Mock
+ private ConnectionInfo connectionInfo;
+
+ @Before
+ public void setUp() {
+ interceptor = new CreateCallableStatementInterceptor();
+
+ when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+ }
+
+ @Test
+ public void testResultIsEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+ verify(ret).setSkyWalkingDynamicField(Matchers.any());
+ }
+
+ @Test
+ public void testResultIsNotEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+ verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptorTest.java
new file mode 100644
index 000000000..595eae0b8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreatePreparedStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.kylin;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreatePreparedStatementInterceptorTest {
+
+ private static final String SQL = "Select * from test";
+
+ private CreatePreparedStatementInterceptor interceptor;
+
+ @Mock
+ private EnhancedInstance ret;
+
+ @Mock
+ private EnhancedInstance objectInstance;
+
+ @Mock
+ private ConnectionInfo connectionInfo;
+
+ @Before
+ public void setUp() {
+ interceptor = new CreatePreparedStatementInterceptor();
+
+ when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+ }
+
+ @Test
+ public void testResultIsEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+ verify(ret).setSkyWalkingDynamicField(Matchers.any());
+ }
+
+ @Test
+ public void testResultIsNotEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+ verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptorTest.java
new file mode 100644
index 000000000..4d610f8ee
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/CreateStatementInterceptorTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.kylin;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CreateStatementInterceptorTest {
+
+ private static final String SQL = "Select * from test";
+
+ private CreateStatementInterceptor interceptor;
+
+ @Mock
+ private EnhancedInstance ret;
+
+ @Mock
+ private EnhancedInstance objectInstance;
+
+ @Mock
+ private ConnectionInfo connectionInfo;
+
+ @Before
+ public void setUp() {
+ interceptor = new CreateStatementInterceptor();
+
+ when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo);
+ }
+
+ @Test
+ public void testResultIsEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret);
+ verify(ret).setSkyWalkingDynamicField(Matchers.any());
+ }
+
+ @Test
+ public void testResultIsNotEnhanceInstance() {
+ interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object());
+ verify(ret, times(0)).setSkyWalkingDynamicField(Matchers.any());
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptorTest.java
new file mode 100644
index 000000000..1b12bbdca
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/PreparedStatementExecuteMethodsInterceptorTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.kylin;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementSetterInterceptor;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class PreparedStatementExecuteMethodsInterceptorTest {
+
+ private static final String SQL = "Select * from test where id = ?";
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ private PreparedStatementExecuteMethodsInterceptor serviceMethodInterceptor;
+
+ private JDBCPreparedStatementSetterInterceptor preparedStatementSetterInterceptor;
+
+ @Mock
+ private ConnectionInfo connectionInfo;
+ @Mock
+ private EnhancedInstance objectInstance;
+ @Mock
+ private Method method;
+ private StatementEnhanceInfos enhanceRequireCacheObject;
+
+ @Before
+ public void setUp() {
+ JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = true;
+ preparedStatementSetterInterceptor = new JDBCPreparedStatementSetterInterceptor();
+ serviceMethodInterceptor = new PreparedStatementExecuteMethodsInterceptor();
+
+ enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "PreparedStatement");
+ when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject);
+ when(method.getName()).thenReturn("executeQuery");
+ when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.APACHE_KYLIN_JDBC_DRIVER);
+ when(connectionInfo.getDBType()).thenReturn("kylin");
+ when(connectionInfo.getDatabaseName()).thenReturn("test");
+ when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306");
+ }
+
+ @After
+ public void clean() {
+ JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048;
+ JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = false;
+ }
+
+ @Test
+ public void testExecutePreparedStatement() throws Throwable {
+ preparedStatementSetterInterceptor.beforeMethod(
+ objectInstance, method, new Object[] {
+ 1,
+ "abcd"
+ }, null, null);
+ preparedStatementSetterInterceptor.beforeMethod(
+ objectInstance, method, new Object[] {
+ 2,
+ "efgh"
+ }, null, null);
+
+ serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[] {SQL}, null, null);
+ serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[] {SQL}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+ SpanAssert.assertLayer(span, SpanLayer.DB);
+ assertThat(span.getOperationName(), is("kylin/JDBI/PreparedStatement/"));
+ SpanAssert.assertTag(span, 0, "sql");
+ SpanAssert.assertTag(span, 1, "test");
+ SpanAssert.assertTag(span, 2, SQL);
+ SpanAssert.assertTag(span, 3, "[abcd,efgh]");
+ }
+
+ @Test
+ public void testExecutePreparedStatementWithLimitSqlBody() throws Throwable {
+ JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 10;
+
+ preparedStatementSetterInterceptor.beforeMethod(
+ objectInstance, method, new Object[] {
+ 1,
+ "abcd"
+ }, null, null);
+ preparedStatementSetterInterceptor.beforeMethod(
+ objectInstance, method, new Object[] {
+ 2,
+ "efgh"
+ }, null, null);
+
+ serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[] {SQL}, null, null);
+ serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[] {SQL}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+ SpanAssert.assertLayer(span, SpanLayer.DB);
+ assertThat(span.getOperationName(), is("kylin/JDBI/PreparedStatement/"));
+ SpanAssert.assertTag(span, 0, "sql");
+ SpanAssert.assertTag(span, 1, "test");
+ SpanAssert.assertTag(span, 2, "Select * f...");
+ SpanAssert.assertTag(span, 3, "[abcd,efgh]");
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptorTest.java
new file mode 100644
index 000000000..b0418a4f4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/kylin/StatementExecuteMethodsInterceptorTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.kylin;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+import java.lang.reflect.Method;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig;
+import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos;
+import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class StatementExecuteMethodsInterceptorTest {
+
+ private static final String SQL = "Select * from test";
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ private StatementExecuteMethodsInterceptor serviceMethodInterceptor;
+
+ @Mock
+ private ConnectionInfo connectionInfo;
+ @Mock
+ private EnhancedInstance objectInstance;
+ @Mock
+ private Method method;
+ private StatementEnhanceInfos enhanceRequireCacheObject;
+
+ @Before
+ public void setUp() {
+ serviceMethodInterceptor = new StatementExecuteMethodsInterceptor();
+
+ enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "CallableStatement");
+ when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject);
+ when(method.getName()).thenReturn("executeQuery");
+ when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.APACHE_KYLIN_JDBC_DRIVER);
+ when(connectionInfo.getDBType()).thenReturn("kylin");
+ when(connectionInfo.getDatabaseName()).thenReturn("test");
+ when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306");
+ }
+
+ @After
+ public void clean() {
+ JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048;
+ }
+
+ @Test
+ public void testExecuteStatement() {
+ serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null);
+ serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+ SpanAssert.assertLayer(span, SpanLayer.DB);
+ assertThat(span.getOperationName(), is("kylin/JDBI/CallableStatement/"));
+ SpanAssert.assertTag(span, 0, "sql");
+ SpanAssert.assertTag(span, 1, "test");
+ SpanAssert.assertTag(span, 2, SQL);
+ }
+
+ @Test
+ public void testExecuteStatementWithLimitSqlBody() {
+ JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 10;
+ serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null);
+ serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(segment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0);
+ SpanAssert.assertLayer(span, SpanLayer.DB);
+ assertThat(span.getOperationName(), is("kylin/JDBI/CallableStatement/"));
+ SpanAssert.assertTag(span, 0, "sql");
+ SpanAssert.assertTag(span, 1, "test");
+ SpanAssert.assertTag(span, 2, "Select * f...");
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 5dc1e0957..dfafd196f 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -111,6 +111,7 @@
hikaricp-3.x-4.x-pluginhttpclient-5.x-pluginclickhouse-0.3.x-plugin
+ kylin-jdbc-2.6.x-3.x-4.x-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 16a65c46e..e3aa29bd8 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -125,3 +125,4 @@
- spring-cloud-gateway-3.x
- neo4j-4.x
- clickhouse-0.3.x
+- kylin-jdbc-2.6.x-3.x-4.x
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 677b09d85..98d49a9d9 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -42,6 +42,7 @@ metrics based on the tracing data.
* [Mssql-Jtds](https://github.com/milesibastos/jTDS) 1.x
* [Mssql-jdbc](https://github.com/microsoft/mssql-jdbc) 6.x -> 8.x
* [ClickHouse-jdbc](https://github.com/ClickHouse/clickhouse-jdbc) 0.3.x
+ * [Apache-Kylin-Jdbc](https://github.com/apache/kylin.git) 2.6.x -> 3.x -> 4.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/kylin-jdbc-2.6.x-3.x-4.x-scenario/bin/startup.sh b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/bin/startup.sh
new file mode 100755
index 000000000..2c552ba86
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-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/kylin-jdbc-2.6.x-3.x-4.x-scenario.jar &
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/config/expectedData.yaml
new file mode 100644
index 000000000..7ecf5659f
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/config/expectedData.yaml
@@ -0,0 +1,82 @@
+# 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: kylin-jdbc-2.6.x-3.x-4.x-scenario
+ segmentSize: ge 1
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: kylin/JDBI/Statement/execute
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Database
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 121
+ isError: false
+ spanType: Exit
+ peer: kylin-server:7070
+ skipAnalysis: 'false'
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: learn_kylin}
+ - key: db.statement
+ value: "select * from KYLIN_ACCOUNT LIMIT 1"
+ - operationName: kylin/JDBI/PreparedStatement/executeQuery
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: Database
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 121
+ isError: false
+ spanType: Exit
+ peer: kylin-server:7070
+ skipAnalysis: 'false'
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: learn_kylin}
+ - {key: db.statement, value: "select * from KYLIN_ACCOUNT"}
+ - operationName: kylin/JDBI/Connection/close
+ parentSpanId: 0
+ spanId: 3
+ spanLayer: Database
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 121
+ isError: false
+ spanType: Exit
+ peer: kylin-server:7070
+ skipAnalysis: 'false'
+ tags:
+ - {key: db.type, value: sql}
+ - {key: db.instance, value: learn_kylin}
+ - {key: db.statement, value: ''}
+ - operationName: HEAD:/kylin-jdbc-2.6.x-3.x-4.x-scenario/case/healthCheck
+ parentSpanId: -1
+ spanId: 0
+ startTime: nq 0
+ endTime: nq 0
+ spanLayer: Http
+ isError: false
+ spanType: Entry
+ peer: ''
+ componentId: 1
+ tags:
+ - {key: url, value: 'http://localhost:8080/kylin-jdbc-2.6.x-3.x-4.x-scenario/case/healthCheck'}
+ - {key: http.method, value: HEAD}
+ logs: []
+ skipAnalysis: 'false'
\ No newline at end of file
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/configuration.yml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/configuration.yml
new file mode 100644
index 000000000..438de6440
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/configuration.yml
@@ -0,0 +1,29 @@
+# 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/kylin-jdbc-2.6.x-3.x-4.x-scenario/case/kylin-jdbc-2.6.x-3.x-4.x-scenario
+healthCheck: http://localhost:8080/kylin-jdbc-2.6.x-3.x-4.x-scenario/case/healthCheck
+startScript: ./bin/startup.sh
+environment:
+depends_on:
+ - kylin-server
+dependencies:
+ kylin-server:
+ image: apachekylin/apache-kylin-standalone:4.0.0
+ hostname: kylin-server
+ expose:
+ - "7070"
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/pom.xml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/pom.xml
new file mode 100644
index 000000000..255ac6ce2
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/pom.xml
@@ -0,0 +1,120 @@
+
+
+
+
+ org.apache.skywalking.apm.testcase
+ kylin-jdbc-2.6.x-3.x-4.x-scenario
+ 1.0.0
+ jar
+
+ 4.0.0
+
+
+ UTF-8
+ 1.8
+ 2.6.3
+ ${test.framework.version}
+ 2.1.6.RELEASE
+ 2.6.2
+ 4.3.8.RELEASE
+
+
+ skywalking-kylin-jdbc-2.6.x-3.x-4.x-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
+
+
+
+ org.apache.kylin
+ kylin-jdbc
+ ${test.framework.version}
+
+
+
+
+ kylin-jdbc-2.6.x-3.x-4.x-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/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 000000000..073f5c5eb
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ zip
+
+
+
+
+ ./bin
+ 0775
+
+
+
+
+
+ ${project.build.directory}/kylin-jdbc-2.6.x-3.x-4.x-scenario.jar
+ ./libs
+ 0775
+
+
+
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/Application.java b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/Application.java
new file mode 100644
index 000000000..218ea3071
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/Application.java
@@ -0,0 +1,39 @@
+/*
+ * 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.kylinjdbc;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ private static final Logger LOGGER = LogManager.getLogger(Application.class);
+
+ public static void main(String[] args) {
+ try {
+ SpringApplication.run(Application.class, args);
+ } catch (Exception ex) {
+ LOGGER.error("Application start error", ex);
+ throw ex;
+ }
+ }
+}
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/KylinJdbcConfig.java b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/KylinJdbcConfig.java
new file mode 100644
index 000000000..42c0aaa75
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/KylinJdbcConfig.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.kylinjdbc;
+
+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 KylinJdbcConfig {
+ private static final Logger LOGGER = LogManager.getLogger(KylinJdbcConfig.class);
+ private static String URL;
+ private static String USER_NAME;
+ private static String PASSWORD;
+
+ static {
+ InputStream inputStream = KylinJdbcConfig.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("kylin.url");
+ USER_NAME = properties.getProperty("kylin.username");
+ PASSWORD = properties.getProperty("kylin.password");
+ }
+
+ public static String getUrl() {
+ return URL;
+ }
+
+ public static String getUserName() {
+ return USER_NAME;
+ }
+
+ public static String getPassword() {
+ return PASSWORD;
+ }
+}
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/SQLExecutor.java b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/SQLExecutor.java
new file mode 100644
index 000000000..9e5749e42
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/SQLExecutor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.kylinjdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public class SQLExecutor implements AutoCloseable {
+
+ private static final Logger LOGGER = LogManager.getLogger(SQLExecutor.class);
+ private Connection connection;
+
+ public SQLExecutor() throws SQLException {
+ try {
+ Class.forName("org.apache.kylin.jdbc.Driver");
+ } catch (ClassNotFoundException ex) {
+ LOGGER.error(ex);
+ }
+ connection = DriverManager.getConnection(KylinJdbcConfig.getUrl(), KylinJdbcConfig.getUserName(),
+ KylinJdbcConfig.getPassword());
+ }
+
+ public void execute(String sql) throws SQLException {
+ Statement statement = connection.createStatement();
+ statement.execute(sql);
+ }
+
+ public void queryData(String sql, Integer id) throws SQLException {
+ PreparedStatement preparedStatement = connection.prepareStatement(sql);
+ preparedStatement.executeQuery();
+ }
+
+ 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/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/controller/CaseController.java b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/controller/CaseController.java
new file mode 100644
index 000000000..392cc99b4
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/kylinjdbc/controller/CaseController.java
@@ -0,0 +1,84 @@
+/*
+ * 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.kylinjdbc.controller;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.skywalking.apm.testcase.kylinjdbc.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 STATEMENT_QUERY_DATA_SQL = "select * from KYLIN_ACCOUNT LIMIT 1";
+ private static final String QUERY_DATA_SQL = "select * from KYLIN_ACCOUNT";
+
+ @RequestMapping("/kylin-jdbc-2.6.x-3.x-4.x-scenario")
+ @ResponseBody
+ public String testcase() throws Exception {
+ Thread.sleep(2000);
+ return SUCCESS;
+ }
+
+ @RequestMapping("/healthCheck")
+ @ResponseBody
+ public String healthCheck() throws Exception {
+ // NEED TO WAIT KYLIN SERVER READY
+ if (!telnet("kylin-server", 7070, 1000)) { //
+ Thread.sleep(5000); // WAIT UTIL CLIENT TIMEOUT
+ } else {
+ try (SQLExecutor sqlExecute = new SQLExecutor()) {
+ sqlExecute.execute(STATEMENT_QUERY_DATA_SQL);
+ sqlExecute.queryData(QUERY_DATA_SQL, 10);
+ } catch (Exception ex) {
+ LOGGER.error("Failed to execute sql.", ex);
+ throw ex;
+ }
+ }
+ return SUCCESS;
+ }
+
+ private boolean telnet(String hostname, int port, int timeout) {
+ Socket socket = new Socket();
+ boolean isConnected = false;
+ try {
+ socket.connect(new InetSocketAddress(hostname, port), timeout);
+ isConnected = socket.isConnected();
+ } catch (IOException e) {
+ LOGGER.warn("connect to kylin server failed");
+ } finally {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ LOGGER.warn("close failed");
+ }
+ }
+ return isConnected;
+ }
+}
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/application.yaml
new file mode 100644
index 000000000..9e8b92ca6
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-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: /kylin-jdbc-2.6.x-3.x-4.x-scenario
+logging:
+ config: classpath:log4j2.xml
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/jdbc.properties
new file mode 100644
index 000000000..fbfd40af6
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-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 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.
+kylin.url=jdbc:kylin://kylin-server:7070/learn_kylin
+kylin.username=ADMIN
+kylin.password=KYLIN
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..b5cda5ae8
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/support-version.list b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/support-version.list
new file mode 100644
index 000000000..81bfde478
--- /dev/null
+++ b/test/plugin/scenarios/kylin-jdbc-2.6.x-3.x-4.x-scenario/support-version.list
@@ -0,0 +1,21 @@
+# 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.
+
+2.6.6
+3.0.2
+3.1.2
+4.0.0
+