Feature add clickhouse jdbc plugin (#41)

This commit is contained in:
wallezhang 2021-10-11 11:37:58 +08:00 committed by GitHub
parent e99a031080
commit 813fc31bd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1572 additions and 0 deletions

View File

@ -90,6 +90,7 @@ jobs:
- oracle-scenario
- druid-1.x-scenario
- hikaricp-scenario
- clickhouse-0.3.x-scenario
steps:
- uses: actions/checkout@v2
with:

View File

@ -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

View File

@ -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");
}

View File

@ -0,0 +1,61 @@
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>apm-sdk-plugin</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>8.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apm-clickhouse-0.3.x-plugin</artifactId>
<packaging>jar</packaging>
<name>clickhouse-0.3.x-plugin</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<clickhouse.jdbc.version>0.3.1-patch</clickhouse.jdbc.version>
</properties>
<dependencies>
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>${clickhouse.jdbc.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>apm-jdbc-commons</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -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) {
}
}

View File

@ -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> T of(ConnectionInfo connectionInfo, String methodName, String sql,
SupplierWithException<T> 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> {
T get() throws SQLException;
}
}

View File

@ -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.
* <p>
* 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.
* </p>
* <p>
* This interceptor is used to replace {@link org.apache.skywalking.apm.plugin.jdbc.JDBCDriverInterceptor}.
* </p>
*/
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) {
}
}

View File

@ -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<ClickHouseQueryParam, String> additionalDBParams) throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseResponse", sql,
() -> delegate.executeQueryClickhouseResponse(sql, additionalDBParams));
}
@Override
public ClickHouseResponse executeQueryClickhouseResponse(String sql,
Map<ClickHouseQueryParam, String> additionalDBParams, Map<String, String> 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<ClickHouseQueryParam, String> additionalDBParams) throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseRowBinaryStream", sql,
() -> delegate.executeQueryClickhouseRowBinaryStream(sql, additionalDBParams));
}
@Override
public ClickHouseRowBinaryInputStream executeQueryClickhouseRowBinaryStream(String sql,
Map<ClickHouseQueryParam, String> additionalDBParams, Map<String, String> additionalRequestParams)
throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQueryClickhouseRowBinaryStream", sql,
() -> delegate.executeQueryClickhouseRowBinaryStream(sql, additionalDBParams, additionalRequestParams));
}
@Override
public ResultSet executeQuery(String sql, Map<ClickHouseQueryParam, String> additionalDBParams)
throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql,
() -> delegate.executeQuery(sql, additionalDBParams));
}
@Override
public ResultSet executeQuery(String sql, Map<ClickHouseQueryParam, String> additionalDBParams,
List<ClickHouseExternalData> externalData) throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql,
() -> delegate.executeQuery(sql, additionalDBParams, externalData));
}
@Override
public ResultSet executeQuery(String sql, Map<ClickHouseQueryParam, String> additionalDBParams,
List<ClickHouseExternalData> externalData, Map<String, String> additionalRequestParams)
throws SQLException {
return ClickHouseStatementTracingWrapper.of(connectionInfo, "executeQuery", sql,
() -> delegate.executeQuery(sql, additionalDBParams, externalData, additionalRequestParams));
}
@Override
public void sendStream(InputStream content, String table, Map<ClickHouseQueryParam, String> 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<ClickHouseQueryParam, String> 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<ClickHouseQueryParam, String> 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<ClickHouseQueryParam, String> 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<ClickHouseQueryParam, String> 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> T unwrap(Class<T> iface) throws SQLException {
return delegate.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return delegate.isWrapperFor(iface);
}
}

View File

@ -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<MethodDescription> 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<MethodDescription> 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<MethodDescription> 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<MethodDescription> 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;
}
}
};
}
}

View File

@ -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

View File

@ -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<TraceSegment> traceSegments = segmentStorage.getTraceSegments();
assertThat(traceSegments.size(), is(1));
final List<AbstractTracingSpan> 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);
}
}

View File

@ -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());
}
}

View File

@ -110,6 +110,7 @@
<module>druid-1.x-plugin</module>
<module>hikaricp-3.x-4.x-plugin</module>
<module>httpclient-5.x-plugin</module>
<module>clickhouse-0.3.x-plugin</module>
</modules>
<packaging>pom</packaging>

View File

@ -124,3 +124,4 @@
- jsonrpc4j
- spring-cloud-gateway-3.x
- neo4j-4.x
- clickhouse-0.3.x

View File

@ -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

View File

@ -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 &

View File

@ -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: []

View File

@ -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

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>org.apache.skywalking.apm.testcase</groupId>
<artifactId>clickhouse-0.3.x-scenario</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<compiler.version>1.8</compiler.version>
<test.framework.version>0.3.1-patch</test.framework.version>
<spring-boot-version>2.5.1</spring-boot-version>
</properties>
<name>skywalking-clickhouse-0.3.x-scenario</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>${test.framework.version}</version>
</dependency>
</dependencies>
<build>
<finalName>clickhouse-0.3.x-scenario</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${compiler.version}</source>
<target>${compiler.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<outputDirectory>./target/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>./bin</directory>
<fileMode>0775</fileMode>
</fileSet>
</fileSets>
<files>
<file>
<source>${project.build.directory}/clickhouse-0.3.x-scenario.jar</source>
<outputDirectory>./libs</outputDirectory>
<fileMode>0775</fileMode>
</file>
</files>
</assembly>

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<Configuration status="WARN">
<Appenders>
<Console name="Console">
<PatternLayout charset="UTF-8"
pattern="[%d{yyyy-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

View File

@ -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