Skip to content

Commit

Permalink
增加MYSQL指标采集插件
Browse files Browse the repository at this point in the history
Signed-off-by: hanbingleixue <[email protected]>
  • Loading branch information
hanbingleixue committed Jan 18, 2024
1 parent c83aa32 commit 7deb9ed
Show file tree
Hide file tree
Showing 39 changed files with 1,181 additions and 66 deletions.
58 changes: 58 additions & 0 deletions sermant-plugins/sermant-metrics/metrics-common/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?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>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>sermant-metrics</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>metrics-common</artifactId>

<name>metrics-common</name>
<description>The common module of metrics.</description>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<jsqlparser.version>4.4</jsqlparser.version>
</properties>
<dependencies>
<!--provided依赖-->
<dependency>
<groupId>com.huaweicloud.sermant</groupId>
<artifactId>sermant-agentcore-core</artifactId>
<scope>provided</scope>
</dependency>
<!--SQL解析第三方依赖-->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>${jsqlparser.version}</version>
</dependency>
<!--test依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,6 @@ public class Constants {
*/
public static final String SIDE_KEY = "side";

/**
* RPC信息保存到context局部变量中的key
*/
public static final String RPC_INFO_KEY = "rpcInfo";

/**
* 服务调用开始时间保存到context局部变量中的key
*/
Expand All @@ -123,6 +118,21 @@ public class Constants {
*/
public static final String HTTPS_PROTOCOL = "https";

/**
* mysql协议
*/
public static final String MYSQL_PROTOCOL = "mysql";

/**
* mysql链接端口的配置信息
*/
public static final String MYSQL_PROPERTY_PORT = "PORT";

/**
* mysql链接端口的配置信息
*/
public static final String MYSQL_PROPERTY_HOST = "HOST";

/**
* 最大成功响应编码
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class MetricsInfo {
/**
* 服务端端口
*/
private String serverPort;
private int serverPort;

/**
* L4角色信息
Expand Down Expand Up @@ -117,11 +117,11 @@ public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}

public String getServerPort() {
public int getServerPort() {
return serverPort;
}

public void setServerPort(String serverPort) {
public void setServerPort(int serverPort) {
this.serverPort = serverPort;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huawei.metrics.interceptor;

import com.huawei.metrics.common.Constants;
import com.huawei.metrics.common.ResultType;
import com.huawei.metrics.entity.MetricsRpcInfo;
import com.huawei.metrics.util.InetAddressUtil;
import com.huawei.metrics.util.ResultJudgmentUtil;
import com.huawei.metrics.util.SqlParseUtil;

import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext;
import com.huaweicloud.sermant.core.plugin.agent.interceptor.Interceptor;

import java.sql.SQLException;

/**
* MYSQL拦截器父类
*
* @author zhp
* @since 2023-12-15
*/
public abstract class AbstractMysqlInterceptor implements Interceptor {
@Override
public ExecuteContext after(ExecuteContext context) {
return collectMetrics(context);
}

/**
* 采集指标信息
*
* @param context 上下文信息
* @return ExecuteContext 上下文信息
*/
public abstract ExecuteContext collectMetrics(ExecuteContext context);

@Override
public ExecuteContext onThrow(ExecuteContext context) {
return collectMetrics(context);
}

/**
* 初始化指标数据
*
* @param context 上下文信息
* @param enableSsl 是否开启SSL
* @param serverIp 服务端IP
* @param serverPort 服务端端口
* @param sql 执行的SQL
* @return 指标信息
*/
public MetricsRpcInfo initMetricsRpcInfo(ExecuteContext context, boolean enableSsl, String serverIp,
int serverPort, String sql) {
MetricsRpcInfo metricsRpcInfo = new MetricsRpcInfo();
metricsRpcInfo.setClientIp(InetAddressUtil.getHostAddress());
metricsRpcInfo.setServerIp(serverIp);
metricsRpcInfo.setServerPort(serverPort);
metricsRpcInfo.setProtocol(Constants.MYSQL_PROTOCOL);
metricsRpcInfo.setEnableSsl(enableSsl);
metricsRpcInfo.setL7Role(Constants.CLIENT_ROLE);
metricsRpcInfo.setL4Role(Constants.TCP_PROTOCOL + Constants.CONNECT + metricsRpcInfo.getL7Role());
metricsRpcInfo.getReqCount().getAndIncrement();
metricsRpcInfo.getResponseCount().getAndIncrement();
metricsRpcInfo.setUrl(SqlParseUtil.getApi(sql));
if (context.getThrowable() == null) {
return metricsRpcInfo;
}
metricsRpcInfo.getReqErrorCount().getAndIncrement();
if (!(context.getThrowable() instanceof SQLException)) {
return metricsRpcInfo;
}
SQLException exception = (SQLException) context.getThrowable();
int value = ResultJudgmentUtil.judgeMysqlResult(exception.getErrorCode());
if (ResultType.CLIENT_ERROR.getValue() == value) {
metricsRpcInfo.getClientErrorCount().getAndIncrement();
} else if (ResultType.SERVER_ERROR.getValue() == value) {
metricsRpcInfo.getServerErrorCount().getAndIncrement();
}
return metricsRpcInfo;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huawei.metrics.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* 网络地址工具类
*
* @author zhp
* @since 2023-12-15
*/
public class InetAddressUtil {
private static final Logger LOGGER = Logger.getLogger(InetAddressUtil.class.getName());

private static volatile String hostAddress;

private InetAddressUtil() {
}

/**
* 获取本机IP地址
*
* @return IP地址
*/
public static String getHostAddress() {
if (hostAddress == null) {
synchronized (InetAddressUtil.class) {
if (hostAddress == null) {
try {
InetAddress localhost = InetAddress.getLocalHost();
hostAddress = localhost.getHostAddress();
} catch (UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Unable to obtain local host address.");
}
}
}
}
return hostAddress;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2023-2023 Huawei Technologies Co., Ltd. All rights reserved.
*
* 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.huawei.metrics.util;

import com.huawei.metrics.common.Constants;

import com.huaweicloud.sermant.core.common.LoggerFactory;
import com.huaweicloud.sermant.core.utils.StringUtils;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.util.TablesNamesFinder;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* SQL解析工具类
*
* @author zhp
* @since 2023-12-15
*/
public class SqlParseUtil {
private static final Logger LOGGER = LoggerFactory.getLogger();

private SqlParseUtil() {
}

/**
* 获取mysql的API维度信息(命令类型_表名)
*
* @param sql 执行的SQL语句
* @return API
*/
public static String getApi(String sql) {
StringBuilder stringBuilder = new StringBuilder();
try {
Statement statement = CCJSqlParserUtil.parse(sql);
stringBuilder.append(statement.getClass().getSimpleName().replace("Statement", StringUtils.EMPTY));
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List<String> tables = tablesNamesFinder.getTableList(statement);
if (tables != null) {
for (String table : tables) {
stringBuilder.append(Constants.CONNECT).append(table);
}
}
return stringBuilder.toString();
} catch (JSQLParserException | UnsupportedOperationException e) {
LOGGER.log(Level.INFO, "There is currently no table data in SQL.");
return stringBuilder.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,29 @@
package com.huawei.metrics.util;

/**
* HttpUrlConnection工具类,用于线程数据传递
* 线程工具类,用于线程数据传递
*
* @author zhp
* @since 2023-12-15
*/
public class HttpUrlConnectionUtil {
public class ThreadLocalUtil {
/**
* 线程变量存储,主要存储请求开始时间
* 线程变量存储,主要存储请求开始时间和预编译SQL
*/
private static final ThreadLocal<Long> START_TIME_THREAD_LOCAL = new InheritableThreadLocal<>();
private static final ThreadLocal<Object> START_TIME_THREAD_LOCAL = new InheritableThreadLocal<>();

/**
* 构造函数
*/
private HttpUrlConnectionUtil() {
private ThreadLocalUtil() {
}

/**
* 设置线程变量
*
* @param value 变量信息
*/
public static void setValue(Long value) {
public static void setValue(Object value) {
START_TIME_THREAD_LOCAL.set(value);
}

Expand All @@ -48,7 +48,7 @@ public static void setValue(Long value) {
*
* @return 变量信息
*/
public static Long getValue() {
public static Object getValue() {
return START_TIME_THREAD_LOCAL.get();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.huawei.metrics.config.MetricsConfig
Loading

0 comments on commit 7deb9ed

Please sign in to comment.