From f6346b0a7e8c67780752b6b00aa7f6298c97aacc Mon Sep 17 00:00:00 2001 From: IluckySi <1151262684@qq.com> Date: Tue, 9 Apr 2019 19:18:21 +0800 Subject: [PATCH] Support ClickHouse-JDBC-0.1.x --- .../trace/component/ComponentsDefine.java | 5 +- .../clickhouse-0.1.x-plugin/pom.xml | 54 +++++++++ .../CreateCallableStatementInterceptor.java | 48 ++++++++ .../CreatePreparedStatmentInterceptor.java | 49 ++++++++ .../v01/CreateStatementInterceptor.java | 50 ++++++++ .../v01/StatementExecuteInterceptor.java | 86 +++++++++++++ .../ClickHouseConnectionInstrumentation.java | 113 ++++++++++++++++++ .../ClickHouseDriverInstrumentation.java | 38 ++++++ .../ClickHouseStatementInstrumentation.java | 71 +++++++++++ .../src/main/resources/skywalking-plugin.def | 21 ++++ .../parser/ClickHouseURLParser.java | 99 +++++++++++++++ .../jdbc/connectionurl/parser/URLParser.java | 3 + apm-sniffer/apm-sdk-plugin/pom.xml | 1 + 13 files changed, 637 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateCallableStatementInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreatePreparedStatmentInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateStatementInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/StatementExecuteInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseDriverInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseStatementInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/ClickHouseURLParser.java 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 ce9cb5f626cc..cdb406f72c69 100644 --- 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 @@ -114,6 +114,8 @@ public class ComponentsDefine { public static final OfficialComponent ZOOKEEPER = new OfficialComponent(58, "Zookeeper"); + public static final OfficialComponent CLICKHOUSE_JDBC = new OfficialComponent(59, "clickhouse-jdbc"); + private static ComponentsDefine INSTANCE = new ComponentsDefine(); private String[] components; @@ -123,7 +125,7 @@ public static ComponentsDefine getInstance() { } public ComponentsDefine() { - components = new String[59]; + components = new String[60]; addComponent(TOMCAT); addComponent(HTTPCLIENT); addComponent(DUBBO); @@ -167,6 +169,7 @@ public ComponentsDefine() { addComponent(REDISSON); addComponent(LETTUCE); addComponent(ZOOKEEPER); + addComponent(CLICKHOUSE_JDBC); } private void addComponent(OfficialComponent component) { diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/pom.xml new file mode 100644 index 000000000000..3f8ac41cea61 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/pom.xml @@ -0,0 +1,54 @@ + + + + + + apm-sdk-plugin + org.apache.skywalking + 6.1.0-SNAPSHOT + + 4.0.0 + + apm-clickhouse-0.1.x-plugin + + + UTF-8 + 0.1.52 + + + + + org.apache.skywalking + apm-jdbc-commons + 6.1.0-SNAPSHOT + + + + ru.yandex.clickhouse + clickhouse-jdbc + ${clickhouse.jdbc.version} + + + + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateCallableStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateCallableStatementInterceptor.java new file mode 100644 index 000000000000..028757e7eb3c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/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.clickhouse.v01; + +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) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + 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/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreatePreparedStatmentInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreatePreparedStatmentInterceptor.java new file mode 100644 index 000000000000..d74eb763f8e4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreatePreparedStatmentInterceptor.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.clickhouse.v01; + +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 CreatePreparedStatmentInterceptor 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 { + 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/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateStatementInterceptor.java new file mode 100644 index 000000000000..524127e0ce90 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/CreateStatementInterceptor.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.plugin.jdbc.clickhouse.v01; + +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) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + 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/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/StatementExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/StatementExecuteInterceptor.java new file mode 100644 index 000000000000..8c13034b8e26 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/StatementExecuteInterceptor.java @@ -0,0 +1,86 @@ +/* + * 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.v01; + +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.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +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.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class StatementExecuteInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ILog logger = LogManager.getLogger(StatementExecuteInterceptor.class); + + @Override + public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField(); + if (cacheObject != null) { + 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()); + Tags.DB_STATEMENT.set(span, (String)allArguments[0]); + span.setComponent(ComponentsDefine.CLICKHOUSE_JDBC); + SpanLayer.asDB(span); + } + } + + } + + @Override + public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, + Object ret) throws Throwable { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos)objInst.getSkyWalkingDynamicField(); + if (cacheObject != null) { + ConnectionInfo connectInfo = cacheObject.getConnectionInfo(); + if (connectInfo != 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 != null) { + ConnectionInfo connectInfo = cacheObject.getConnectionInfo(); + if (connectInfo != null) { + ContextManager.activeSpan().errorOccurred().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/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseConnectionInstrumentation.java new file mode 100644 index 000000000000..ed7d3121049c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseConnectionInstrumentation.java @@ -0,0 +1,113 @@ +/* + * 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.v01.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link ClickHouseConnectionInstrumentation} intercepts {@link ru.yandex.clickhouse.ClickHouseConnection} + * + * @author IluckySi + */ +public class ClickHouseConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String ENHANCE_CLASS = "ru.yandex.clickhouse.ClickHouseConnectionImpl"; + public static final String CREATE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.CreateStatementInterceptor"; + public static final String CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.CreatePreparedStatmentInterceptor"; + public static final String CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.CreateCallableStatementInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override public ElementMatcher getMethodsMatcher() { + return named(org.apache.skywalking.apm.plugin.jdbc.define.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(org.apache.skywalking.apm.plugin.jdbc.define.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(org.apache.skywalking.apm.plugin.jdbc.define.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(org.apache.skywalking.apm.plugin.jdbc.define.Constants.COMMIT_METHOD_NAME) + .or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.ROLLBACK_METHOD_NAME)) + .or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.CLOSE_METHOD_NAME)) + .or(named(org.apache.skywalking.apm.plugin.jdbc.define.Constants.RELEASE_SAVE_POINT_METHOD_NAME)); + } + + @Override public String getMethodsInterceptor() { + return org.apache.skywalking.apm.plugin.jdbc.define.Constants.SERVICE_METHOD_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseDriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseDriverInstrumentation.java new file mode 100644 index 000000000000..3d3d5a07f234 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseDriverInstrumentation.java @@ -0,0 +1,38 @@ +/* + * 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.v01.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; +import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ClickHouseDriverInstrumentation} intercepts {@link ru.yandex.clickhouse.ClickHouseDriver}. + * + * @author IluckySi + */ +public class ClickHouseDriverInstrumentation extends AbstractDriverInstrumentation { + + public static final String ENHANCE_CLASS = "ru.yandex.clickhouse.ClickHouseDriver"; + + protected NameMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseStatementInstrumentation.java new file mode 100644 index 000000000000..52e93fafaa65 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v01/define/ClickHouseStatementInstrumentation.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.clickhouse.v01.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link ClickHouseStatementInstrumentation } intercepts {@link ru.yandex.clickhouse.ClickHouseStatementImpl} + * + * @author IluckySi + */ +public class ClickHouseStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String ENHANCE_CLASS = "ru.yandex.clickhouse.ClickHouseStatementImpl"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.StatementExecuteInterceptor"; + + @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("executeQuery") + .or(named("executeQueryClickhouseResponse")) + .or(named("execute")) + .or(named("executeUpdate")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000000..a7523dacc996 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.1.x-plugin/src/main/resources/skywalking-plugin.def @@ -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. + +clickhouse-0.1.x=org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.define.ClickHouseDriverInstrumentation +clickhouse-0.1.x=org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.define.ClickHouseConnectionInstrumentation +clickhouse-0.1.x=org.apache.skywalking.apm.plugin.jdbc.clickhouse.v01.define.ClickHouseStatementInstrumentation + + diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/ClickHouseURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/ClickHouseURLParser.java new file mode 100644 index 000000000000..4ee0c5e9f477 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/ClickHouseURLParser.java @@ -0,0 +1,99 @@ +/* + * 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; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class ClickHouseURLParser extends AbstractURLParser { + + private static final int DEFAULT_PORT = 8123; + private static final String DB_TYPE = "ClickHouse"; + + public ClickHouseURLParser(String url) { + super(url); + } + + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = url.indexOf("?", hostLabelStartIndex + 2); + } + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); + } + + protected String fetchDatabaseNameFromURL(int startSize) { + URLLocation hostsLocation = fetchDatabaseNameIndexRange(startSize); + if (hostsLocation == null) { + return ""; + } + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); + } + + protected URLLocation fetchDatabaseNameIndexRange(int startSize) { + int databaseStartTag = url.indexOf("/", startSize); + if (databaseStartTag == -1) { + return null; + } + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + URLLocation location = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(location.startIndex(), location.endIndex()); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host + ":" + DEFAULT_PORT + ","); + } else { + sb.append(host + ","); + } + } + return new ConnectionInfo(ComponentsDefine.CLICKHOUSE_JDBC, DB_TYPE, sb.toString(), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo(ComponentsDefine.CLICKHOUSE_JDBC, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL(location.endIndex())); + } else { + return new ConnectionInfo(ComponentsDefine.CLICKHOUSE_JDBC, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location.endIndex())); + } + } + } + +} + 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 b9781213a3b6..27b7498a931a 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 ORACLE_JDBC_URL_PREFIX = "jdbc:oracle"; private static final String H2_JDBC_URL_PREFIX = "jdbc:h2"; private static final String POSTGRESQL_JDBC_URL_PREFIX = "jdbc:postgresql"; + private static final String CLICKHOUSE_JDBC_URL_PREFIX = "jdbc:clickhouse"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -45,6 +46,8 @@ public static ConnectionInfo parser(String url) { parser = new H2URLParser(url); } else if (lowerCaseUrl.startsWith(POSTGRESQL_JDBC_URL_PREFIX)) { parser = new PostgreSQLURLParser(url); + } else if (lowerCaseUrl.startsWith(CLICKHOUSE_JDBC_URL_PREFIX)) { + parser = new ClickHouseURLParser(url); } return parser.parse(); } diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index b2f0023817b9..fda753f013b1 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -69,6 +69,7 @@ canal-1.x-plugin dubbo-2.7.x-plugin dubbo-2.7.x-conflict-patch + clickhouse-0.1.x-plugin pom