From a01b776871032c045894e2f09b48cdb2a37a821a Mon Sep 17 00:00:00 2001 From: hanbingleixue Date: Thu, 11 Jan 2024 11:04:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0SpringCloud=E6=8C=87=E6=A0=87?= =?UTF-8?q?=E9=87=87=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hanbingleixue --- .../sermant-metrics/metrics-plugin/pom.xml | 44 ++- .../com/huawei/metrics/common/Constants.java | 77 +++-- .../com/huawei/metrics/common/ResultType.java | 55 ++++ .../alibaba/ExchangeCodecDeclarer.java | 16 +- .../alibaba/MonitorFilterDeclarer.java | 4 +- .../apache/ExchangeCodecDeclarer.java | 16 +- .../apache/MonitorFilterDeclarer.java | 4 +- .../httpclient/HttpClientDeclarer.java | 59 ++++ .../httpurlconnection/ConnectDeclarer.java | 47 +++ .../httpurlconnection/DisconnectDeclarer.java | 47 +++ .../metrics/declarer/okhttp/CallDeclarer.java | 47 +++ .../declarer/okhttp3/CallDeclarer.java | 50 +++ .../declarer/servlet/HttpServletDeclarer.java | 47 +++ .../huawei/metrics/entity/MetricsInfo.java | 13 + .../metrics/entity/MetricsLinkInfo.java | 80 ----- .../huawei/metrics/entity/MetricsRpcInfo.java | 20 ++ .../interceptor/AbstractCodecInterceptor.java | 125 ++------ .../AbstractFilterInterceptor.java | 21 +- .../interceptor/AbstractHttpInterceptor.java | 107 +++++++ .../alibaba/ExchangeCodecInterceptor.java | 57 ++-- .../alibaba/MonitorFilterInterceptor.java | 6 +- .../apache/ExchangeCodecInterceptor.java | 57 ++-- .../apache/MonitorFilterInterceptor.java | 6 +- .../httpclient/HttpClientInterceptor.java | 59 ++++ .../ConnectorInterceptor.java | 47 +++ .../DisconnectorInterceptor.java | 57 ++++ .../interceptor/okhttp/CallInterceptor.java | 51 +++ .../interceptor/okhttp3/CallInterceptor.java | 56 ++++ .../servlet/HttpServletInterceptor.java | 78 +++++ .../metrics/manager/MetricsManager.java | 52 +-- .../metrics/util/HttpUrlConnectionUtil.java | 61 ++++ .../metrics/util/ResultJudgmentUtil.java | 91 ++++++ ....core.plugin.agent.declarer.PluginDeclarer | 8 +- .../metrics/service/MetricsService.java | 302 ++++++++---------- 34 files changed, 1353 insertions(+), 514 deletions(-) create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/ResultType.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpclient/HttpClientDeclarer.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/ConnectDeclarer.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/DisconnectDeclarer.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp/CallDeclarer.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp3/CallDeclarer.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/servlet/HttpServletDeclarer.java delete mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsLinkInfo.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractHttpInterceptor.java rename sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/{ => dubbo}/alibaba/ExchangeCodecInterceptor.java (50%) rename sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/{ => dubbo}/alibaba/MonitorFilterInterceptor.java (87%) rename sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/{ => dubbo}/apache/ExchangeCodecInterceptor.java (50%) rename sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/{ => dubbo}/apache/MonitorFilterInterceptor.java (87%) create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpclient/HttpClientInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/ConnectorInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/DisconnectorInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp/CallInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp3/CallInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/servlet/HttpServletInterceptor.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/HttpUrlConnectionUtil.java create mode 100644 sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/ResultJudgmentUtil.java diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/pom.xml b/sermant-plugins/sermant-metrics/metrics-plugin/pom.xml index 524c6db844..3fb8e79365 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/pom.xml +++ b/sermant-plugins/sermant-metrics/metrics-plugin/pom.xml @@ -20,9 +20,15 @@ 2.5.7 2.7.3 4.0.1 + 4.5.13 + 2.7.5 + 4.1.0 + 3.0.1 + 4.4 + 8.0.28 - + com.huaweicloud.sermant sermant-agentcore-core @@ -40,6 +46,42 @@ ${apache.dubbo.version} provided + + org.apache.httpcomponents + httpclient + ${httpclient.version} + provided + + + com.squareup.okhttp + okhttp + ${okhttp.version} + provided + + + com.squareup.okhttp3 + okhttp + ${okhtt3.version} + provided + + + javax.servlet + javax.servlet-api + ${javax-servlet-api.version} + provided + + + mysql + mysql-connector-java + ${mysql.version} + provided + + + + com.github.jsqlparser + jsqlparser + ${jsqlparser.version} + junit diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/Constants.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/Constants.java index f30b8fbc48..6a3076ddca 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/Constants.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/Constants.java @@ -63,16 +63,6 @@ public class Constants { */ public static final String SSL_ENABLE = "sslEnabled"; - /** - * 服务调用使用的CLIENT下表字段名 - */ - public static final String CLIENT_INDEX = "index"; - - /** - * CLIENT集合名称 - */ - public static final String CLIENTS_NAME = "clients"; - /** * DUBBO TCP协议集合 */ @@ -81,12 +71,12 @@ public class Constants { /** * 连接信息头 */ - public static final String LINK_HEAD = "sermant_l7_link"; + public static final String RPC_HEADER = "sermant_l7_rpc"; /** - * 连接信息头 + * API连接信息头 */ - public static final String RPC_HEAD = "sermant_l7_rpc"; + public static final String RPC_API_HEADER = "sermant_l7_rpc_api"; /** * SSL开启标识 @@ -104,49 +94,74 @@ public class Constants { public static final String CONSUMER_SIDE = "consumer"; /** - * 提供者标识 + * 客户端 服务端标识的KEY */ - public static final String PROVIDER_SIDE = "provider"; + public static final String SIDE_KEY = "side"; /** - * 客户端 服务端标识的KEY + * RPC信息保存到context局部变量中的key */ - public static final String SIDE_KEY = "side"; + public static final String RPC_INFO_KEY = "rpcInfo"; /** - * 字符串写下标保存到context局部变量中的key + * 服务调用开始时间保存到context局部变量中的key */ - public static final String WRITE_INDEX_KEY = "writeIndex"; + public static final String START_TIME_KEY = "startTime"; /** - * 字符串读下标保存到context局部变量中的key + * 异常线程ID */ - public static final String READ_INDEX_KEY = "readIndex"; + public static final String EXCEPTION_PID = "-1"; /** - * 连接信息保存到context局部变量中的key + * 指标值的连接符 */ - public static final String LINK_INFO_KEY = "linkInfo"; + public static final String METRICS_LINK = "|"; /** - * RPC信息保存到context局部变量中的key + * HTTPS协议 */ - public static final String RPC_INFO_KEY = "rpcInfo"; + public static final String HTTPS_PROTOCOL = "https"; /** - * 服务调用开始时间保存到context局部变量中的key + * 最大成功响应编码 */ - public static final String START_TIME_KEY = "startTime"; + public static final int MAX_SUCCESS_CODE = 399; /** - * 异常线程ID + * 最大客户端失败编码 */ - public static final String EXCEPTION_PID = "-1"; + public static final int MAX_CLIENT_ERROR_CODE = 499; /** - * 指标值的连接符 + * 最大服务端失败编码 */ - public static final String METRICS_LINK = "|"; + public static final int MAX_SERVER_ERROR_CODE = 599; + + /** + * MYSQL 客户端异常编码 + */ + public static final int[][] MYSQL_CLIENT_ERROR = {{1, 999}, {2000, 2999}}; + + /** + * MYSQL 服务服务端编码 + */ + public static final int[][] MYSQL_SERVER_ERROR = {{1000, 1999}, {3000, 4000}}; + + /** + * http请求成功 + */ + public static final byte HTTP_OK = 20; + + /** + * HTTP客户端异常编码 + */ + public static final byte[] HTTP_CLIENT_ERROR = {30, 40, 90}; + + /** + * HTTP异常编码 + */ + public static final byte[] HTTP_SERVER_ERROR = {31, 80, 50, 60, 70, 100}; private Constants() { } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/ResultType.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/ResultType.java new file mode 100644 index 0000000000..28c9eadcc8 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/common/ResultType.java @@ -0,0 +1,55 @@ +/* + * 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.common; + +/** + * 结果类型 + * + * @author zhp + * @since 2023-12-15 + */ +public enum ResultType { + /** + * 请求成功 + */ + SUCCESS(0), + + /** + * 客户端错误 + */ + CLIENT_ERROR(1), + + /** + * 服务端错误 + */ + SERVER_ERROR(2), + + /** + * 请求失败 + */ + ERROR(3); + + private final int value; + + ResultType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/ExchangeCodecDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/ExchangeCodecDeclarer.java index 6667b1f27e..e9dd11101c 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/ExchangeCodecDeclarer.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/ExchangeCodecDeclarer.java @@ -17,14 +17,14 @@ package com.huawei.metrics.declarer.alibaba; import com.huawei.metrics.declarer.AbstractDeclarer; -import com.huawei.metrics.interceptor.alibaba.ExchangeCodecInterceptor; +import com.huawei.metrics.interceptor.dubbo.alibaba.ExchangeCodecInterceptor; import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; /** - * dubbo报文转码、解码增强声明 + * dubbo2.6.x报文转码、解码增强声明 * * @author zhp * @since 2023-10-17 @@ -32,11 +32,7 @@ public class ExchangeCodecDeclarer extends AbstractDeclarer { private static final String ENHANCE_CLASS = "com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec"; - private static final String ENCODE_METHODS_NAMES = "encode"; - - private static final String DECODE_METHODS_NAMES = "decode"; - - private static final int ENCODE_PARAM_COUNT = 3; + private static final String DECODE_METHODS_NAMES = "decodeBody"; private static final int DECODE_PARAM_COUNT = 2; @@ -47,10 +43,8 @@ public ClassMatcher getClassMatcher() { @Override public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { - return new InterceptDeclarer[]{InterceptDeclarer.build(MethodMatcher.nameEquals(ENCODE_METHODS_NAMES) - .and(MethodMatcher.paramCountEquals(ENCODE_PARAM_COUNT)), new ExchangeCodecInterceptor()), - InterceptDeclarer.build(MethodMatcher.nameEquals(DECODE_METHODS_NAMES) - .and(MethodMatcher.paramCountEquals(DECODE_PARAM_COUNT)), new ExchangeCodecInterceptor()) + return new InterceptDeclarer[]{InterceptDeclarer.build(MethodMatcher.nameEquals(DECODE_METHODS_NAMES) + .and(MethodMatcher.paramCountEquals(DECODE_PARAM_COUNT)), new ExchangeCodecInterceptor()) }; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/MonitorFilterDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/MonitorFilterDeclarer.java index 78f632730e..5ff3a41d03 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/MonitorFilterDeclarer.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/alibaba/MonitorFilterDeclarer.java @@ -17,14 +17,14 @@ package com.huawei.metrics.declarer.alibaba; import com.huawei.metrics.declarer.AbstractDeclarer; -import com.huawei.metrics.interceptor.alibaba.MonitorFilterInterceptor; +import com.huawei.metrics.interceptor.dubbo.alibaba.MonitorFilterInterceptor; import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; /** - * dubbo监控过滤器增强声明 + * dubbo2.6.x监控过滤器增强声明 * * @author zhp * @since 2023-10-17 diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/ExchangeCodecDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/ExchangeCodecDeclarer.java index d0c9e62e1f..927d189917 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/ExchangeCodecDeclarer.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/ExchangeCodecDeclarer.java @@ -17,14 +17,14 @@ package com.huawei.metrics.declarer.apache; import com.huawei.metrics.declarer.AbstractDeclarer; -import com.huawei.metrics.interceptor.apache.ExchangeCodecInterceptor; +import com.huawei.metrics.interceptor.dubbo.apache.ExchangeCodecInterceptor; import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; /** - * dubbo报文转码、解码增强声明 + * dubbo2.7.x报文转码、解码增强声明 * * @author zhp * @since 2023-10-17 @@ -32,11 +32,7 @@ public class ExchangeCodecDeclarer extends AbstractDeclarer { private static final String ENHANCE_CLASS = "org.apache.dubbo.remoting.exchange.codec.ExchangeCodec"; - private static final String ENCODE_METHODS_NAMES = "encode"; - - private static final String DECODE_METHODS_NAMES = "decode"; - - private static final int ENCODE_PARAM_COUNT = 3; + private static final String DECODE_METHODS_NAMES = "decodeBody"; private static final int DECODE_PARAM_COUNT = 2; @@ -47,10 +43,8 @@ public ClassMatcher getClassMatcher() { @Override public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { - return new InterceptDeclarer[]{InterceptDeclarer.build(MethodMatcher.nameEquals(ENCODE_METHODS_NAMES) - .and(MethodMatcher.paramCountEquals(ENCODE_PARAM_COUNT)), new ExchangeCodecInterceptor()), - InterceptDeclarer.build(MethodMatcher.nameEquals(DECODE_METHODS_NAMES) - .and(MethodMatcher.paramCountEquals(DECODE_PARAM_COUNT)), new ExchangeCodecInterceptor()) + return new InterceptDeclarer[]{InterceptDeclarer.build(MethodMatcher.nameEquals(DECODE_METHODS_NAMES) + .and(MethodMatcher.paramCountEquals(DECODE_PARAM_COUNT)), new ExchangeCodecInterceptor()) }; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/MonitorFilterDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/MonitorFilterDeclarer.java index 21b2f936b2..e435637662 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/MonitorFilterDeclarer.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/apache/MonitorFilterDeclarer.java @@ -17,14 +17,14 @@ package com.huawei.metrics.declarer.apache; import com.huawei.metrics.declarer.AbstractDeclarer; -import com.huawei.metrics.interceptor.apache.MonitorFilterInterceptor; +import com.huawei.metrics.interceptor.dubbo.apache.MonitorFilterInterceptor; import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; /** - * dubbo监控过滤器增强声明 + * dubbo2.7.x监控过滤器增强声明 * * @author zhp * @since 2023-10-17 diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpclient/HttpClientDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpclient/HttpClientDeclarer.java new file mode 100644 index 0000000000..0ae9139940 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpclient/HttpClientDeclarer.java @@ -0,0 +1,59 @@ +/* + * 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.declarer.httpclient; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.httpclient.HttpClientInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * HttpClient4.x请求方法拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class HttpClientDeclarer extends AbstractDeclarer { + /** + * 增强类的全限定名 http请求 + */ + private static final String[] ENHANCE_CLASSES = { + "org.apache.http.impl.client.AbstractHttpClient", + "org.apache.http.impl.client.DefaultRequestDirector", + "org.apache.http.impl.client.InternalHttpClient", + "org.apache.http.impl.client.MinimalHttpClient" + }; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameContains(ENHANCE_CLASSES); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameContains("doExecute", "execute") + .and(MethodMatcher.paramTypesEqual( + "org.apache.http.HttpHost", + "org.apache.http.HttpRequest", + "org.apache.http.protocol.HttpContext")), + new HttpClientInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/ConnectDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/ConnectDeclarer.java new file mode 100644 index 0000000000..c6e66d092b --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/ConnectDeclarer.java @@ -0,0 +1,47 @@ +/* + * 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.declarer.httpurlconnection; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.httpurlconnection.ConnectorInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * HttpURLConnection1.7.x+链接方法拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class ConnectDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "sun.net.www.protocol.http.HttpURLConnection"; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameEquals("connect"), + new ConnectorInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/DisconnectDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/DisconnectDeclarer.java new file mode 100644 index 0000000000..144c1b7118 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/httpurlconnection/DisconnectDeclarer.java @@ -0,0 +1,47 @@ +/* + * 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.declarer.httpurlconnection; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.httpurlconnection.DisconnectorInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * HttpURLConnection1.7.x+链接断开方法拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class DisconnectDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "sun.net.www.protocol.http.HttpURLConnection"; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameEquals("disconnect"), + new DisconnectorInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp/CallDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp/CallDeclarer.java new file mode 100644 index 0000000000..6aed99a40a --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp/CallDeclarer.java @@ -0,0 +1,47 @@ +/* + * 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.declarer.okhttp; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.okhttp.CallInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * okhttp2.x服务调用拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class CallDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "com.squareup.okhttp.Call"; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameEquals(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameEquals("getResponseWithInterceptorChain"), + new CallInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp3/CallDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp3/CallDeclarer.java new file mode 100644 index 0000000000..1a0c27bd98 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/okhttp3/CallDeclarer.java @@ -0,0 +1,50 @@ +/* + * 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.declarer.okhttp3; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.okhttp3.CallInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * okhttp3.x服务调用拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class CallDeclarer extends AbstractDeclarer { + private static final String[] ENHANCE_CLASSES = { + "okhttp3.RealCall", + "okhttp3.internal.connection.RealCall" + }; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.nameContains(ENHANCE_CLASSES); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameEquals("getResponseWithInterceptorChain"), + new CallInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/servlet/HttpServletDeclarer.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/servlet/HttpServletDeclarer.java new file mode 100644 index 0000000000..1f669394ab --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/declarer/servlet/HttpServletDeclarer.java @@ -0,0 +1,47 @@ +/* + * 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.declarer.servlet; + +import com.huawei.metrics.declarer.AbstractDeclarer; +import com.huawei.metrics.interceptor.servlet.HttpServletInterceptor; + +import com.huaweicloud.sermant.core.plugin.agent.declarer.InterceptDeclarer; +import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; +import com.huaweicloud.sermant.core.plugin.agent.matcher.MethodMatcher; + +/** + * HttpServlet3.0+服务处理拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class HttpServletDeclarer extends AbstractDeclarer { + private static final String ENHANCE_CLASS = "javax.servlet.http.HttpServlet"; + + @Override + public ClassMatcher getClassMatcher() { + return ClassMatcher.isExtendedFrom(ENHANCE_CLASS); + } + + @Override + public InterceptDeclarer[] getInterceptDeclarers(ClassLoader classLoader) { + return new InterceptDeclarer[]{ + InterceptDeclarer.build(MethodMatcher.nameEquals("service"), + new HttpServletInterceptor()) + }; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsInfo.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsInfo.java index bc5c035558..c1cb8d11a1 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsInfo.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsInfo.java @@ -88,6 +88,11 @@ public class MetricsInfo { */ private String machineId; + /** + * URL信息 + */ + private String url; + public String getProcessId() { return processId; } @@ -191,4 +196,12 @@ public String getMachineId() { public void setMachineId(String machineId) { this.machineId = machineId; } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsLinkInfo.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsLinkInfo.java deleted file mode 100644 index 23657af56d..0000000000 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsLinkInfo.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.entity; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 连接信息 - * - * @author zhp - * @since 2023-10-17 - */ -public class MetricsLinkInfo extends MetricsInfo { - /** - * 发送的字节数 - */ - private AtomicLong sentBytes = new AtomicLong(); - - /** - * 接收的字节数 - */ - private AtomicLong receiveBytes = new AtomicLong(); - - /** - * 发送的报文数 - */ - private AtomicInteger sentMessages = new AtomicInteger(); - - /** - * 接收的报文数 - */ - private AtomicInteger receiveMessages = new AtomicInteger(); - - public AtomicLong getSentBytes() { - return sentBytes; - } - - public void setSentBytes(AtomicLong sentBytes) { - this.sentBytes = sentBytes; - } - - public AtomicLong getReceiveBytes() { - return receiveBytes; - } - - public void setReceiveBytes(AtomicLong receiveBytes) { - this.receiveBytes = receiveBytes; - } - - public AtomicInteger getSentMessages() { - return sentMessages; - } - - public void setSentMessages(AtomicInteger sentMessages) { - this.sentMessages = sentMessages; - } - - public AtomicInteger getReceiveMessages() { - return receiveMessages; - } - - public void setReceiveMessages(AtomicInteger receiveMessages) { - this.receiveMessages = receiveMessages; - } -} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsRpcInfo.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsRpcInfo.java index f961d31e9f..3b281ef1f8 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsRpcInfo.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/entity/MetricsRpcInfo.java @@ -36,6 +36,10 @@ public class MetricsRpcInfo extends MetricsInfo { private AtomicInteger reqErrorCount = new AtomicInteger(); + private AtomicInteger clientErrorCount = new AtomicInteger(); + + private AtomicInteger serverErrorCount = new AtomicInteger(); + private List latencyList = new CopyOnWriteArrayList<>(); public AtomicInteger getReqCount() { @@ -77,4 +81,20 @@ public List getLatencyList() { public void setLatencyList(List latencyList) { this.latencyList = latencyList; } + + public AtomicInteger getClientErrorCount() { + return clientErrorCount; + } + + public void setClientErrorCount(AtomicInteger clientErrorCount) { + this.clientErrorCount = clientErrorCount; + } + + public AtomicInteger getServerErrorCount() { + return serverErrorCount; + } + + public void setServerErrorCount(AtomicInteger serverErrorCount) { + this.serverErrorCount = serverErrorCount; + } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractCodecInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractCodecInterceptor.java index c677e956a4..77f25363eb 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractCodecInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractCodecInterceptor.java @@ -17,8 +17,9 @@ package com.huawei.metrics.interceptor; import com.huawei.metrics.common.Constants; -import com.huawei.metrics.entity.MetricsLinkInfo; -import com.huawei.metrics.manager.MetricsManager; +import com.huawei.metrics.common.ResultType; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.util.ResultJudgmentUtil; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.agent.interceptor.Interceptor; @@ -44,25 +45,8 @@ public abstract class AbstractCodecInterceptor implements Interceptor { } }; - private static final String ENCODE_METHOD_NAME = "encode"; - @Override public ExecuteContext before(ExecuteContext context) { - if (!isValid(context)) { - return context; - } - MetricsLinkInfo metricsLinkInfo = initLinkInfo(context); - initIndexInfo(context); - context.setLocalFieldValue(Constants.LINK_INFO_KEY, metricsLinkInfo); - return context; - } - - @Override - public ExecuteContext after(ExecuteContext context) { - if (!isValid(context)) { - return context; - } - fillMessageInfo(context); return context; } @@ -81,22 +65,6 @@ private boolean isClientSide(String side) { return Constants.CONSUMER_SIDE.equals(side); } - /** - * 校验 - * - * @param context 上下文信息 - * @return 校验结果 - */ - public abstract boolean isValid(ExecuteContext context); - - /** - * 初始化连接信息 - * - * @param context 上下文信息 - * @return 连接信息 - */ - public abstract MetricsLinkInfo initLinkInfo(ExecuteContext context); - /** * 初始化连接信息 * @@ -107,92 +75,57 @@ private boolean isClientSide(String side) { * @param protocol 协议信息 * @return 连接信息 */ - public MetricsLinkInfo initLinkInfo(InetSocketAddress localAddress, InetSocketAddress remoteAddress, + public MetricsRpcInfo initRpcInfo(InetSocketAddress localAddress, InetSocketAddress remoteAddress, String side, boolean sslEnable, String protocol) { - String metricsKey = localAddress.getHostName() + Constants.CONNECT + remoteAddress.getHostName() - + Constants.CONNECT + remoteAddress.getPort(); - MetricsLinkInfo metricsLinkInfo = MetricsManager.getLinkInfo(metricsKey); - if (!StringUtils.isEmpty(metricsLinkInfo.getClientIp())) { - return metricsLinkInfo; - } - metricsLinkInfo.setProtocol(protocol); + MetricsRpcInfo metricsRpcInfo = new MetricsRpcInfo(); + metricsRpcInfo.setProtocol(protocol); if (isClientSide(side)) { - initAddressAndRole(metricsLinkInfo, Constants.CLIENT_ROLE, localAddress, remoteAddress); + initAddressAndRole(metricsRpcInfo, Constants.CLIENT_ROLE, localAddress, remoteAddress); } else { - initAddressAndRole(metricsLinkInfo, Constants.SERVER_ROLE, remoteAddress, localAddress); + initAddressAndRole(metricsRpcInfo, Constants.SERVER_ROLE, remoteAddress, localAddress); } - if (TCP_PROTOCOL.contains(metricsLinkInfo.getProtocol())) { - metricsLinkInfo.setL4Role(Constants.TCP_PROTOCOL + Constants.CONNECT + metricsLinkInfo.getL7Role()); + if (TCP_PROTOCOL.contains(metricsRpcInfo.getProtocol())) { + metricsRpcInfo.setL4Role(Constants.TCP_PROTOCOL + Constants.CONNECT + metricsRpcInfo.getL7Role()); } else { - metricsLinkInfo.setL4Role(Constants.UDP_PROTOCOL + Constants.CONNECT + metricsLinkInfo.getL7Role()); + metricsRpcInfo.setL4Role(Constants.UDP_PROTOCOL + Constants.CONNECT + metricsRpcInfo.getL7Role()); } - metricsLinkInfo.setEnableSsl(sslEnable); - return metricsLinkInfo; + metricsRpcInfo.setEnableSsl(sslEnable); + return metricsRpcInfo; } /** * 初始化地址和角色信息 * - * @param metricsLinkInfo 连接信息 + * @param metricsRpcInfo RPC指标信息 * @param role 角色信息 * @param clientAddress 客户端地址 * @param serverAddress 服务端地址 */ - private void initAddressAndRole(MetricsLinkInfo metricsLinkInfo, String role, InetSocketAddress clientAddress, + private void initAddressAndRole(MetricsRpcInfo metricsRpcInfo, String role, InetSocketAddress clientAddress, InetSocketAddress serverAddress) { - metricsLinkInfo.setL7Role(role); - metricsLinkInfo.setClientIp(clientAddress.getAddress().getHostAddress()); - metricsLinkInfo.setServerIp(serverAddress.getAddress().getHostAddress()); - metricsLinkInfo.setServerPort(StringUtils.getString(serverAddress.getPort())); + metricsRpcInfo.setL7Role(role); + metricsRpcInfo.setClientIp(clientAddress.getAddress().getHostAddress()); + metricsRpcInfo.setServerIp(serverAddress.getAddress().getHostAddress()); + metricsRpcInfo.setServerPort(StringUtils.getString(serverAddress.getPort())); } /** - * 初始化渠道缓存的下标信息 - * - * @param context 上下文信息 - */ - public abstract void initIndexInfo(ExecuteContext context); - - /** - * 填充报文信息 + * 填充错误统计信息 * - * @param currentWriteIndex 当前读索引下标 - * @param currentReadIndex 当前写索引下标 - * @param context 上下文信息 + * @param status 响应编码 + * @param metricsRpcInfo 指标信息 */ - protected void fillMessageInfo(int currentWriteIndex, int currentReadIndex, ExecuteContext context) { - Object linkInfoObject = context.getLocalFieldValue(Constants.LINK_INFO_KEY); - if (!(linkInfoObject instanceof MetricsLinkInfo)) { - return; - } - MetricsLinkInfo metricsLinkInfo = (MetricsLinkInfo) linkInfoObject; - if (StringUtils.equals(context.getMethod().getName(), ENCODE_METHOD_NAME)) { - Object writeIndex = context.getLocalFieldValue(Constants.WRITE_INDEX_KEY); - if (!(writeIndex instanceof Integer)) { - return; - } - int addWriteIndex = currentWriteIndex - Integer.parseInt(StringUtils.getString(writeIndex)); - if (addWriteIndex > 0) { - metricsLinkInfo.getSentBytes().addAndGet(addWriteIndex); - metricsLinkInfo.getSentMessages().incrementAndGet(); - } + public void fillErrorCountInfo(byte status, MetricsRpcInfo metricsRpcInfo) { + int value = ResultJudgmentUtil.judgeDubboResult(status); + if (value == ResultType.SUCCESS.getValue()) { return; } - Object readIndex = context.getLocalFieldValue(Constants.READ_INDEX_KEY); - if (!(readIndex instanceof Integer)) { + if (value == ResultType.CLIENT_ERROR.getValue()) { + metricsRpcInfo.getClientErrorCount().getAndIncrement(); return; } - int addReadIndex = currentReadIndex - Integer.parseInt(StringUtils.getString(readIndex)); - if (addReadIndex > 0) { - metricsLinkInfo.getReceiveBytes().addAndGet(addReadIndex); - metricsLinkInfo.getReceiveMessages().incrementAndGet(); + if (value == ResultType.SERVER_ERROR.getValue()) { + metricsRpcInfo.getServerErrorCount().getAndIncrement(); } } - - /** - * 填充报文信息 - * - * @param context 上下文信息 - */ - protected abstract void fillMessageInfo(ExecuteContext context); } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractFilterInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractFilterInterceptor.java index ad3ff95117..7bdc46dbdf 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractFilterInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractFilterInterceptor.java @@ -39,10 +39,7 @@ public ExecuteContext before(ExecuteContext context) { return context; } long startTime = System.nanoTime(); - MetricsRpcInfo metricsRpcInfo = initRpcInfo(context); - metricsRpcInfo.getReqCount().incrementAndGet(); context.setLocalFieldValue(Constants.START_TIME_KEY, startTime); - context.setLocalFieldValue(Constants.RPC_INFO_KEY, metricsRpcInfo); return context; } @@ -55,16 +52,13 @@ public ExecuteContext after(ExecuteContext context) { if (!(startTimeObject instanceof Long)) { return context; } - Object metrcisObject = context.getLocalFieldValue(Constants.RPC_INFO_KEY); - if (!(metrcisObject instanceof MetricsRpcInfo)) { - return context; - } - long startTime = Long.parseLong(StringUtils.getString(startTimeObject)); - MetricsRpcInfo metricsRpcInfo = (MetricsRpcInfo) metrcisObject; + MetricsRpcInfo metricsRpcInfo = initRpcInfo(context); + metricsRpcInfo.getReqCount().incrementAndGet(); metricsRpcInfo.getResponseCount().incrementAndGet(); - long latency = System.nanoTime() - startTime; + long latency = System.nanoTime() - (long) startTimeObject; metricsRpcInfo.getSumLatency().addAndGet(latency); metricsRpcInfo.getLatencyList().add(latency); + MetricsManager.saveRpcInfo(metricsRpcInfo); return context; } @@ -120,12 +114,7 @@ private boolean isClientSide(String side) { */ public MetricsRpcInfo initRpcInfo(InetSocketAddress localAddress, InetSocketAddress remoteAddress, String side, boolean sslEnable, String protocol) { - String metricsKey = localAddress.getHostName() + Constants.CONNECT + remoteAddress.getHostName() - + Constants.CONNECT + remoteAddress.getPort(); - MetricsRpcInfo metricsRpcInfo = MetricsManager.getRpcInfo(metricsKey); - if (!StringUtils.isEmpty(metricsRpcInfo.getClientIp())) { - return metricsRpcInfo; - } + MetricsRpcInfo metricsRpcInfo = new MetricsRpcInfo(); metricsRpcInfo.setProtocol(protocol); if (isClientSide(side)) { initAddressAndRole(metricsRpcInfo, localAddress, remoteAddress, Constants.CLIENT_ROLE); diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractHttpInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractHttpInterceptor.java new file mode 100644 index 0000000000..25392cdcad --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/AbstractHttpInterceptor.java @@ -0,0 +1,107 @@ +/* + * 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.ResultJudgmentUtil; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.agent.interceptor.Interceptor; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; + +/** + * Http拦截器父类 + * + * @author zhp + * @since 2023-12-15 + */ +public abstract class AbstractHttpInterceptor implements Interceptor { + @Override + public ExecuteContext after(ExecuteContext context) throws Exception { + return collectMetrics(context); + } + + /** + * 采集指标信息 + * + * @param context 上下文信息 + * @return ExecuteContext 上下文信息 + * @throws Exception 指标采集异常 + */ + public abstract ExecuteContext collectMetrics(ExecuteContext context) throws Exception; + + @Override + public ExecuteContext onThrow(ExecuteContext context) throws Exception { + return collectMetrics(context); + } + + /** + * 初始化指标信息 + * + * @param url 链接信息 + * @param enableSsl 是否开启SSL加密 + * @param latency 时延 + * @param statusCode 结果编码 + * @return 指标数据 + * @throws UnknownHostException 未知域名异常 + */ + public MetricsRpcInfo initMetricsInfo(URL url, boolean enableSsl, long latency, int statusCode) + throws UnknownHostException { + MetricsRpcInfo metricsRpcInfo = new MetricsRpcInfo(); + metricsRpcInfo.setClientIp(InetAddress.getLocalHost().getHostAddress()); + metricsRpcInfo.setServerIp(url.getHost()); + metricsRpcInfo.setServerPort(StringUtils.getString(url.getPort())); + metricsRpcInfo.setProtocol(url.getProtocol()); + metricsRpcInfo.setEnableSsl(enableSsl); + metricsRpcInfo.setL7Role(Constants.CLIENT_ROLE); + metricsRpcInfo.setL4Role(Constants.TCP_PROTOCOL + Constants.CONNECT + metricsRpcInfo.getL7Role()); + metricsRpcInfo.setUrl(url.getPath()); + metricsRpcInfo.getReqCount().getAndIncrement(); + metricsRpcInfo.getResponseCount().getAndIncrement(); + metricsRpcInfo.getLatencyList().add(latency); + metricsRpcInfo.getSumLatency().getAndAdd(latency); + fillErrorCountInfo(statusCode, metricsRpcInfo); + return metricsRpcInfo; + } + + /** + * 填充错误数量 + * + * @param statusCode 状态编码 + * @param metricsRpcInfo 指标数据 + */ + public void fillErrorCountInfo(int statusCode, MetricsRpcInfo metricsRpcInfo) { + int value = ResultJudgmentUtil.judgeHttpResult(statusCode); + if (value == ResultType.SUCCESS.getValue()) { + return; + } + metricsRpcInfo.getReqErrorCount().getAndIncrement(); + if (value == ResultType.CLIENT_ERROR.getValue()) { + metricsRpcInfo.getClientErrorCount().getAndIncrement(); + return; + } + if (value == ResultType.SERVER_ERROR.getValue()) { + metricsRpcInfo.getServerErrorCount().getAndIncrement(); + } + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/ExchangeCodecInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/ExchangeCodecInterceptor.java similarity index 50% rename from sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/ExchangeCodecInterceptor.java rename to sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/ExchangeCodecInterceptor.java index 596ef3be1b..467b74228d 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/ExchangeCodecInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/ExchangeCodecInterceptor.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.huawei.metrics.interceptor.alibaba; +package com.huawei.metrics.interceptor.dubbo.alibaba; import com.huawei.metrics.common.Constants; -import com.huawei.metrics.entity.MetricsLinkInfo; +import com.huawei.metrics.entity.MetricsRpcInfo; import com.huawei.metrics.interceptor.AbstractCodecInterceptor; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.remoting.Channel; -import com.alibaba.dubbo.remoting.buffer.ChannelBuffer; +import com.alibaba.dubbo.remoting.exchange.Response; /** * dubbo报文转码、解码拦截器 @@ -33,42 +33,33 @@ * @since 2023-10-17 */ public class ExchangeCodecInterceptor extends AbstractCodecInterceptor { - private static final int PARAM_COUNT = 2; - - @Override - public boolean isValid(ExecuteContext context) { - Object[] arguments = context.getArguments(); - if (arguments == null || arguments.length < PARAM_COUNT) { - return false; - } - if (!(arguments[0] instanceof Channel)) { - return false; - } - if (!(arguments[1] instanceof ChannelBuffer)) { - return false; - } - return ((Channel) arguments[0]).getUrl() != null; - } - - @Override - public MetricsLinkInfo initLinkInfo(ExecuteContext context) { + /** + * 初始化指标信息 + * + * @param context 上下文信息 + * @return 连接信息 + */ + private MetricsRpcInfo initRpcInfo(ExecuteContext context) { Channel channel = (Channel) context.getArguments()[0]; URL url = channel.getUrl(); boolean sslEnable = Boolean.parseBoolean(url.getParameter(Constants.SSL_ENABLE)); - return initLinkInfo(channel.getLocalAddress(), channel.getRemoteAddress(), + MetricsRpcInfo metricsRpcInfo = initRpcInfo(channel.getLocalAddress(), channel.getRemoteAddress(), url.getParameter(Constants.SIDE_KEY), sslEnable, url.getProtocol()); + metricsRpcInfo.setUrl(url.getPath()); + return metricsRpcInfo; } @Override - public void initIndexInfo(ExecuteContext context) { - ChannelBuffer buffer = (ChannelBuffer) context.getArguments()[1]; - context.setLocalFieldValue(Constants.WRITE_INDEX_KEY, buffer.writerIndex()); - context.setLocalFieldValue(Constants.READ_INDEX_KEY, buffer.readerIndex()); - } - - @Override - protected void fillMessageInfo(ExecuteContext context) { - ChannelBuffer buffer = (ChannelBuffer) context.getArguments()[1]; - fillMessageInfo(buffer.writerIndex(), buffer.readerIndex(), context); + public ExecuteContext after(ExecuteContext context) { + if (!(context.getResult() instanceof Response)) { + return context; + } + Response response = (Response) context.getResult(); + if (response.isHeartbeat() || response.isEvent()) { + return context; + } + MetricsRpcInfo metricsRpcInfo = initRpcInfo(context); + fillErrorCountInfo(response.getStatus(), metricsRpcInfo); + return context; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/MonitorFilterInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/MonitorFilterInterceptor.java similarity index 87% rename from sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/MonitorFilterInterceptor.java rename to sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/MonitorFilterInterceptor.java index c0afcbffeb..70d94883df 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/alibaba/MonitorFilterInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/alibaba/MonitorFilterInterceptor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.huawei.metrics.interceptor.alibaba; +package com.huawei.metrics.interceptor.dubbo.alibaba; import com.huawei.metrics.common.Constants; import com.huawei.metrics.entity.MetricsRpcInfo; @@ -44,7 +44,9 @@ public MetricsRpcInfo initRpcInfo(ExecuteContext context) { RpcContext rpcContext = RpcContext.getContext(); URL url = rpcContext.getUrl(); boolean sslEnable = Boolean.parseBoolean(url.getParameter(Constants.SSL_ENABLE)); - return initRpcInfo(rpcContext.getLocalAddress(), rpcContext.getRemoteAddress(), + MetricsRpcInfo metricsRpcInfo = initRpcInfo(rpcContext.getLocalAddress(), rpcContext.getRemoteAddress(), url.getParameter(Constants.SIDE_KEY), sslEnable, url.getProtocol()); + metricsRpcInfo.setUrl(url.getPath()); + return metricsRpcInfo; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/ExchangeCodecInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/ExchangeCodecInterceptor.java similarity index 50% rename from sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/ExchangeCodecInterceptor.java rename to sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/ExchangeCodecInterceptor.java index 9004828bab..0ff576a0f4 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/ExchangeCodecInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/ExchangeCodecInterceptor.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.huawei.metrics.interceptor.apache; +package com.huawei.metrics.interceptor.dubbo.apache; import com.huawei.metrics.common.Constants; -import com.huawei.metrics.entity.MetricsLinkInfo; +import com.huawei.metrics.entity.MetricsRpcInfo; import com.huawei.metrics.interceptor.AbstractCodecInterceptor; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import org.apache.dubbo.common.URL; import org.apache.dubbo.remoting.Channel; -import org.apache.dubbo.remoting.buffer.ChannelBuffer; +import org.apache.dubbo.remoting.exchange.Response; /** * dubbo报文转码、解码拦截器 @@ -33,42 +33,33 @@ * @since 2023-10-17 */ public class ExchangeCodecInterceptor extends AbstractCodecInterceptor { - private static final int PARAM_COUNT = 2; - - @Override - public boolean isValid(ExecuteContext context) { - Object[] arguments = context.getArguments(); - if (arguments == null || arguments.length < PARAM_COUNT) { - return false; - } - if (!(arguments[0] instanceof Channel)) { - return false; - } - if (!(arguments[1] instanceof ChannelBuffer)) { - return false; - } - return ((Channel) arguments[0]).getUrl() != null; - } - - @Override - public MetricsLinkInfo initLinkInfo(ExecuteContext context) { + /** + * 初始化指标信息 + * + * @param context 上下文信息 + * @return 连接信息 + */ + private MetricsRpcInfo initRpcInfo(ExecuteContext context) { Channel channel = (Channel) context.getArguments()[0]; URL url = channel.getUrl(); boolean sslEnable = Boolean.parseBoolean(url.getParameter(Constants.SSL_ENABLE)); - return initLinkInfo(channel.getLocalAddress(), channel.getRemoteAddress(), + MetricsRpcInfo metricsRpcInfo = initRpcInfo(channel.getLocalAddress(), channel.getRemoteAddress(), url.getParameter(Constants.SIDE_KEY), sslEnable, url.getProtocol()); + metricsRpcInfo.setUrl(url.getPath()); + return metricsRpcInfo; } @Override - public void initIndexInfo(ExecuteContext context) { - ChannelBuffer buffer = (ChannelBuffer) context.getArguments()[1]; - context.setLocalFieldValue(Constants.WRITE_INDEX_KEY, buffer.writerIndex()); - context.setLocalFieldValue(Constants.READ_INDEX_KEY, buffer.readerIndex()); - } - - @Override - protected void fillMessageInfo(ExecuteContext context) { - ChannelBuffer buffer = (ChannelBuffer) context.getArguments()[1]; - fillMessageInfo(buffer.writerIndex(), buffer.readerIndex(), context); + public ExecuteContext after(ExecuteContext context) { + if (!(context.getResult() instanceof Response)) { + return context; + } + Response response = (Response) context.getResult(); + if (response.isHeartbeat() || response.isEvent()) { + return context; + } + MetricsRpcInfo metricsRpcInfo = initRpcInfo(context); + fillErrorCountInfo(response.getStatus(), metricsRpcInfo); + return context; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/MonitorFilterInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/MonitorFilterInterceptor.java similarity index 87% rename from sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/MonitorFilterInterceptor.java rename to sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/MonitorFilterInterceptor.java index 70aa2efc5f..09d2e71eb5 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/apache/MonitorFilterInterceptor.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/dubbo/apache/MonitorFilterInterceptor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.huawei.metrics.interceptor.apache; +package com.huawei.metrics.interceptor.dubbo.apache; import com.huawei.metrics.common.Constants; import com.huawei.metrics.entity.MetricsRpcInfo; @@ -44,7 +44,9 @@ public MetricsRpcInfo initRpcInfo(ExecuteContext context) { RpcContext rpcContext = RpcContext.getContext(); URL url = rpcContext.getUrl(); boolean sslEnable = Boolean.parseBoolean(url.getParameter(Constants.SSL_ENABLE)); - return initRpcInfo(rpcContext.getLocalAddress(), rpcContext.getRemoteAddress(), + MetricsRpcInfo metricsRpcInfo = initRpcInfo(rpcContext.getLocalAddress(), rpcContext.getRemoteAddress(), url.getParameter(Constants.SIDE_KEY), sslEnable, url.getProtocol()); + metricsRpcInfo.setUrl(url.getPath()); + return metricsRpcInfo; } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpclient/HttpClientInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpclient/HttpClientInterceptor.java new file mode 100644 index 0000000000..5795406f02 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpclient/HttpClientInterceptor.java @@ -0,0 +1,59 @@ +/* + * 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.httpclient; + +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.interceptor.AbstractHttpInterceptor; +import com.huawei.metrics.manager.MetricsManager; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; + +import java.net.URI; + +/** + * HttpClient请求发送增强器 + * + * @author zhp + * @since 2023-12-15 + */ +public class HttpClientInterceptor extends AbstractHttpInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + context.setLocalFieldValue(Constants.START_TIME_KEY, System.nanoTime()); + return context; + } + + @Override + public ExecuteContext collectMetrics(ExecuteContext context) throws Exception { + HttpHost httpHost = (HttpHost) context.getArguments()[0]; + HttpRequest httpRequest = (HttpRequest) context.getArguments()[1]; + URI uri = new URI(httpRequest.getRequestLine().getUri()); + long latency = System.nanoTime() - (Long) context.getLocalFieldValue(Constants.START_TIME_KEY); + HttpResponse httpResponse = (HttpResponse) context.getResult(); + int statusCode = httpResponse.getStatusLine().getStatusCode(); + boolean enableSsl = StringUtils.equals(httpHost.getSchemeName(), Constants.HTTPS_PROTOCOL); + MetricsRpcInfo metricsRpcInfo = initMetricsInfo(uri.toURL(), enableSsl, latency, statusCode); + MetricsManager.saveRpcInfo(metricsRpcInfo); + return context; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/ConnectorInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/ConnectorInterceptor.java new file mode 100644 index 0000000000..d3d4e8a55a --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/ConnectorInterceptor.java @@ -0,0 +1,47 @@ +/* + * 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.httpurlconnection; + +import com.huawei.metrics.util.HttpUrlConnectionUtil; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.plugin.agent.interceptor.Interceptor; + +/** + * HttpUrlConnection连接方法增强器 + * + * @author zhp + * @since 2023-12-15 + */ +public class ConnectorInterceptor implements Interceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + // 设置请求开始时间,链接断开时用于计算时延 + HttpUrlConnectionUtil.setValue(System.nanoTime()); + return context; + } + + @Override + public ExecuteContext after(ExecuteContext context) { + return context; + } + + @Override + public ExecuteContext onThrow(ExecuteContext context) { + return context; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/DisconnectorInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/DisconnectorInterceptor.java new file mode 100644 index 0000000000..0a737839d8 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/httpurlconnection/DisconnectorInterceptor.java @@ -0,0 +1,57 @@ +/* + * 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.httpurlconnection; + +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.interceptor.AbstractHttpInterceptor; +import com.huawei.metrics.manager.MetricsManager; +import com.huawei.metrics.util.HttpUrlConnectionUtil; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * 连接断开方法增强器 + * + * @author zhp + * @since 2023-12-15 + */ +public class DisconnectorInterceptor extends AbstractHttpInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + return context; + } + + @Override + public ExecuteContext collectMetrics(ExecuteContext context) throws Exception { + if (HttpUrlConnectionUtil.getValue() == null) { + return context; + } + HttpURLConnection httpUrlConnection = (HttpURLConnection) context.getObject(); + URL url = httpUrlConnection.getURL(); + boolean enableSsl = StringUtils.equals(url.getProtocol(), Constants.HTTPS_PROTOCOL); + long latency = System.nanoTime() - HttpUrlConnectionUtil.getValue(); + MetricsRpcInfo metricsRpcInfo = initMetricsInfo(url, enableSsl, latency, httpUrlConnection.getResponseCode()); + MetricsManager.saveRpcInfo(metricsRpcInfo); + HttpUrlConnectionUtil.remove(); + return context; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp/CallInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp/CallInterceptor.java new file mode 100644 index 0000000000..093e6c1305 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp/CallInterceptor.java @@ -0,0 +1,51 @@ +/* + * 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.okhttp; + +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.interceptor.AbstractHttpInterceptor; +import com.huawei.metrics.manager.MetricsManager; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; + +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +/** + * OKHttp请求发送增强器 + * + * @author zhp + * @since 2023-12-15 + */ +public class CallInterceptor extends AbstractHttpInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + context.setLocalFieldValue(Constants.START_TIME_KEY, System.nanoTime()); + return context; + } + + @Override + public ExecuteContext collectMetrics(ExecuteContext context) throws Exception { + Response response = (Response) context.getResult(); + Request request = response.request(); + long latency = System.nanoTime() - (Long) context.getLocalFieldValue(Constants.START_TIME_KEY); + MetricsRpcInfo metricsRpcInfo = initMetricsInfo(request.url(), request.isHttps(), latency, response.code()); + MetricsManager.saveRpcInfo(metricsRpcInfo); + return context; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp3/CallInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp3/CallInterceptor.java new file mode 100644 index 0000000000..130ced297c --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/okhttp3/CallInterceptor.java @@ -0,0 +1,56 @@ +/* + * 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.okhttp3; + +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.interceptor.AbstractHttpInterceptor; +import com.huawei.metrics.manager.MetricsManager; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; + +import okhttp3.Call; +import okhttp3.Request; +import okhttp3.Response; + +import java.net.URL; + +/** + * OKHttp3请求发送增强器 + * + * @author zhp + * @since 2023-12-15 + */ +public class CallInterceptor extends AbstractHttpInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + context.setLocalFieldValue(Constants.START_TIME_KEY, System.nanoTime()); + return context; + } + + @Override + public ExecuteContext collectMetrics(ExecuteContext context) throws Exception { + Call realCall = (Call) context.getObject(); + Request request = realCall.request(); + URL url = request.url().url(); + long latency = System.nanoTime() - (Long) context.getLocalFieldValue(Constants.START_TIME_KEY); + Response response = (Response) context.getResult(); + MetricsRpcInfo metricsRpcInfo = initMetricsInfo(url, request.url().isHttps(), latency, response.code()); + MetricsManager.saveRpcInfo(metricsRpcInfo); + return context; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/servlet/HttpServletInterceptor.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/servlet/HttpServletInterceptor.java new file mode 100644 index 0000000000..e83db99a79 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/interceptor/servlet/HttpServletInterceptor.java @@ -0,0 +1,78 @@ +/* + * 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.servlet; + +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsRpcInfo; +import com.huawei.metrics.interceptor.AbstractHttpInterceptor; +import com.huawei.metrics.manager.MetricsManager; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.utils.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * HttpServlet服务调用拦截声明 + * + * @author zhp + * @since 2023-12-15 + */ +public class HttpServletInterceptor extends AbstractHttpInterceptor { + @Override + public ExecuteContext before(ExecuteContext context) { + context.setLocalFieldValue(Constants.START_TIME_KEY, System.nanoTime()); + return context; + } + + @Override + public ExecuteContext collectMetrics(ExecuteContext context) { + HttpServletRequest req = (HttpServletRequest) context.getArguments()[0]; + long latency = System.nanoTime() - (Long) context.getLocalFieldValue(Constants.START_TIME_KEY); + HttpServletResponse resp = (HttpServletResponse) context.getArguments()[1]; + MetricsRpcInfo metricsRpcInfo = initMetricsInfo(req, latency, resp.getStatus()); + MetricsManager.saveRpcInfo(metricsRpcInfo); + return context; + } + + /** + * 初始化指标信息 + * + * @param req 请求数据 + * @param latency 时延 + * @param status 请求状态编码 + * @return Rpc指标数据 + */ + private MetricsRpcInfo initMetricsInfo(HttpServletRequest req, long latency, int status) { + MetricsRpcInfo metricsRpcInfo = new MetricsRpcInfo(); + metricsRpcInfo.setClientIp(req.getRemoteHost()); + metricsRpcInfo.setServerIp(req.getLocalAddr()); + metricsRpcInfo.setServerPort(StringUtils.getString(req.getLocalPort())); + metricsRpcInfo.setProtocol(req.getScheme()); + metricsRpcInfo.setEnableSsl(Constants.HTTPS_PROTOCOL.equals(req.getScheme())); + metricsRpcInfo.setL7Role(Constants.SERVER_ROLE); + metricsRpcInfo.setL4Role(Constants.TCP_PROTOCOL + Constants.CONNECT + metricsRpcInfo.getL7Role()); + metricsRpcInfo.setUrl(req.getRequestURI()); + metricsRpcInfo.getReqCount().getAndIncrement(); + metricsRpcInfo.getLatencyList().add(latency); + metricsRpcInfo.getSumLatency().getAndAdd(latency); + metricsRpcInfo.getResponseCount().getAndIncrement(); + fillErrorCountInfo(status, metricsRpcInfo); + return metricsRpcInfo; + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/manager/MetricsManager.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/manager/MetricsManager.java index d2010d6a04..c842c631a3 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/manager/MetricsManager.java +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/manager/MetricsManager.java @@ -16,7 +16,8 @@ package com.huawei.metrics.manager; -import com.huawei.metrics.entity.MetricsLinkInfo; +import com.huawei.metrics.common.Constants; +import com.huawei.metrics.entity.MetricsInfo; import com.huawei.metrics.entity.MetricsRpcInfo; import java.util.Map; @@ -29,48 +30,59 @@ * @since 2023-10-17 */ public class MetricsManager { - private static final Map METRICS_LINK_INFO_MAP = new ConcurrentHashMap<>(); - private static final Map METRICS_RPC_INFO_MAP = new ConcurrentHashMap<>(); private MetricsManager() { } /** - * 获取全部连接信息 + * 获取全部RPC信息 * * @return 连接信息 */ - public static Map getLinkInfoMap() { - return METRICS_LINK_INFO_MAP; + public static Map getRpcInfoMap() { + return METRICS_RPC_INFO_MAP; } /** - * 获取全部RPC信息 + * 保存RPC信息 * - * @return 连接信息 + * @param metricsRpcInfo RPC信息 */ - public static Map getRpcInfoMap() { - return METRICS_RPC_INFO_MAP; + public static void saveRpcInfo(MetricsRpcInfo metricsRpcInfo) { + String key = getKey(metricsRpcInfo); + MetricsRpcInfo rpcInfo = METRICS_RPC_INFO_MAP.computeIfAbsent(key, s -> metricsRpcInfo); + if (rpcInfo != metricsRpcInfo) { + rpcInfo.getReqCount().getAndAdd(metricsRpcInfo.getReqCount().get()); + rpcInfo.getResponseCount().getAndAdd(metricsRpcInfo.getResponseCount().get()); + rpcInfo.getSumLatency().getAndAdd(metricsRpcInfo.getSumLatency().get()); + rpcInfo.getLatencyList().addAll(metricsRpcInfo.getLatencyList()); + rpcInfo.getReqErrorCount().getAndAdd(metricsRpcInfo.getReqErrorCount().get()); + } } /** - * 获取连接信息 + * 获取Map的key * - * @param key MAP的密钥信息 - * @return 连接信息 + * @param metricsInfo 指标信息 + * @return key */ - public static MetricsLinkInfo getLinkInfo(String key) { - return METRICS_LINK_INFO_MAP.computeIfAbsent(key, s -> new MetricsLinkInfo()); + public static String getKey(MetricsInfo metricsInfo) { + return metricsInfo.getClientIp() + Constants.CONNECT + metricsInfo.getServerIp() + Constants.CONNECT + + metricsInfo.getServerPort() + Constants.CONNECT + metricsInfo.getProtocol() + Constants.CONNECT + + metricsInfo.getL4Role() + Constants.CONNECT + metricsInfo.isEnableSsl() + Constants.CONNECT + + metricsInfo.getUrl(); } /** - * 获取RPC信息 + * 获取Map的key * - * @param key MAP的密钥信息 - * @return RPC信息 + * @param metricsInfo 指标信息 + * @return key */ - public static MetricsRpcInfo getRpcInfo(String key) { - return METRICS_RPC_INFO_MAP.computeIfAbsent(key, s -> new MetricsRpcInfo()); + public static String getRpcKey(MetricsInfo metricsInfo) { + return metricsInfo.getClientIp() + Constants.CONNECT + metricsInfo.getServerIp() + Constants.CONNECT + + metricsInfo.getServerPort() + Constants.CONNECT + metricsInfo.getProtocol() + Constants.CONNECT + + metricsInfo.getL4Role() + Constants.CONNECT + metricsInfo.isEnableSsl(); } } diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/HttpUrlConnectionUtil.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/HttpUrlConnectionUtil.java new file mode 100644 index 0000000000..a7b9137f6c --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/HttpUrlConnectionUtil.java @@ -0,0 +1,61 @@ +/* + * 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; + +/** + * HttpUrlConnection工具类,用于线程数据传递 + * + * @author zhp + * @since 2023-12-15 + */ +public class HttpUrlConnectionUtil { + /** + * 线程变量存储,主要存储请求开始时间 + */ + private static final ThreadLocal START_TIME_THREAD_LOCAL = new InheritableThreadLocal<>(); + + /** + * 构造函数 + */ + private HttpUrlConnectionUtil() { + } + + /** + * 设置线程变量 + * + * @param value 变量信息 + */ + public static void setValue(Long value) { + START_TIME_THREAD_LOCAL.set(value); + } + + /** + * 获取线程变量 + * + * @return 变量信息 + */ + public static Long getValue() { + return START_TIME_THREAD_LOCAL.get(); + } + + /** + * 删除线程变量信息 + */ + public static void remove() { + START_TIME_THREAD_LOCAL.remove(); + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/ResultJudgmentUtil.java b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/ResultJudgmentUtil.java new file mode 100644 index 0000000000..44045823d0 --- /dev/null +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/java/com/huawei/metrics/util/ResultJudgmentUtil.java @@ -0,0 +1,91 @@ +/* + * 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.huawei.metrics.common.ResultType; + +/** + * 结果判断工具类 + * + * @author zhp + * @since 2023-12-15 + */ +public class ResultJudgmentUtil { + private ResultJudgmentUtil() { + } + + /** + * 判断HTTP的请求结果 + * + * @param statusCode 结果编码 + * @return 结果类型 + */ + public static int judgeHttpResult(int statusCode) { + if (statusCode <= Constants.MAX_SUCCESS_CODE) { + return ResultType.SUCCESS.getValue(); + } + if (statusCode <= Constants.MAX_CLIENT_ERROR_CODE) { + return ResultType.CLIENT_ERROR.getValue(); + } + if (statusCode <= Constants.MAX_SERVER_ERROR_CODE) { + return ResultType.SERVER_ERROR.getValue(); + } + return ResultType.ERROR.getValue(); + } + + /** + * 判断Dubbo的请求结果 + * + * @param status 结果编码 + * @return 结果类型 + */ + public static int judgeDubboResult(byte status) { + if (status == Constants.HTTP_OK) { + return ResultType.SUCCESS.getValue(); + } + for (int i = 0; i < Constants.HTTP_CLIENT_ERROR.length; i++) { + if (status == Constants.HTTP_CLIENT_ERROR[i]) { + return ResultType.CLIENT_ERROR.getValue(); + } + } + for (int i = 0; i < Constants.HTTP_SERVER_ERROR.length; i++) { + if (status == Constants.HTTP_SERVER_ERROR[i]) { + return ResultType.SERVER_ERROR.getValue(); + } + } + return ResultType.ERROR.getValue(); + } + + /** + * 判断Mysql的请求结果 + * + * @param status 结果编码 + * @return 结果类型 + */ + public static int judgeMysqlResult(int status) { + if (status >= Constants.MYSQL_CLIENT_ERROR[0][0] && status <= Constants.MYSQL_CLIENT_ERROR[0][1] + || status >= Constants.MYSQL_CLIENT_ERROR[1][0] && status <= Constants.MYSQL_CLIENT_ERROR[1][1]) { + return ResultType.CLIENT_ERROR.getValue(); + } + if (status >= Constants.MYSQL_SERVER_ERROR[0][0] && status <= Constants.MYSQL_SERVER_ERROR[0][1] + || status >= Constants.MYSQL_SERVER_ERROR[1][0] && status <= Constants.MYSQL_SERVER_ERROR[1][1]) { + return ResultType.SERVER_ERROR.getValue(); + } + return ResultType.ERROR.getValue(); + } +} diff --git a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer index 67b4daa9be..5a623188dc 100644 --- a/sermant-plugins/sermant-metrics/metrics-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer +++ b/sermant-plugins/sermant-metrics/metrics-plugin/src/main/resources/META-INF/services/com.huaweicloud.sermant.core.plugin.agent.declarer.PluginDeclarer @@ -18,4 +18,10 @@ com.huawei.metrics.declarer.alibaba.ExchangeCodecDeclarer com.huawei.metrics.declarer.alibaba.MonitorFilterDeclarer com.huawei.metrics.declarer.apache.ExchangeCodecDeclarer -com.huawei.metrics.declarer.apache.MonitorFilterDeclarer \ No newline at end of file +com.huawei.metrics.declarer.apache.MonitorFilterDeclarer +com.huawei.metrics.declarer.httpurlconnection.ConnectDeclarer +com.huawei.metrics.declarer.httpurlconnection.DisconnectDeclarer +com.huawei.metrics.declarer.httpclient.HttpClientDeclarer +com.huawei.metrics.declarer.okhttp.CallDeclarer +com.huawei.metrics.declarer.okhttp3.CallDeclarer +com.huawei.metrics.declarer.servlet.HttpServletDeclarer \ No newline at end of file diff --git a/sermant-plugins/sermant-metrics/metrics-service/src/main/java/com/huawei/metrics/service/MetricsService.java b/sermant-plugins/sermant-metrics/metrics-service/src/main/java/com/huawei/metrics/service/MetricsService.java index e33080fece..a980d23009 100644 --- a/sermant-plugins/sermant-metrics/metrics-service/src/main/java/com/huawei/metrics/service/MetricsService.java +++ b/sermant-plugins/sermant-metrics/metrics-service/src/main/java/com/huawei/metrics/service/MetricsService.java @@ -18,7 +18,6 @@ import com.huawei.metrics.common.Constants; import com.huawei.metrics.config.MetricsConfig; -import com.huawei.metrics.entity.MetricsLinkInfo; import com.huawei.metrics.entity.MetricsRpcInfo; import com.huawei.metrics.manager.MetricsManager; @@ -30,19 +29,18 @@ import com.alibaba.fastjson.JSONObject; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.math.BigDecimal; import java.math.RoundingMode; -import java.net.InetAddress; import java.nio.channels.FileLock; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -61,14 +59,12 @@ public class MetricsService implements PluginService { private static final MetricsConfig METRICS_CONFIG = PluginConfigManager.getPluginConfig(MetricsConfig.class); - private static final int CONTAINER_NAME_INDEX = 2; - private static final int ENABLE_NUM = 2; /** - * 换行符。Gopher解析时需要用到 System.lineSeparator()在UNIX返回"\n" 在Windows 返回"\r\n". 因此不能修改为System.lineSeparator(); + * 换行符。Gopher解析时需要用到。 System.lineSeparator()在UNIX返回"\n",在Windows 返回"\r\n".因此不能修改为System.lineSeparator(); */ - private static final String LINE_BREAK = "|\r\n"; + private static final String LINE_BREAK = "\r\n"; private static final BigDecimal MS_TO_S = new BigDecimal(1000); @@ -83,31 +79,6 @@ public class MetricsService implements PluginService { */ private String pid; - /** - * 进程名称 - */ - private String processName; - - /** - * 机器Id - */ - private String machineId; - - /** - * 容器ID - */ - private String containerId; - - /** - * 容器名称 - */ - private String containerName; - - /** - * 容器IP - */ - private String containerIp; - /** * 文件名称 */ @@ -125,13 +96,9 @@ public void start() { int index = name.indexOf(Constants.PROCESS_NAME_LINK); if (index != -1) { pid = name.substring(0, index); - processName = name.substring(index + 1); } else { pid = Constants.EXCEPTION_PID; - processName = StringUtils.EMPTY; } - initMachineId(); - initContainerInfo(); String filePath = METRICS_CONFIG.getFilePath() + pid; metricsFileName = filePath + Constants.FILE_PATH_LINK + METRICS_CONFIG.getFileName(); try { @@ -141,7 +108,7 @@ public void start() { return; } executorService = Executors.newScheduledThreadPool(1, new ThreadFactoryUtils("metrics")); - executorService.scheduleAtFixedRate(this::writeMetricData, METRICS_CONFIG.getDelayTime(), + executorService.scheduleWithFixedDelay(this::writeMetricData, METRICS_CONFIG.getDelayTime(), METRICS_CONFIG.getPeriod(), TimeUnit.MILLISECONDS); } @@ -156,171 +123,156 @@ public void stop() { * 把指标数据写进文件里 */ private void writeMetricData() { - if (MetricsManager.getLinkInfoMap().isEmpty() && MetricsManager.getRpcInfoMap().isEmpty()) { + if (MetricsManager.getRpcInfoMap().isEmpty()) { return; } try (RandomAccessFile raf = new RandomAccessFile(metricsFileName, "rw"); FileLock lock = raf.getChannel().lock()) { raf.seek(raf.length()); - writeLinkData(raf); - writeRpcData(raf); + reportData(raf); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Exception writing indicator data to file.", e); } } /** - * 写连接数据 + * 写RPC API数据 * - * @param raf 文件连接 + * @param raf 文件内容访问类 * @throws IOException 文件写入异常 */ - private void writeLinkData(RandomAccessFile raf) throws IOException { - StringBuilder stringBuilder = new StringBuilder(Constants.METRICS_LINK + Constants.LINK_HEAD); - for (Entry entry : MetricsManager.getLinkInfoMap().entrySet()) { - MetricsLinkInfo originalLinkInfo = entry.getValue(); - if (originalLinkInfo.getSentMessages().get() == 0 || originalLinkInfo.getReceiveMessages().get() == 0) { + private void reportData(RandomAccessFile raf) throws IOException { + Map rpcInfoMap = new HashMap<>(); + StringBuilder stringBuilder = new StringBuilder(); + for (Entry entry : MetricsManager.getRpcInfoMap().entrySet()) { + MetricsRpcInfo metricsRpcInfo = JSONObject.parseObject(JSONObject.toJSONString(entry.getValue()), + MetricsRpcInfo.class); + if (metricsRpcInfo.getReqCount().get() == 0 || metricsRpcInfo.getResponseCount().get() == 0 + || metricsRpcInfo.getSumLatency().get() == 0) { + continue; + } + reportBaseInfo(metricsRpcInfo, raf, Constants.RPC_API_HEADER); + raf.write((metricsRpcInfo.getUrl() + Constants.METRICS_LINK).getBytes(StandardCharsets.UTF_8)); + BigDecimal clientErrorCount = new BigDecimal(metricsRpcInfo.getClientErrorCount().get()); + BigDecimal reqCount = new BigDecimal(metricsRpcInfo.getReqCount().get()); + BigDecimal clientErrorRatio = clientErrorCount.multiply(TO_PERCENT) + .divide(reqCount, ENABLE_NUM, RoundingMode.HALF_UP); + BigDecimal serverErrorCount = new BigDecimal(metricsRpcInfo.getServerErrorCount().get()); + BigDecimal serverErrorRatio = serverErrorCount.multiply(TO_PERCENT).divide(reqCount, ENABLE_NUM, + RoundingMode.HALF_UP); + BigDecimal errorCount = new BigDecimal(metricsRpcInfo.getReqErrorCount().get()); + BigDecimal errorRatio = errorCount.multiply(TO_PERCENT).divide(reqCount, ENABLE_NUM, RoundingMode.HALF_UP); + stringBuilder.append(errorCount).append(Constants.METRICS_LINK).append(clientErrorCount) + .append(Constants.METRICS_LINK).append(serverErrorCount) + .append(Constants.METRICS_LINK).append(errorRatio).append(Constants.METRICS_LINK) + .append(clientErrorRatio).append(Constants.METRICS_LINK) + .append(serverErrorRatio).append(Constants.METRICS_LINK).append(LINE_BREAK); + reportCommonInfo(metricsRpcInfo, raf, stringBuilder.toString()); + stringBuilder.setLength(0); + cleanReportData(metricsRpcInfo); + countDataInfo(metricsRpcInfo, rpcInfoMap); + } + for (Entry entry : rpcInfoMap.entrySet()) { + MetricsRpcInfo metricsRpcInfo = entry.getValue(); + if (metricsRpcInfo.getReqCount().get() == 0 || metricsRpcInfo.getResponseCount().get() == 0 + || metricsRpcInfo.getSumLatency().get() == 0) { continue; } - MetricsLinkInfo metricsLinkInfo = JSONObject.parseObject(JSONObject.toJSONString(originalLinkInfo), - MetricsLinkInfo.class); - String metricsInfoStr = stringBuilder.append(Constants.METRICS_LINK).append(pid) - .append(Constants.METRICS_LINK).append(metricsLinkInfo.getClientIp()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getServerIp()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getServerPort()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getL4Role()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getL7Role()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getProtocol()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.isEnableSsl() ? Constants.SSL_OPEN : Constants.SSL_CLOSE) - .append(Constants.METRICS_LINK).append(metricsLinkInfo.getSentBytes().get()) - .append(Constants.METRICS_LINK).append(metricsLinkInfo.getSentMessages().get()) - .append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getReceiveBytes().get()).append(Constants.METRICS_LINK) - .append(metricsLinkInfo.getReceiveMessages().get()).toString(); - raf.write(metricsInfoStr.getBytes(Charset.defaultCharset())); - raf.write(LINE_BREAK.getBytes(Charset.defaultCharset())); + reportBaseInfo(metricsRpcInfo, raf, Constants.RPC_HEADER); + BigDecimal reqCount = new BigDecimal(metricsRpcInfo.getReqCount().get()); + BigDecimal errorCount = new BigDecimal(metricsRpcInfo.getReqErrorCount().get()); + BigDecimal errorRatio = errorCount.multiply(TO_PERCENT).divide(reqCount, ENABLE_NUM, RoundingMode.HALF_UP); + stringBuilder.append(errorCount).append(Constants.METRICS_LINK).append(errorRatio) + .append(Constants.METRICS_LINK).append(LINE_BREAK); + reportCommonInfo(metricsRpcInfo, raf, stringBuilder.toString()); stringBuilder.setLength(0); - originalLinkInfo.getReceiveMessages().getAndAdd(-metricsLinkInfo.getReceiveMessages().get()); - originalLinkInfo.getReceiveBytes().getAndAdd(-metricsLinkInfo.getReceiveBytes().get()); - originalLinkInfo.getSentMessages().getAndAdd(-metricsLinkInfo.getSentMessages().get()); - originalLinkInfo.getSentBytes().getAndAdd(-metricsLinkInfo.getSentBytes().get()); } } /** - * 写RPC数据 + * 清除本次上报的数据 + * + * @param metricsRpcInfo 指标信息 + */ + private void cleanReportData(MetricsRpcInfo metricsRpcInfo) { + MetricsRpcInfo originalRpcInfo = MetricsManager.getRpcInfoMap().get(MetricsManager.getKey(metricsRpcInfo)); + originalRpcInfo.getReqErrorCount().getAndAdd(-metricsRpcInfo.getReqErrorCount().get()); + originalRpcInfo.getSumLatency().getAndAdd(-metricsRpcInfo.getSumLatency().get()); + originalRpcInfo.getResponseCount().getAndAdd(-metricsRpcInfo.getResponseCount().get()); + originalRpcInfo.getReqCount().getAndAdd(-metricsRpcInfo.getReqCount().get()); + originalRpcInfo.getLatencyList().removeAll(metricsRpcInfo.getLatencyList()); + } + + /** + * 写RPC和RPC API的基础信息 * - * @param raf 文件连接 + * @param metricsRpcInfo 指标信息 + * @param raf 文件内容访问类 + * @param head 指标头信息 * @throws IOException 文件写入异常 */ - private void writeRpcData(RandomAccessFile raf) throws IOException { + private void reportBaseInfo(MetricsRpcInfo metricsRpcInfo, RandomAccessFile raf, String head) throws IOException { StringBuilder stringBuilder = new StringBuilder(); - for (Entry entry : MetricsManager.getRpcInfoMap().entrySet()) { - MetricsRpcInfo originalRpcInfo = entry.getValue(); - if (originalRpcInfo.getReqCount().get() == 0 || originalRpcInfo.getResponseCount().get() == 0 - || originalRpcInfo.getSumLatency().get() == 0) { - continue; - } - MetricsRpcInfo metricsRpcInfo = JSONObject.parseObject(JSONObject.toJSONString(originalRpcInfo), - MetricsRpcInfo.class); - BigDecimal reqCount = new BigDecimal(metricsRpcInfo.getReqCount().get()); - BigDecimal resCount = new BigDecimal(metricsRpcInfo.getResponseCount().get()); - BigDecimal errorCount = new BigDecimal(metricsRpcInfo.getReqErrorCount().get()); - BigDecimal errorRatio = errorCount.multiply(TO_PERCENT).divide(resCount, ENABLE_NUM, RoundingMode.HALF_UP); - BigDecimal sumLatency = new BigDecimal(metricsRpcInfo.getSumLatency().get()); - BigDecimal avgLatency = sumLatency.divide(resCount, ENABLE_NUM, RoundingMode.HALF_UP); - BigDecimal reqThroughout = reqCount.multiply(MS_TO_S).divide(new BigDecimal(METRICS_CONFIG.getDelayTime()), - ENABLE_NUM, RoundingMode.HALF_UP); - BigDecimal resThroughout = resCount.multiply(MS_TO_S).divide(new BigDecimal(METRICS_CONFIG.getDelayTime()), - ENABLE_NUM, RoundingMode.HALF_UP); - String latencyHistogram = getLatencyHistogram(metricsRpcInfo.getLatencyList()); - String sslFlag = metricsRpcInfo.isEnableSsl() ? Constants.SSL_OPEN : Constants.SSL_CLOSE; - String metricsInfoStr = stringBuilder.append(Constants.METRICS_LINK).append(Constants.RPC_HEAD) - .append(Constants.METRICS_LINK).append(pid).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getClientIp()).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getServerIp()).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getServerPort()).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getL4Role()).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getL7Role()).append(Constants.METRICS_LINK) - .append(metricsRpcInfo.getProtocol()).append(Constants.METRICS_LINK) - .append(sslFlag).append(Constants.METRICS_LINK).append(reqThroughout).append(Constants.METRICS_LINK) - .append(resThroughout).append(Constants.METRICS_LINK).append(reqCount) - .append(Constants.METRICS_LINK).append(resCount).append(Constants.METRICS_LINK).append(avgLatency) - .append(Constants.METRICS_LINK).append(latencyHistogram).append(Constants.METRICS_LINK) - .append(sumLatency).append(Constants.METRICS_LINK).append(errorRatio).append(Constants.METRICS_LINK) - .append(errorCount).toString(); - raf.write(metricsInfoStr.getBytes(Charset.defaultCharset())); - raf.write(LINE_BREAK.getBytes(Charset.defaultCharset())); - stringBuilder.setLength(0); - originalRpcInfo.getReqErrorCount().getAndAdd(-metricsRpcInfo.getReqErrorCount().get()); - originalRpcInfo.getSumLatency().getAndAdd(-metricsRpcInfo.getSumLatency().get()); - originalRpcInfo.getResponseCount().getAndAdd(-metricsRpcInfo.getResponseCount().get()); - originalRpcInfo.getReqCount().getAndAdd(-metricsRpcInfo.getReqCount().get()); - originalRpcInfo.getLatencyList().removeAll(metricsRpcInfo.getLatencyList()); - } + String commonInfo = stringBuilder.append(Constants.METRICS_LINK).append(head) + .append(Constants.METRICS_LINK).append(pid).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getClientIp()).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getServerIp()).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getServerPort()).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getL4Role()).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getL7Role()).append(Constants.METRICS_LINK) + .append(metricsRpcInfo.getProtocol()).append(Constants.METRICS_LINK).toString(); + raf.write(commonInfo.getBytes(StandardCharsets.UTF_8)); + stringBuilder.setLength(0); } /** - * 初始化机器Id + * 写RPC和RPC API的公共信息 + * + * @param metricsRpcInfo 指标信息 + * @param raf 文件内容访问类 + * @param errorInfo 错误信息 + * @throws IOException 文件写入异常 */ - private void initMachineId() { - try { - ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "dmidecode -s system-uuid"); - Process process = processBuilder.start(); - try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - if (StringUtils.isExist(line)) { - machineId = line.trim(); - break; - } - } - } - int exitCode = process.waitFor(); - if (exitCode != 0) { - LOGGER.log(Level.WARNING, "Failed to execute command: dmidecode -s system-uuid."); - } - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Error executing command: dmidecode -s system-uuid.", e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LOGGER.log(Level.SEVERE, "Command execution interrupted.", e); - } - if (StringUtils.isEmpty(machineId)) { - machineId = StringUtils.EMPTY; - } + private void reportCommonInfo(MetricsRpcInfo metricsRpcInfo, RandomAccessFile raf, String errorInfo) + throws IOException { + BigDecimal reqCount = new BigDecimal(metricsRpcInfo.getReqCount().get()); + BigDecimal resCount = new BigDecimal(metricsRpcInfo.getResponseCount().get()); + BigDecimal sumLatency = new BigDecimal(metricsRpcInfo.getSumLatency().get()); + BigDecimal avgLatency = sumLatency.divide(resCount, ENABLE_NUM, RoundingMode.HALF_UP); + BigDecimal reqThroughout = reqCount.multiply(MS_TO_S).divide(new BigDecimal(METRICS_CONFIG.getDelayTime()), + ENABLE_NUM, RoundingMode.HALF_UP); + BigDecimal resThroughout = resCount.multiply(MS_TO_S).divide(new BigDecimal(METRICS_CONFIG.getDelayTime()), + ENABLE_NUM, RoundingMode.HALF_UP); + String latencyHistogram = getLatencyHistogram(metricsRpcInfo.getLatencyList()); + String sslFlag = metricsRpcInfo.isEnableSsl() ? Constants.SSL_OPEN : Constants.SSL_CLOSE; + StringBuilder stringBuilder = new StringBuilder(); + String metricsRpcInfoStr = stringBuilder.append(sslFlag).append(Constants.METRICS_LINK) + .append(reqThroughout).append(Constants.METRICS_LINK) + .append(resThroughout).append(Constants.METRICS_LINK).append(reqCount) + .append(Constants.METRICS_LINK).append(resCount).append(Constants.METRICS_LINK).append(avgLatency) + .append(Constants.METRICS_LINK).append(latencyHistogram).append(Constants.METRICS_LINK) + .append(sumLatency).append(Constants.METRICS_LINK).append(errorInfo).toString(); + raf.write(metricsRpcInfoStr.getBytes(StandardCharsets.UTF_8)); + stringBuilder.setLength(0); } /** - * 初始化容器信息 + * 统计RPC数据,非API维度 + * + * @param metricsRpcInfo 指标数据 + * @param rpcInfoMap 保存统计后的RPC数据 */ - private void initContainerInfo() { - try { - containerIp = InetAddress.getLocalHost().getHostAddress(); - ProcessBuilder processBuilder = new ProcessBuilder("cat", "/proc/self/cgroup"); - Process process = processBuilder.start(); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - if (line.contains("docker") || line.contains("kubepods")) { - String[] parts = line.split("/"); - containerId = parts[parts.length - 1]; - containerName = parts[parts.length - CONTAINER_NAME_INDEX]; - break; - } - } - int exitCode = process.waitFor(); - if (exitCode != 0) { - LOGGER.log(Level.WARNING, "Failed to get container ID."); - } - } catch (IOException | InterruptedException e) { - LOGGER.log(Level.SEVERE, "Failed to get container ID.", e); - } - if (StringUtils.isEmpty(containerId)) { - containerId = StringUtils.EMPTY; - } - if (StringUtils.isEmpty(containerName)) { - containerName = StringUtils.EMPTY; + private void countDataInfo(MetricsRpcInfo metricsRpcInfo, Map rpcInfoMap) { + String rpcKey = MetricsManager.getRpcKey(metricsRpcInfo); + MetricsRpcInfo rpcInfo = rpcInfoMap.get(rpcKey); + if (rpcInfo == null) { + rpcInfoMap.put(MetricsManager.getRpcKey(metricsRpcInfo), metricsRpcInfo); + } else { + rpcInfo.getReqErrorCount().getAndAdd(metricsRpcInfo.getReqErrorCount().get()); + rpcInfo.getSumLatency().getAndAdd(metricsRpcInfo.getSumLatency().get()); + rpcInfo.getResponseCount().getAndAdd(metricsRpcInfo.getResponseCount().get()); + rpcInfo.getReqCount().getAndAdd(metricsRpcInfo.getReqCount().get()); + rpcInfo.getLatencyList().addAll(metricsRpcInfo.getLatencyList()); } } @@ -334,11 +286,15 @@ private void initContainerInfo() { private void createTmpFile(String filePath, String fileName) throws IOException { File dir = new File(filePath); if (!dir.exists()) { - dir.mkdirs(); + boolean createDirFlag = dir.mkdirs(); + LOGGER.log(Level.INFO, "The folder does not exist, created the folder {0}.", + createDirFlag ? "successfully" : "failed"); } File file = new File(fileName); if (!file.exists()) { - file.createNewFile(); + boolean createFileFlag = file.createNewFile(); + LOGGER.log(Level.INFO, "{0} to create indicator collection file.", + createFileFlag ? "Successfully" : "Failed"); } }