Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add feature :add plugin zookeeper and clickhouse #241

Merged
merged 2 commits into from
Aug 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions chaosblade-exec-plugin/chaosblade-exec-plugin-clickhouse/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>chaosblade-exec-plugin</artifactId>
<groupId>com.alibaba.chaosblade</groupId>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>chaosblade-exec-plugin-clickhouse</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package com.alibaba.chaosblade.exec.plugin.clickhouse;

import com.alibaba.chaosblade.exec.common.aop.*;
import com.alibaba.chaosblade.exec.common.aop.matcher.clazz.ClassMatcher;
import com.alibaba.chaosblade.exec.common.aop.matcher.clazz.NameClassMatcher;
import com.alibaba.chaosblade.exec.common.aop.matcher.clazz.OrClassMatcher;
import com.alibaba.chaosblade.exec.common.aop.matcher.method.MethodMatcher;
import com.alibaba.chaosblade.exec.common.aop.matcher.method.NameMethodMatcher;
import com.alibaba.chaosblade.exec.common.aop.matcher.method.OrMethodMatcher;
import com.alibaba.chaosblade.exec.common.model.FrameworkModelSpec;
import com.alibaba.chaosblade.exec.common.model.ModelSpec;
import com.alibaba.chaosblade.exec.common.model.matcher.MatcherModel;
import com.alibaba.chaosblade.exec.common.model.matcher.MatcherSpec;
import com.alibaba.chaosblade.exec.common.model.matcher.SimplePredicateMatcherSpec;
import com.alibaba.chaosblade.exec.common.util.ReflectUtil;
import com.alibaba.chaosblade.exec.common.util.SQLParserUtil;
import com.alibaba.chaosblade.exec.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
* clickhouse的插件
* @author liuhq
*/
public class ClickhousePlugin implements Plugin {
private static final Logger LOGGER = LoggerFactory.getLogger(ClickhousePlugin.class);

private static final String TARGET_NAME = "ck";
private static final String GETSERVER_METHOD = "getServer";
private static final String GETDATABASE_METHOD = "getDatabase";
private static final String GETCLUSTER_METHOD = "getCluster";
private static final String GETADDRESS_METHOD = "getAddress";
private static final Class<InetSocketAddress> ADDRESS_CLAZZ = InetSocketAddress.class;
private static final String TABLE_MATCH_NAME = "table";
private static final String CLUSTER_MATCH_NAME = "cluster";
private static final String HOST_MATCH_NAME = "host";
private static final String PORT_MATCH_NAME = "port";
private static final String DATABASE_MATCH_NAME = "database";
private static final String CK_CLASS_HTTP = "com.clickhouse.client.http.ClickHouseHttpClient";
private static final String CK_CLASS_GRPC = "com.clickhouse.client.grpc.ClickHouseGrpcClient";
private static final String CK_METHOD = "execute";
private static final String PARAM_FIELD = "sql";
private static final String PARAM_CLASS = "com.clickhouse.client.ClickHouseRequest";

@Override
public String getName() {
return TARGET_NAME;
}

@Override
public ModelSpec getModelSpec() {
return new FrameworkModelSpec() {
@Override
protected List<MatcherSpec> createNewMatcherSpecs() {
MatcherSpec tableMatcher = new SimplePredicateMatcherSpec(TABLE_MATCH_NAME,"The first table name in sql");
MatcherSpec databaseMatcher = new SimplePredicateMatcherSpec(DATABASE_MATCH_NAME,"The database which used");
MatcherSpec clusterMatcher = new SimplePredicateMatcherSpec(CLUSTER_MATCH_NAME,"The cluster which used");
MatcherSpec hostMatcher = new SimplePredicateMatcherSpec(HOST_MATCH_NAME,"The host which used");
MatcherSpec portMatcher = new SimplePredicateMatcherSpec(PORT_MATCH_NAME,"The ip which used");
List<MatcherSpec> res = new ArrayList<MatcherSpec>();
res.add(tableMatcher);
res.add(databaseMatcher);
res.add(clusterMatcher);
res.add(hostMatcher);
res.add(portMatcher);
return res;
}

@Override
public String getTarget() {
return TARGET_NAME;
}

@Override
public String getShortDesc() {
return "Clickhouse experiment ";
}

@Override
public String getLongDesc() {
return "Clickhouse experiment contains delay and exception by table name and so on";
}
};
}

@Override
public PointCut getPointCut() {
return new PointCut() {
@Override
public ClassMatcher getClassMatcher() {
OrClassMatcher orClassMatcher = new OrClassMatcher();
orClassMatcher.or(new NameClassMatcher(CK_CLASS_GRPC))
.or(new NameClassMatcher(CK_CLASS_HTTP));
return orClassMatcher;
}

@Override
public MethodMatcher getMethodMatcher() {
return new OrMethodMatcher().or(new NameMethodMatcher(CK_METHOD));
}
};
}

@Override
public Enhancer getEnhancer() {

return new BeforeEnhancer() {
@Override
public EnhancerModel doBeforeAdvice(ClassLoader classLoader, String className, Object object, Method method, Object[] methodArguments) throws Exception {
if (methodArguments == null || methodArguments.length == 0) {
LOGGER.info("The necessary parameters is empty, {}",
methodArguments != null ? methodArguments.length : null);
return null;
}
Object methodArgument = methodArguments[0];
boolean assignableFrom =
ReflectUtil.isAssignableFrom(
classLoader, methodArgument.getClass(), PARAM_CLASS);
if (!assignableFrom) {
return null;
}
String database = null;
String cluster = null;
String host = null;
String port = null;
String table = null;

try {
//读取server
Object server = ReflectUtil.invokeMethod(methodArgument, GETSERVER_METHOD);
//读取database
Optional<String> databaseOpt = ReflectUtil.invokeMethod(server, GETDATABASE_METHOD);
database = databaseOpt.get();
//读取cluster
cluster = ReflectUtil.invokeMethod(server, GETCLUSTER_METHOD);
//读取IP
Object address = ReflectUtil.invokeMethod(server, GETADDRESS_METHOD);
if(address.getClass().isAssignableFrom(ADDRESS_CLAZZ)){
host = ((InetSocketAddress)address).getHostName();
port = String.valueOf(((InetSocketAddress)address).getPort());
}

//读取SQL字段信息,获取table
String fieldValue = ReflectUtil.getFieldValue(methodArgument, PARAM_FIELD, true);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("sql ck: {}", fieldValue);
}
if(StringUtil.isBlank(fieldValue)){
return null;
}
table = SQLParserUtil.findTableName(fieldValue);
}catch (Exception e){
LOGGER.error("reflect invoke error",e);
}


MatcherModel matcherModel = new MatcherModel();
if (!StringUtil.isBlank(table)) {
matcherModel.add(TABLE_MATCH_NAME,table);
}
if (!StringUtil.isBlank(database)) {
matcherModel.add(DATABASE_MATCH_NAME,table);
}
if (!StringUtil.isBlank(cluster)) {
matcherModel.add(CLUSTER_MATCH_NAME,cluster);
}
if (!StringUtil.isBlank(host)) {
matcherModel.add(HOST_MATCH_NAME,host);
}
if (!StringUtil.isBlank(port)) {
matcherModel.add(PORT_MATCH_NAME,port);
}

LOGGER.info("table database cluster host host : {},{},{},{},{}", table,database,cluster,host,port);

return new EnhancerModel(classLoader, matcherModel);
}
};
}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#
# Copyright 1999-2019 Alibaba Group Holding Ltd.
#
# Licensed 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.
#



com.alibaba.chaosblade.exec.plugin.clickhouse.ClickhousePlugin
20 changes: 20 additions & 0 deletions chaosblade-exec-plugin/chaosblade-exec-plugin-zookeeper/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<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>chaosblade-exec-plugin</artifactId>
<groupId>com.alibaba.chaosblade</groupId>
<version>1.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>chaosblade-exec-plugin-zookeeper</artifactId>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed 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 com.alibaba.chaosblade.exec.plugin.zookeeper;

/**
* @author liuhq
* @Date 2020/11/23 上午11:36
**/
public interface ZookeeperConstant {
String TARGET_NAME = "zk";
String PATH_MATCHER_NAME = "path";
String PARAM_CLASS_NAME = "org.apache.jute.Record";
String ZK_CLASS = "org.apache.zookeeper.ClientCnxn";
String ZK_SEND_METHOD = "sendPacket";
String ZK_SUBMIT_METHOD = "submitRequest";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed 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 com.alibaba.chaosblade.exec.plugin.zookeeper;

import com.alibaba.chaosblade.exec.common.aop.BeforeEnhancer;
import com.alibaba.chaosblade.exec.common.aop.EnhancerModel;
import com.alibaba.chaosblade.exec.common.model.matcher.MatcherModel;
import com.alibaba.chaosblade.exec.common.util.JsonUtil;
import com.alibaba.chaosblade.exec.common.util.ReflectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;


/**
* @author liuhq
* @Date 2020/11/23 上午11:40
**/
public class ZookeeperEnhancer extends BeforeEnhancer {

private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperEnhancer.class);

@Override
public EnhancerModel doBeforeAdvice(ClassLoader classLoader, String className, Object object, Method method,
Object[] methodArguments) throws Exception {

if (methodArguments == null || methodArguments.length == 0) {
LOGGER.info("The necessary parameters is null or length is not equal 1, {}",
methodArguments != null ? methodArguments.length : null);
return null;
}
Object packgeParam = null;

if(method.getName().equals(ZookeeperConstant.ZK_SEND_METHOD)){
packgeParam = methodArguments[0];
}else if(method.getName().equals(ZookeeperConstant.ZK_SUBMIT_METHOD)){
packgeParam = methodArguments[1];
}
if (packgeParam == null) {
return null;
}
boolean packgeClassFlag =
ReflectUtil.isAssignableFrom(classLoader, packgeParam.getClass(), ZookeeperConstant.PARAM_CLASS_NAME);
String path = null;
if (packgeClassFlag) {
try {
path = ReflectUtil.invokeMethod(packgeParam, "getPath", new Object[0], false);
}catch (Exception e){
LOGGER.info("not find method");
return null;
}
}
if (path == null) {
return null;
}

MatcherModel matcherModel = new MatcherModel();

matcherModel.add(ZookeeperConstant.PATH_MATCHER_NAME, path.toLowerCase());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("zk matchers: {}", JsonUtil.writer().writeValueAsString(matcherModel));
}
return new EnhancerModel(classLoader, matcherModel);
}
}
Loading