From 813fc31bd2c6a243db781f4d1a8f7959510b7536 Mon Sep 17 00:00:00 2001 From: wallezhang Date: Mon, 11 Oct 2021 11:37:58 +0800 Subject: [PATCH] Feature add clickhouse jdbc plugin (#41) --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 1 + .../clickhouse-0.3.x-plugin/pom.xml | 61 +++ .../ClickHouseStatementMethodInterceptor.java | 58 +++ .../ClickHouseStatementTracingWrapper.java | 57 +++ .../InitConnectionMethodInterceptor.java | 63 +++ .../clickhouse/TracedClickHouseStatement.java | 407 ++++++++++++++++++ .../define/ConnectionInstrumentation.java | 125 ++++++ .../src/main/resources/skywalking-plugin.def | 17 + ...ckHouseStatementMethodInterceptorTest.java | 128 ++++++ .../InitConnectionMethodInterceptorTest.java | 72 ++++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 1 + .../clickhouse-0.3.x-scenario/bin/startup.sh | 24 ++ .../config/expectedData.yaml | 182 ++++++++ .../configuration.yml | 29 ++ .../clickhouse-0.3.x-scenario/pom.xml | 117 +++++ .../src/main/assembly/assembly.xml | 41 ++ .../apm/testcase/neo4j/Application.java | 50 +++ .../neo4j/controller/CaseController.java | 63 +++ .../src/main/resources/application.yaml | 23 + .../src/main/resources/log4j2.xml | 31 ++ .../support-version.list | 18 + 25 files changed, 1572 insertions(+) create mode 100755 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/TracedClickHouseStatement.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/define/ConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptorTest.java create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/Application.java create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/controller/CaseController.java create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/clickhouse-0.3.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 979946aa4..620d09a10 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -90,6 +90,7 @@ jobs: - oracle-scenario - druid-1.x-scenario - hikaricp-scenario + - clickhouse-0.3.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 666235544..eacd9f80c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,7 @@ Release Notes. * Format SpringMVC & Tomcat EntrySpan operation name to `METHOD:URI`. * Make `HTTP method` in the operation name according to runtime, rather than previous code-level definition, which used to have possibilities including multiple HTTP methods. * Fix the bug that httpasyncclient-4.x-plugin does not take effect every time. +* Add plugin to support ClickHouse JDBC driver. #### 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 35902c955..d84ae5403 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 @@ -215,4 +215,5 @@ 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"); } diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/pom.xml new file mode 100755 index 000000000..4b6cfdfbb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/pom.xml @@ -0,0 +1,61 @@ + + + + + apm-sdk-plugin + org.apache.skywalking + 8.8.0-SNAPSHOT + + 4.0.0 + + apm-clickhouse-0.3.x-plugin + jar + + clickhouse-0.3.x-plugin + + + UTF-8 + 0.3.1-patch + + + + + ru.yandex.clickhouse + clickhouse-jdbc + ${clickhouse.jdbc.version} + provided + + + org.apache.skywalking + apm-jdbc-commons + ${project.version} + provided + + + + + + + maven-deploy-plugin + + + + diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptor.java new file mode 100644 index 000000000..e706dbb66 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptor.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.plugin.jdbc.clickhouse; + +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; +import ru.yandex.clickhouse.ClickHouseConnectionImpl; +import ru.yandex.clickhouse.ClickHouseStatement; + +/** + * This interceptor is used to replace {@link org.apache.skywalking.apm.plugin.jdbc.JDBCStatementInterceptor}. + * Because return value type of {@link ClickHouseConnectionImpl#createStatement()} method is {@link + * ru.yandex.clickhouse.ClickHouseStatement} instead of {@link java.sql.Statement}. + */ +public class ClickHouseStatementMethodInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + final Object connectionInfo = objInst.getSkyWalkingDynamicField(); + if (connectionInfo == null) { + return ret; + } + + return new TracedClickHouseStatement((ClickHouseStatement) ret, (ConnectionInfo) connectionInfo); + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java new file mode 100644 index 000000000..eaa9e4569 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java @@ -0,0 +1,57 @@ +/* + * 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.clickhouse; + +import java.sql.SQLException; +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.plugin.jdbc.trace.ConnectionInfo; + +/** + * + */ +public class ClickHouseStatementTracingWrapper { + + public static T of(ConnectionInfo connectionInfo, String methodName, String sql, + SupplierWithException supplier) throws SQLException { + final AbstractSpan span = ContextManager.createExitSpan( + connectionInfo.getDBType() + "/JDBI/Statement/" + methodName, connectionInfo.getDatabasePeer()); + try { + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectionInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + span.setComponent(connectionInfo.getComponent()); + SpanLayer.asDB(span); + return supplier.get(); + } catch (SQLException e) { + span.log(e); + throw e; + } finally { + ContextManager.stopSpan(); + } + } + + public interface SupplierWithException { + + T get() throws SQLException; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptor.java new file mode 100644 index 000000000..dffda565d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptor.java @@ -0,0 +1,63 @@ +/* + * 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.clickhouse; + +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.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import ru.yandex.clickhouse.settings.ClickHouseProperties; + +/** + * Enhance {@link ru.yandex.clickhouse.ClickHouseConnectionImpl#initConnection(ClickHouseProperties)} method. + *

+ * ClickHouse JDBC Driver uses this method to simulate the action of connecting database in JDBC protocol. + * So this method is enhanced to prevent the generation of exit span of http type. + *

+ *

+ * This interceptor is used to replace {@link org.apache.skywalking.apm.plugin.jdbc.JDBCDriverInterceptor}. + *

+ */ +public class InitConnectionMethodInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + final Object properties = allArguments[0]; + ClickHouseProperties clickHouseProperties = (ClickHouseProperties) properties; + final ConnectionInfo connectionInfo = new ConnectionInfo(ComponentsDefine.CLICKHOUSE_JDBC_DRIVER, + "ClickHouse", clickHouseProperties.getHost(), clickHouseProperties.getPort(), + clickHouseProperties.getDatabase()); + objInst.setSkyWalkingDynamicField(connectionInfo); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/TracedClickHouseStatement.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/TracedClickHouseStatement.java new file mode 100644 index 000000000..1604dbad0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/TracedClickHouseStatement.java @@ -0,0 +1,407 @@ +/* + * 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.clickhouse; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.util.List; +import java.util.Map; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import ru.yandex.clickhouse.ClickHouseExternalData; +import ru.yandex.clickhouse.ClickHouseStatement; +import ru.yandex.clickhouse.Writer; +import ru.yandex.clickhouse.response.ClickHouseResponse; +import ru.yandex.clickhouse.response.ClickHouseResponseSummary; +import ru.yandex.clickhouse.settings.ClickHouseQueryParam; +import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream; +import ru.yandex.clickhouse.util.ClickHouseStreamCallback; + +/** + * The {@link ru.yandex.clickhouse.ClickHouseStatementImpl} instance wrapper. + */ +public class TracedClickHouseStatement implements ClickHouseStatement { + + private final ClickHouseStatement delegate; + private final ConnectionInfo connectionInfo; + + public TracedClickHouseStatement(ClickHouseStatement delegate, ConnectionInfo connectionInfo) { + this.delegate = delegate; + this.connectionInfo = connectionInfo; + } + + @Override + public ClickHouseResponse executeQueryClickhouseResponse(String sql) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseResponse", sql, + () -> delegate.executeQueryClickhouseResponse(sql)); + } + + @Override + public ClickHouseResponse executeQueryClickhouseResponse(String sql, + Map additionalDBParams) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseResponse", sql, + () -> delegate.executeQueryClickhouseResponse(sql, additionalDBParams)); + } + + @Override + public ClickHouseResponse executeQueryClickhouseResponse(String sql, + Map additionalDBParams, Map additionalRequestParams) + throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseResponse", sql, + () -> delegate.executeQueryClickhouseResponse(sql, additionalDBParams, additionalRequestParams)); + } + + @Override + public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseRowBinaryStream", sql, + () -> delegate.executeQueryClickhouseRowBinaryStream(sql)); + } + + @Override + public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, + Map additionalDBParams) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseRowBinaryStream", sql, + () -> delegate.executeQueryClickhouseRowBinaryStream(sql, additionalDBParams)); + } + + @Override + public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql, + Map additionalDBParams, Map additionalRequestParams) + throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseRowBinaryStream", sql, + () -> delegate.executeQueryClickhouseRowBinaryStream(sql, additionalDBParams, additionalRequestParams)); + } + + @Override + public ResultSet executeQuery(String sql, Map additionalDBParams) + throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql, + () -> delegate.executeQuery(sql, additionalDBParams)); + } + + @Override + public ResultSet executeQuery(String sql, Map additionalDBParams, + List externalData) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql, + () -> delegate.executeQuery(sql, additionalDBParams, externalData)); + } + + @Override + public ResultSet executeQuery(String sql, Map additionalDBParams, + List externalData, Map additionalRequestParams) + throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql, + () -> delegate.executeQuery(sql, additionalDBParams, externalData, additionalRequestParams)); + } + + @Override + public void sendStream(InputStream content, String table, Map additionalDBParams) + throws SQLException { + delegate.sendStream(content, table, additionalDBParams); + } + + @Override + public void sendStream(InputStream content, String table) throws SQLException { + delegate.sendStream(content, table); + } + + @Override + public void sendRowBinaryStream(String sql, Map additionalDBParams, + ClickHouseStreamCallback callback) throws SQLException { + sendRowBinaryStream(sql, additionalDBParams, callback); + } + + @Override + public void sendRowBinaryStream(String sql, ClickHouseStreamCallback callback) throws SQLException { + sendRowBinaryStream(sql, callback); + } + + @Override + public void sendNativeStream(String sql, Map additionalDBParams, + ClickHouseStreamCallback callback) throws SQLException { + sendNativeStream(sql, additionalDBParams, callback); + } + + @Override + public void sendNativeStream(String sql, ClickHouseStreamCallback callback) throws SQLException { + sendNativeStream(sql, callback); + } + + @Override + public void sendCSVStream(InputStream content, String table, Map additionalDBParams) + throws SQLException { + sendCSVStream(content, table, additionalDBParams); + } + + @Override + public void sendCSVStream(InputStream content, String table) throws SQLException { + sendCSVStream(content, table); + } + + @Override + public void sendStreamSQL(InputStream content, String sql, Map additionalDBParams) + throws SQLException { + sendStreamSQL(content, sql, additionalDBParams); + } + + @Override + public void sendStreamSQL(InputStream content, String sql) throws SQLException { + sendStreamSQL(content, sql); + } + + @Override + public Writer write() { + return delegate.write(); + } + + @Override + public ClickHouseResponseSummary getResponseSummary() { + return delegate.getResponseSummary(); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql, + () -> delegate.executeQuery(sql)); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeUpdate", sql, + () -> delegate.executeUpdate(sql)); + } + + @Override + public void close() throws SQLException { + delegate.close(); + } + + @Override + public int getMaxFieldSize() throws SQLException { + return delegate.getMaxFieldSize(); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + delegate.setMaxFieldSize(max); + } + + @Override + public int getMaxRows() throws SQLException { + return delegate.getMaxRows(); + } + + @Override + public void setMaxRows(int max) throws SQLException { + delegate.setMaxRows(max); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + delegate.setEscapeProcessing(enable); + } + + @Override + public int getQueryTimeout() throws SQLException { + return delegate.getQueryTimeout(); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + delegate.setQueryTimeout(seconds); + } + + @Override + public void cancel() throws SQLException { + delegate.cancel(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return delegate.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + delegate.clearWarnings(); + } + + @Override + public void setCursorName(String name) throws SQLException { + delegate.setCursorName(name); + } + + @Override + public boolean execute(String sql) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, () -> delegate.execute(sql)); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return delegate.getResultSet(); + } + + @Override + public int getUpdateCount() throws SQLException { + return delegate.getUpdateCount(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return delegate.getMoreResults(); + } + + @Override + public int getFetchDirection() throws SQLException { + return delegate.getFetchDirection(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + delegate.setFetchDirection(direction); + } + + @Override + public int getFetchSize() throws SQLException { + return delegate.getFetchSize(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + delegate.setFetchSize(rows); + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return delegate.getResultSetConcurrency(); + } + + @Override + public int getResultSetType() throws SQLException { + return delegate.getResultSetType(); + } + + @Override + public void addBatch(String sql) throws SQLException { + delegate.addBatch(sql); + } + + @Override + public void clearBatch() throws SQLException { + delegate.clearBatch(); + } + + @Override + public int[] executeBatch() throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeBatch", "", delegate::executeBatch); + } + + @Override + public Connection getConnection() throws SQLException { + return delegate.getConnection(); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return delegate.getMoreResults(current); + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return delegate.getGeneratedKeys(); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeUpdate", sql, + () -> delegate.executeUpdate(sql, autoGeneratedKeys)); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeUpdate", sql, + () -> delegate.executeUpdate(sql, columnIndexes)); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeUpdate", sql, + () -> delegate.executeUpdate(sql, columnNames)); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, + () -> delegate.execute(sql, autoGeneratedKeys)); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, + () -> delegate.execute(sql, columnIndexes)); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + return ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, + () -> delegate.execute(sql, columnNames)); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return delegate.getResultSetHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return delegate.isClosed(); + } + + @Override + public boolean isPoolable() throws SQLException { + return delegate.isPoolable(); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + delegate.setPoolable(poolable); + } + + @Override + public void closeOnCompletion() throws SQLException { + delegate.closeOnCompletion(); + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return delegate.isCloseOnCompletion(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return delegate.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return delegate.isWrapperFor(iface); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/define/ConnectionInstrumentation.java new file mode 100644 index 000000000..d7fd1f2b1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/define/ConnectionInstrumentation.java @@ -0,0 +1,125 @@ +/* + * 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.clickhouse.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 net.bytebuddy.matcher.ElementMatchers; +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; + +/** + * Intercept {@link ru.yandex.clickhouse.ClickHouseConnectionImpl} class. + */ +public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private final static String ENHANCE_CLASS = "ru.yandex.clickhouse.ClickHouseConnectionImpl"; + private final static String INIT_CONNECTION_METHOD_NAME = "initConnection"; + private final static String INIT_CONNECTION_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.InitConnectionMethodInterceptor"; + private final static String CREATE_CLICKHOUSE_STATEMENT_METHOD_NAME = "createClickHouseStatement"; + private final static String CREATE_CLICKHOUSE_STATEMENT_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.ClickHouseStatementMethodInterceptor"; + + @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).or( + named(CREATE_CLICKHOUSE_STATEMENT_METHOD_NAME)); + } + + @Override + public String getMethodsInterceptor() { + return CREATE_CLICKHOUSE_STATEMENT_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_STATEMENT_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return Constants.PREPARE_STATEMENT_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.CLOSE_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(INIT_CONNECTION_METHOD_NAME).and(ElementMatchers.takesArgument(0, + named("ru.yandex.clickhouse.settings.ClickHouseProperties"))); + } + + @Override + public String getMethodsInterceptor() { + return INIT_CONNECTION_METHOD_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..ea2f8f85b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,17 @@ +# 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. + +clickhouse-0.3.x=org.apache.skywalking.apm.plugin.jdbc.clickhouse.define.ConnectionInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptorTest.java new file mode 100644 index 000000000..594d38043 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementMethodInterceptorTest.java @@ -0,0 +1,128 @@ +/* + * 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.clickhouse; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.List; +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.trace.ConnectionInfo; +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; +import ru.yandex.clickhouse.ClickHouseStatementImpl; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class ClickHouseStatementMethodInterceptorTest { + + private final static String SQL = "SELECT 1"; + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private Object value; + + @Override + public Object getSkyWalkingDynamicField() { + return value; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.value = value; + } + }; + private final ClickHouseStatementMethodInterceptor interceptor = new ClickHouseStatementMethodInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @SegmentStoragePoint + private SegmentStorage segmentStorage; + @Mock + private ConnectionInfo connectionInfo; + @Mock + private ClickHouseStatementImpl clickHouseStatement; + + @Before + public void setUp() throws Exception { + // Mock connection info instance method + when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.CLICKHOUSE_JDBC_DRIVER); + when(connectionInfo.getDatabaseName()).thenReturn("default"); + when(connectionInfo.getDatabasePeer()).thenReturn("127.0.0.1:8123"); + when(connectionInfo.getDBType()).thenReturn("ClickHouse"); + + // Mock clickhouse statement instance method + when(clickHouseStatement.execute(SQL)).thenReturn(true); + } + + @Test + public void testWithoutConnectionInfo() throws Throwable { + final Object ret = interceptor.afterMethod(enhancedInstance, null, new Object[0], new Class[0], + clickHouseStatement); + + assertSame(clickHouseStatement, ret); + } + + @Test + public void test() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(connectionInfo); + final Object ret = interceptor.afterMethod(enhancedInstance, null, new Object[0], new Class[0], + clickHouseStatement); + + assertNotSame(clickHouseStatement, ret); + assertSame(TracedClickHouseStatement.class, ret.getClass()); + TracedClickHouseStatement statement = (TracedClickHouseStatement) ret; + final boolean result = statement.execute(SQL); + assertTrue(result); + + final List traceSegments = segmentStorage.getTraceSegments(); + assertThat(traceSegments.size(), is(1)); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertNotNull(spans); + assertThat(spans.size(), is(1)); + assertSpan(spans.get(0)); + } + + private void assertSpan(final AbstractTracingSpan span) throws JsonProcessingException { + SpanAssert.assertComponent(span, ComponentsDefine.CLICKHOUSE_JDBC_DRIVER); + SpanAssert.assertLayer(span, SpanLayer.DB); + SpanAssert.assertTagSize(span, 3); + SpanAssert.assertTag(span, 0, "sql"); + SpanAssert.assertTag(span, 1, "default"); + SpanAssert.assertTag(span, 2, SQL); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptorTest.java new file mode 100644 index 000000000..3c1324083 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/InitConnectionMethodInterceptorTest.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.clickhouse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.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.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import ru.yandex.clickhouse.settings.ClickHouseProperties; + +@RunWith(PowerMockRunner.class) +public class InitConnectionMethodInterceptorTest { + + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private Object value; + + @Override + public Object getSkyWalkingDynamicField() { + return value; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.value = value; + } + }; + private InitConnectionMethodInterceptor targetInterceptor; + @Mock + private ClickHouseProperties clickHouseProperties; + + @Before + public void setUp() throws Exception { + targetInterceptor = new InitConnectionMethodInterceptor(); + when(clickHouseProperties.getHost()).thenReturn("127.0.0.1"); + when(clickHouseProperties.getPort()).thenReturn(8123); + when(clickHouseProperties.getDatabase()).thenReturn("default"); + } + + @Test + public void test() throws Throwable { + targetInterceptor.beforeMethod(enhancedInstance, null, new Object[] {clickHouseProperties}, new Class[0], null); + final ConnectionInfo connectionInfo = (ConnectionInfo) enhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(connectionInfo); + assertEquals("ClickHouse-jdbc-driver", connectionInfo.getComponent().getName()); + assertEquals("127.0.0.1:8123", connectionInfo.getDatabasePeer()); + assertEquals("default", connectionInfo.getDatabaseName()); + assertEquals("ClickHouse", connectionInfo.getDBType()); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 3b85113b3..5dc1e0957 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -110,6 +110,7 @@ druid-1.x-plugin hikaricp-3.x-4.x-plugin httpclient-5.x-plugin + clickhouse-0.3.x-plugin pom diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index 81a09cc7b..16a65c46e 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -124,3 +124,4 @@ - jsonrpc4j - spring-cloud-gateway-3.x - neo4j-4.x +- clickhouse-0.3.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 296609953..025749037 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -41,6 +41,7 @@ metrics based on the tracing data. * [InfluxDB](https://github.com/influxdata/influxdb-java) 2.5 -> 2.17 * [Mssql-Jtds](https://github.com/milesibastos/jTDS) 1.x * [Mssql-jdbc](https://github.com/microsoft/mssql-jdbc) 6.x -> 8.x + * [ClickHouse-jdbc](https://github.com/ClickHouse/clickhouse-jdbc) 0.3.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/clickhouse-0.3.x-scenario/bin/startup.sh b/test/plugin/scenarios/clickhouse-0.3.x-scenario/bin/startup.sh new file mode 100644 index 000000000..b21584064 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/bin/startup.sh @@ -0,0 +1,24 @@ +#!/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} "-Dskywalking.plugin.neo4j.trace_cypher_parameters=true" ${home}/../libs/clickhouse-0.3.x-scenario.jar & diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/config/expectedData.yaml new file mode 100644 index 000000000..f940f6498 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/config/expectedData.yaml @@ -0,0 +1,182 @@ +# 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: clickhouse-0.3.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/clickhouse-scenario/case/healthCheck + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/clickhouse-scenario/case/healthCheck'} + - {key: http.method, value: HEAD} + - segmentId: not null + spans: + - operationName: ClickHouse/JDBI/Statement/executeQuery + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: 'select timezone(), version()'} + - operationName: ClickHouse/JDBI/Statement/executeQuery + operationId: 0 + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: SELECT * FROM clusters} + - operationName: ClickHouse/JDBI/Statement/execute + operationId: 0 + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: SELECT 1} + - operationName: ClickHouse/JDBI/Connection/close + operationId: 0 + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: ''} + - operationName: ClickHouse/JDBI/Statement/executeQuery + operationId: 0 + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: 'select timezone(), version()'} + - operationName: ClickHouse/JDBI/PreparedStatement/executeQuery + operationId: 0 + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: SELECT * FROM clusters} + - operationName: ClickHouse/JDBI/Statement/execute + operationId: 0 + parentSpanId: 0 + spanId: 7 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: SELECT 1} + - operationName: ClickHouse/JDBI/Connection/close + operationId: 0 + parentSpanId: 0 + spanId: 8 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 119 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: sql} + - {key: db.instance, value: system} + - {key: db.statement, value: ''} + - operationName: GET:/clickhouse-scenario/case/clickhouse-scenario + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/clickhouse-scenario/case/clickhouse-scenario'} + - {key: http.method, value: GET} +meterItems: [] diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/configuration.yml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/configuration.yml new file mode 100644 index 000000000..e3befa24d --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.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/clickhouse-scenario/case/clickhouse-scenario +healthCheck: http://localhost:8080/clickhouse-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - clickhouse-server +dependencies: + clickhouse-server: + image: yandex/clickhouse-server:21.8.8.29 + hostname: clickhouse-server + expose: + - 8123 \ No newline at end of file diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/pom.xml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/pom.xml new file mode 100644 index 000000000..ab2cec73c --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/pom.xml @@ -0,0 +1,117 @@ + + + + + org.apache.skywalking.apm.testcase + clickhouse-0.3.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 0.3.1-patch + 2.5.1 + + + skywalking-clickhouse-0.3.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 + + + + ru.yandex.clickhouse + clickhouse-jdbc + ${test.framework.version} + + + + + clickhouse-0.3.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/clickhouse-0.3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 000000000..89ea09240 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/clickhouse-0.3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/Application.java b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/Application.java new file mode 100644 index 000000000..b9e907f0d --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/Application.java @@ -0,0 +1,50 @@ +/* + * 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.neo4j; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import ru.yandex.clickhouse.ClickHouseDataSource; +import ru.yandex.clickhouse.settings.ClickHouseProperties; + +@SpringBootApplication +public class Application { + + @Value("${clickhouse.jdbc.url:jdbc:clickhouse://clickhouse-server:8123/system}") + private String clickhouseJdbcUrl; + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } + + @Bean + public ClickHouseDataSource dataSource() { + ClickHouseProperties properties = new ClickHouseProperties(); + properties.setClientName("Agent #1"); + properties.setSessionId("default-session-id"); + + return new ClickHouseDataSource(clickhouseJdbcUrl, properties); + } +} diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/controller/CaseController.java b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/controller/CaseController.java new file mode 100644 index 000000000..c561c56d8 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/neo4j/controller/CaseController.java @@ -0,0 +1,63 @@ +/* + * 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.neo4j.controller; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import javax.annotation.Resource; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import ru.yandex.clickhouse.ClickHouseConnection; +import ru.yandex.clickhouse.ClickHouseDataSource; +import ru.yandex.clickhouse.ClickHouseStatement; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final String SUCCESS = "Success"; + private static final String SQL = "SELECT * FROM clusters"; + @Resource + private ClickHouseDataSource dataSource; + + @RequestMapping("/clickhouse-scenario") + @ResponseBody + public String testcase() throws Exception { + try (ClickHouseConnection conn = dataSource.getConnection(); + ClickHouseStatement stmt = conn.createStatement(); + ResultSet ignored = stmt.executeQuery(SQL)) { + conn.isValid(3); + } + + try (final ClickHouseConnection connection = dataSource.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(SQL); + final ResultSet ignored = preparedStatement.executeQuery()) { + connection.isValid(3); + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/application.yaml new file mode 100644 index 000000000..f39d6f9d3 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.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: /clickhouse-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 000000000..b0336f413 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/clickhouse-0.3.x-scenario/support-version.list b/test/plugin/scenarios/clickhouse-0.3.x-scenario/support-version.list new file mode 100644 index 000000000..dd3def824 --- /dev/null +++ b/test/plugin/scenarios/clickhouse-0.3.x-scenario/support-version.list @@ -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. + +0.3.0 +0.3.1