This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 63ea3123b [type:feature] add logging-tencent-cls plugin. (#3873)
63ea3123b is described below

commit 63ea3123bff47d310a805ef127f5eba44ad00cb4
Author: yunlongn <[email protected]>
AuthorDate: Thu Sep 1 15:08:26 2022 +0800

    [type:feature] add logging-tencent-cls plugin. (#3873)
    
    * [type:feature] add logging-tencent-cls plugin
    
    * [type:feature] add logging-tencent-cls data in sql.
    
    * [type:feature] add logging-tencent-cls data in sql.
    
    * [type:feature] add logging-tencent-cls data in sql.
    
    * [type:feature] add logging-tencent-cls data in sql.
    
    * [type:feature] add logging-tencent-cls plugin.
    
    * [type:feature] add logging-tencent-cls plugin.
    
    * [type:feature] exclusion artifactId.
    
    * [type:feature] exclusion artifactId.
    
    * [type:feat] move loggingTencentCls sql.
    
    * [type:feat] move loggingTencentCls sql.
    
    * [type:feat] move loggingTencentCls sql.
    
    * [type:feat] modify loggingTencentCls sql.
---
 db/init/mysql/schema.sql                           |  17 +
 db/init/oracle/schema.sql                          |  45 +++
 db/init/pg/create-table.sql                        |  17 +-
 db/upgrade/2.4.3-upgrade-2.5.0-mysql.sql           |   1 -
 db/upgrade/2.5.0-upgrade-2.5.1-mysql.sql           |  18 +
 db/upgrade/2.5.0-upgrade-2.5.1-oracle.sql          |  70 ++++
 db/upgrade/2.5.0-upgrade-2.5.1-pg.sql              |  18 +
 .../src/main/resources/sql-script/h2/schema.sql    |  16 +
 shenyu-bootstrap/pom.xml                           |   8 +
 .../org/apache/shenyu/common/enums/PluginEnum.java |   5 +
 .../src/main/release-docs/LICENSE                  |   1 +
 shenyu-plugin/shenyu-plugin-logging/pom.xml        |   1 +
 .../common/constant/GenericLoggingConstant.java    |  67 +++-
 .../shenyu-plugin-logging-tencent-cls/pom.xml      |  85 ++++
 .../tencent/cls/LoggingTencentClsPlugin.java       |  70 ++++
 .../cls/client/TencentClsLogCollectClient.java     | 224 +++++++++++
 .../cls/collector/TencentClsSlsLogCollector.java   |  45 +++
 .../cls/config/TencentLogCollectConfig.java        | 440 +++++++++++++++++++++
 .../LoggingTencentClsPluginDataHandler.java        | 101 +++++
 .../tencent/cls/LoggingTencentClsPluginTest.java   | 106 +++++
 .../collector/TencentClsSlsLogCollectorTest.java   |  61 +++
 .../cls/config/TencentLogCollectConfigTest.java    |  64 +++
 .../LoggingTencentClsPluginDataHandlerTest.java    |  65 +++
 .../tencentcls/TencentClsLogCollectClientTest.java |  95 +++++
 .../shenyu-spring-boot-starter-plugin/pom.xml      |   1 +
 .../pom.xml                                        |  38 +-
 .../cls/LoggingTencentClsPluginConfiguration.java  |  52 +++
 .../src/main/resources/META-INF/spring.factories   |  19 +
 .../src/main/resources/META-INF/spring.provides    |  18 +
 .../LoggingTencentClsPluginConfigurationTest.java  |  50 +++
 30 files changed, 1801 insertions(+), 17 deletions(-)

diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index d592ffd33..c839b5281 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -597,6 +597,7 @@ INSERT INTO `plugin` VALUES ('32', 
'loggingElasticSearch','{\"host\":\"localhost
 INSERT INTO `plugin` VALUES ('33', 'loggingKafka','{\"host\":\"localhost\", 
\"port\": \"9092\"}', 'Logging', 180, 0, '2022-07-04 22:00:00', '2022-07-02 
22:00:00');
 INSERT INTO `plugin` VALUES ('34', 'loggingAliyunSls','{\"projectName\": 
\"shenyu\", \"logStoreName\": \"shenyu-logstore\", \"topic\": 
\"shenyu-topic\"}', 'Logging', 175, 0, '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO `plugin` VALUES ('35', 'loggingPulsar', 
'{\"topic":\"shenyu-access-logging\", \"serviceUrl\": 
\"pulsar://localhost:6650\"}', 'Logging', 185, 0, '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin` VALUES ('36', 'loggingTencentCls','{\"endpoint\": 
\"ap-guangzhou.cls.tencentcs.com\", \"topic\": \"shenyu-topic\"}', 'Logging', 
176, 0, '2022-06-30 21:00:00', '2022-06-30 21:00:00');
 
 -- ----------------------------
 -- Table structure for plugin_handle
@@ -818,6 +819,22 @@ INSERT INTO `plugin_handle` VALUES ('1529402613204172908', 
'35', 'sampleRate', '
 INSERT INTO `plugin_handle` VALUES ('1529402613204172909', '35', 
'maxResponseBody', 'maxResponseBody', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 INSERT INTO `plugin_handle` VALUES ('1529402613204172910', '35', 
'maxRequestBody', 'maxRequestBody', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 INSERT INTO `plugin_handle` VALUES ('1529402613204172911', '35', 
'compressAlg', 'compressAlg', 3, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":\"none\"}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172912', '36', 'secretId', 
'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172913', '36', 'secretKey', 
'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172914', '36', 'endpoint', 
'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172915', '36', 'topic', 
'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172916', '36', 
'sendThreadCount', 'sendThreadCount', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172917', '36', 
'totalSizeInBytes', 'totalSizeInBytes', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":104857600}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172918', '36', 
'maxSendThreadCount', 'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}', '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172919', '36', 
'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172920', '36', 
'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172921', '36', 
'maxBatchCount', 'maxBatchCount', 1, 3, 10, 
'{\"required\":\"0\",\"defaultValue\":4096}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172922', '36', 'lingerMs', 
'lingerMs', 1, 3, 11, '{\"required\":\"0\",\"defaultValue\":2000}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172923', '36', 'retries', 
'retries', 1, 3, 12, '{\"required\":\"0\",\"defaultValue\":10}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172924', '36', 
'maxReservedAttempts', 'maxReservedAttempts', 1, 3, 13, 
'{\"required\":\"0\",\"defaultValue\":11}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172925', '36', 
'baseRetryBackoffMs', 'baseRetryBackoffMs', 1, 3, 14, 
'{\"required\":\"0\",\"defaultValue\":100}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172926', '36', 
'maxRetryBackoffMs', 'maxRetryBackoffMs', 1, 3, 15, 
'{\"required\":\"0\",\"defaultValue\":50000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+
 -- ----------------------------
 -- Table structure for resource
 -- ----------------------------
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 44be01687..6207917bb 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -855,6 +855,7 @@ INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO 
plugin (id, name, conf
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
config, role, sort, enabled) VALUES ('33', 'loggingKafka', 
'{"topic":"shenyu-access-logging", "namesrvAddr": "localhost:9092"}', 
'Logging', 180, 0);
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
config, role, sort, enabled) VALUES ('34', 'loggingAliyunSls', '{"projectName": 
"shenyu", "logStoreName": "shenyu-logstore", "topic": "shenyu-topic"}', 
'Logging', 175, '0');
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
config, role, sort, enabled) VALUES ('35', 'loggingPulsar', 
'{"topic":"shenyu-access-logging", "serviceUrl": "pulsar://localhost:6650"}', 
'Logging', 185, '0')
+INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
config, role, sort, enabled) VALUES ('36', 'loggingTencentCls', '{"endpoint": 
"ap-guangzhou.cls.tencentcs.com", "topic": "shenyu-topic"}', 'Logging', 176, 
'0');
 
 
 
@@ -1446,6 +1447,50 @@ values ('1518229897214468202', '35', 'maxRequestBody', 
'maxRequestBody', 1, 3, 6
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1518229897214468203', '35', 'compressAlg', 'compressAlg', 3, 3, 7, 
'{"required":"0","defaultValue":"none"}');
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468204', '36', 'secretId', 'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468205', '36', 'secretKey', 'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468206', '36', 'endpoint', 'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468207', '36', 'topic', 'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468208', '36', 'sendThreadCount', 'sendThreadCount', 1, 
3, 5, '{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468209', '36', 'totalSizeInBytes', 'totalSizeInBytes', 
1, 3, 6, '{\"required\":\"0\",\"defaultValue\":104857600}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468210', '36', 'maxSendThreadCount', 
'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468211', '36', 'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468206', '36', 'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468212', '36', 'maxBatchCount', 'maxBatchCount', 1, 3, 
10, '{\"required\":\"0\",\"defaultValue\":4096}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468213', '36', 'lingerMs', 'lingerMs', 1, 3, 11, 
'{\"required\":\"0\",\"defaultValue\":2000}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468214', '36', 'retries', 'retries', 1, 3, 12, 
'{\"required\":\"0\",\"defaultValue\":10}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468215', '36', 'maxReservedAttempts', 
'maxReservedAttempts', 1, 3, 13, '{\"required\":\"0\",\"defaultValue\":11}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468216', '36', 'baseRetryBackoffMs', 
'baseRetryBackoffMs', 1, 3, 14, '{\"required\":\"0\",\"defaultValue\":100}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468217', '36', 'maxRetryBackoffMs', 'maxRetryBackoffMs', 
1, 3, 15, '{\"required\":\"0\",\"defaultValue\":50000}');
 
 /** insert resource for resource */
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX("resource" (id)) */ INTO "resource"   
(id, parent_id, title, name, url, component, resource_type, sort, icon, 
is_leaf, is_route, perms, status) 
VALUES('1346775491550474240','','SHENYU.MENU.PLUGIN.LIST','plug','/plug','PluginList','0','0','dashboard','0','0','','1');
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index ca07fb578..9bd00cdae 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -674,7 +674,7 @@ INSERT INTO "public"."plugin" VALUES ('32', 
'loggingElasticSearch', '{"host":"lo
 INSERT INTO "public"."plugin" VALUES ('33', 'loggingKafka', 
'{"topic":"shenyu-access-logging", "namesrvAddr": "localhost:9092"}', 
'Logging', 180, 0, '2022-07-04 22:00:00', '2022-07-04 22:00:00');
 INSERT INTO "public"."plugin" VALUES ('34', 'loggingAliyunSls', 
'{"projectName": "shenyu", "logStoreName": "shenyu-logstore", "topic": 
"shenyu-topic"}', 'Logging', 175, 0, '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO "public"."plugin" VALUES ('35', 'loggingPulsar', 
'{"topic":"shenyu-access-logging", "serviceUrl": "pulsar://localhost:6650"}', 
'Logging', 185, 0, '2022-05-25 18:08:01', '2022-05-25 18:08:01');
-
+INSERT INTO "public"."plugin" VALUES ('36', 'loggingTencentCls', '{"endpoint": 
"ap-guangzhou.cls.tencentcs.com", "topic": "shenyu-topic"}', 'Logging', 176, 0, 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
 
 -- ----------------------------
 -- Table structure for plugin_handle
@@ -907,6 +907,21 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1529403902783524974', '35', 'sampl
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524975', '35', 
'maxResponseBody', 'maxResponseBody', 1, 3, 5, 
'{"required":"0","defaultValue":524288}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524976', '35', 
'maxRequestBody', 'maxRequestBody', 1, 3, 6, 
'{"required":"0","defaultValue":524288}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524977', '35', 
'compressAlg', 'compressAlg', 3, 3, 7, 
'{"required":"0","defaultValue":"none"}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524978', '36', 
'secretId', 'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524979', '36', 
'secretKey', 'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524980', '36', 
'endpoint', 'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524981', '36', 
'topic', 'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524982', '36', 
'sendThreadCount', 'sendThreadCount', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524983', '36', 
'totalSizeInBytes', 'totalSizeInBytes', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":104857600}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524984', '36', 
'maxSendThreadCount', 'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}', '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524985', '36', 
'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524986', '36', 
'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524987', '36', 
'maxBatchCount', 'maxBatchCount', 1, 3, 10, 
'{\"required\":\"0\",\"defaultValue\":4096}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524988', '36', 
'lingerMs', 'lingerMs', 1, 3, 11, '{\"required\":\"0\",\"defaultValue\":2000}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524989', '36', 
'retries', 'retries', 1, 3, 12, '{\"required\":\"0\",\"defaultValue\":10}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524990', '36', 
'maxReservedAttempts', 'maxReservedAttempts', 1, 3, 13, 
'{\"required\":\"0\",\"defaultValue\":11}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524991', '36', 
'baseRetryBackoffMs', 'baseRetryBackoffMs', 1, 3, 14, 
'{\"required\":\"0\",\"defaultValue\":100}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524992', '36', 
'maxRetryBackoffMs', 'maxRetryBackoffMs', 1, 3, 15, 
'{\"required\":\"0\",\"defaultValue\":50000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 
 -- ----------------------------
 -- Table structure for resource
diff --git a/db/upgrade/2.4.3-upgrade-2.5.0-mysql.sql 
b/db/upgrade/2.4.3-upgrade-2.5.0-mysql.sql
index 1a6a89cf8..bbd2cf34c 100644
--- a/db/upgrade/2.4.3-upgrade-2.5.0-mysql.sql
+++ b/db/upgrade/2.4.3-upgrade-2.5.0-mysql.sql
@@ -112,7 +112,6 @@ INSERT INTO `plugin_handle` VALUES ('1529402613204172903', 
'34', 'maxRequestBody
 INSERT INTO `plugin_handle` VALUES ('1529402613204172904', '34', 
'maxResponseBody', 'maxResponseBody', 1, 3, 12, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 INSERT INTO `plugin_handle` VALUES ('1529402613204172905', '34', 
'bufferQueueSize', 'bufferQueueSize', 1, 3, 13, 
'{\"required\":\"0\",\"defaultValue\":50000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 
-
 /* insert plugin for loggingElasticSearch  */
 INSERT INTO `plugin` VALUES ('33', 'loggingKafka','{\"host\":\"localhost\", 
\"port\": \"9092\"}', 'Logging', 180, 0, '2022-07-04 22:00:00', '2022-07-02 
22:00:00');
 
diff --git a/db/upgrade/2.5.0-upgrade-2.5.1-mysql.sql 
b/db/upgrade/2.5.0-upgrade-2.5.1-mysql.sql
index 4a5e015ec..c149180ec 100644
--- a/db/upgrade/2.5.0-upgrade-2.5.1-mysql.sql
+++ b/db/upgrade/2.5.0-upgrade-2.5.1-mysql.sql
@@ -26,3 +26,21 @@ INSERT INTO `plugin_handle` VALUES ('1529402613204172908', 
'35', 'sampleRate', '
 INSERT INTO `plugin_handle` VALUES ('1529402613204172909', '35', 
'maxResponseBody', 'maxResponseBody', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 INSERT INTO `plugin_handle` VALUES ('1529402613204172910', '35', 
'maxRequestBody', 'maxRequestBody', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
 INSERT INTO `plugin_handle` VALUES ('1529402613204172911', '35', 
'compressAlg', 'compressAlg', 3, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":\"none\"}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+
+-- insert loggingTencentCls plugin
+INSERT INTO `plugin` VALUES ('36', 'loggingTencentCls','{\"endpoint\": 
\"ap-guangzhou.cls.tencentcs.com\, \"topic\": \"shenyu-topic\"}', 'Logging', 
176, 0, '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172912', '36', 'secretId', 
'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172913', '36', 'secretKey', 
'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172914', '36', 'endpoint', 
'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172915', '36', 'topic', 
'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172916', '36', 
'sendThreadCount', 'sendThreadCount', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172917', '36', 
'totalSizeInBytes', 'totalSizeInBytes', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":104857600}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172918', '36', 
'maxSendThreadCount', 'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}', '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172919', '36', 
'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172920', '36', 
'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172921', '36', 
'maxBatchCount', 'maxBatchCount', 1, 3, 10, 
'{\"required\":\"0\",\"defaultValue\":4096}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172922', '36', 'lingerMs', 
'lingerMs', 1, 3, 11, '{\"required\":\"0\",\"defaultValue\":2000}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172923', '36', 'retries', 
'retries', 1, 3, 12, '{\"required\":\"0\",\"defaultValue\":10}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172924', '36', 
'maxReservedAttempts', 'maxReservedAttempts', 1, 3, 13, 
'{\"required\":\"0\",\"defaultValue\":11}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172925', '36', 
'baseRetryBackoffMs', 'baseRetryBackoffMs', 1, 3, 14, 
'{\"required\":\"0\",\"defaultValue\":100}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172926', '36', 
'maxRetryBackoffMs', 'maxRetryBackoffMs', 1, 3, 15, 
'{\"required\":\"0\",\"defaultValue\":50000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
diff --git a/db/upgrade/2.5.0-upgrade-2.5.1-oracle.sql 
b/db/upgrade/2.5.0-upgrade-2.5.1-oracle.sql
new file mode 100644
index 000000000..7ec13f274
--- /dev/null
+++ b/db/upgrade/2.5.0-upgrade-2.5.1-oracle.sql
@@ -0,0 +1,70 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+-- this file works for PostgreSQL, can not use "`" syntax.
+
+-- Note: it doesn't matter if you don't execute this SQL
+-- Note: because most users have changed ZK configuration, this SQL is 
annotated to prevent erroneous execution
+-- UPDATE plugin SET 
config='{"register":"127.0.0.1:2181","corethreads":0,"threads":2147483647,"queues":0}'
 WHERE "name" = 'motan';
+-- if you want to execute this SQL, please replace it with your ZK 
configuration
+
+-- insert loggingTencentCls plugin start
+INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
config, role, sort, enabled) VALUES ('36', 'loggingTencentCls', '{"endpoint": 
"ap-guangzhou.cls.tencentcs.com", "topic": "shenyu-topic"}', 'Logging', 176, 
'0');
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468204', '36', 'secretId', 'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468205', '36', 'secretKey', 'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468206', '36', 'endpoint', 'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468207', '36', 'topic', 'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468208', '36', 'sendThreadCount', 'sendThreadCount', 1, 
3, 5, '{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468209', '36', 'totalSizeInBytes', 'totalSizeInBytes', 
1, 3, 6, '{\"required\":\"0\",\"defaultValue\":104857600}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468210', '36', 'maxSendThreadCount', 
'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468211', '36', 'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468206', '36', 'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468212', '36', 'maxBatchCount', 'maxBatchCount', 1, 3, 
10, '{\"required\":\"0\",\"defaultValue\":4096}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468213', '36', 'lingerMs', 'lingerMs', 1, 3, 11, 
'{\"required\":\"0\",\"defaultValue\":2000}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468214', '36', 'retries', 'retries', 1, 3, 12, 
'{\"required\":\"0\",\"defaultValue\":10}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468215', '36', 'maxReservedAttempts', 
'maxReservedAttempts', 1, 3, 13, '{\"required\":\"0\",\"defaultValue\":11}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468216', '36', 'baseRetryBackoffMs', 
'baseRetryBackoffMs', 1, 3, 14, '{\"required\":\"0\",\"defaultValue\":100}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1518229897214468217', '36', 'maxRetryBackoffMs', 'maxRetryBackoffMs', 
1, 3, 15, '{\"required\":\"0\",\"defaultValue\":50000}');
+-- insert loggingTencentCls plugin End
diff --git a/db/upgrade/2.5.0-upgrade-2.5.1-pg.sql 
b/db/upgrade/2.5.0-upgrade-2.5.1-pg.sql
index 6f459fe9c..db437103e 100644
--- a/db/upgrade/2.5.0-upgrade-2.5.1-pg.sql
+++ b/db/upgrade/2.5.0-upgrade-2.5.1-pg.sql
@@ -26,3 +26,21 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1529403902783524974', '35', 'sampl
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524975', '35', 
'maxResponseBody', 'maxResponseBody', 1, 3, 5, 
'{"required":"0","defaultValue":524288}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524976', '35', 
'maxRequestBody', 'maxRequestBody', 1, 3, 6, 
'{"required":"0","defaultValue":524288}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524977', '35', 
'compressAlg', 'compressAlg', 3, 3, 7, 
'{"required":"0","defaultValue":"none"}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+
+-- insert loggingTencentCls plugin
+INSERT INTO "public"."plugin" VALUES ('36', 'loggingTencentCls', 
'{"endpoint\": \"ap-guangzhou.cls.tencentcs.com\, \"topic\": \"shenyu-topic"}', 
'Logging', 176, 0, '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524978', '36', 
'secretId', 'secretId', 2, 3, 1, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524979', '36', 
'secretKey', 'secretKey', 2, 3, 2, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524980', '36', 
'endpoint', 'endpoint', 2, 3, 3, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524981', '36', 
'topic', 'topic', 2, 3, 4, 
'{\"required\":\"1\",\"defaultValue\":\"\",\"placeholder\":\"\"}', '2022-06-30 
21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524982', '36', 
'sendThreadCount', 'sendThreadCount', 1, 3, 5, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"1-500\"}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524983', '36', 
'totalSizeInBytes', 'totalSizeInBytes', 1, 3, 6, 
'{\"required\":\"0\",\"defaultValue\":104857600}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524984', '36', 
'maxSendThreadCount', 'maxSendThreadCount', 1, 3, 7, 
'{\"required\":\"0\",\"defaultValue\":1,\"placeholder\":\"availableProcessors + 
1\"}', '2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524985', '36', 
'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{\"required\":\"0\",\"defaultValue\":60000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524986', '36', 
'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{\"required\":\"0\",\"defaultValue\":524288}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524987', '36', 
'maxBatchCount', 'maxBatchCount', 1, 3, 10, 
'{\"required\":\"0\",\"defaultValue\":4096}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524988', '36', 
'lingerMs', 'lingerMs', 1, 3, 11, '{\"required\":\"0\",\"defaultValue\":2000}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524989', '36', 
'retries', 'retries', 1, 3, 12, '{\"required\":\"0\",\"defaultValue\":10}', 
'2022-06-30 21:00:00', '2022-06-30 21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524990', '36', 
'maxReservedAttempts', 'maxReservedAttempts', 1, 3, 13, 
'{\"required\":\"0\",\"defaultValue\":11}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524991', '36', 
'baseRetryBackoffMs', 'baseRetryBackoffMs', 1, 3, 14, 
'{\"required\":\"0\",\"defaultValue\":100}', '2022-06-30 21:00:00', '2022-06-30 
21:00:00');
+INSERT INTO "public"."plugin_handle" VALUES ('1529403902783524992', '36', 
'maxRetryBackoffMs', 'maxRetryBackoffMs', 1, 3, 15, 
'{\"required\":\"0\",\"defaultValue\":50000}', '2022-06-30 21:00:00', 
'2022-06-30 21:00:00');
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql 
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index 1100f6ca0..6efa3fa38 100755
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -390,6 +390,7 @@ INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, 
`config`, `enabled`)
 INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`, 
`enabled`) VALUES ('33', 'loggingKafka', 'Logging', 
180,'{"topic":"shenyu-access-logging", "namesrvAddr": "localhost:9092"}', '0');
 INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`, 
`enabled`) VALUES ('34', 'loggingAliyunSls', 'Logging', 175, '{"projectName": 
"shenyu", "logStoreName": "shenyu-logstore", "topic": "shenyu-topic"}', '0');
 INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`, 
`enabled`) VALUES ('35', 'loggingPulsar', 'Logging', 185, 
'{"topic":"shenyu-access-logging", "serviceUrl": "pulsar://localhost:6650"}', 
'0');
+INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`, 
`enabled`) VALUES ('36', 'loggingTencentCls', 'Logging', 176, '{"endpoint": 
"ap-guangzhou.cls.tencentcs.com", "topic": "shenyu-topic"}', '0');
 
 
 /*insert plugin_handle data for sentinel*/
@@ -593,6 +594,21 @@ INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172909', '35', 'maxResponseBody', 'maxResponseBody', 1, 3, 5, 
'{"required":"0","defaultValue":524288}');
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172910', '35', 'maxRequestBody', 'maxRequestBody', 1, 3, 6, 
'{"required":"0","defaultValue":524288}');
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172911', '35', 'compressAlg', 'compressAlg', 3, 3, 7, 
'{"required":"0","defaultValue":"none"}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172912', '36', 'secretId', 'secretId', 2, 3, 1, 
'{"required":"1","defaultValue":"","placeholder":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172913', '36', 'secretKey', 'secretKey', 2, 3, 2, 
'{"required":"1","defaultValue":"","placeholder":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172914', '36', 'endpoint', 'endpoint', 2, 3, 3, 
'{"required":"1","defaultValue":"","placeholder":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172915', '36', 'topic', 'topic', 2, 3, 4, 
'{"required":"1","defaultValue":"","placeholder":""}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172916', '36', 'sendThreadCount', 'sendThreadCount', 1, 3, 5, 
'{"required":"0","defaultValue":1,"placeholder":"1-500"}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172917', '36', 'totalSizeInBytes', 'totalSizeInBytes', 1, 3, 6, 
'{"required":"0","defaultValue":104857600}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172918', '36', 'maxSendThreadCount', 'maxSendThreadCount', 1, 3, 
7, '{"required":"0","defaultValue":1,"placeholder":"availableProcessors + 1"}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172919', '36', 'maxBlockSec', 'maxBlockSec', 1, 3, 8, 
'{"required":"0","defaultValue":60000}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172920', '36', 'maxBatchSize', 'maxBatchSize', 1, 3, 9, 
'{"required":"0","defaultValue":524288}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172921', '36', 'maxBatchCount', 'maxBatchCount', 1, 3, 10, 
'{"required":"0","defaultValue":4096}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172922', '36', 'lingerMs', 'lingerMs', 1, 3, 11, 
'{"required":"0","defaultValue":2000}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172923', '36', 'retries', 'retries', 1, 3, 12, 
'{"required":"0","defaultValue":10}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172924', '36', 'maxReservedAttempts', 'maxReservedAttempts', 1, 
3, 13, '{"required":"0","defaultValue":11}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172925', '36', 'baseRetryBackoffMs', 'baseRetryBackoffMs', 1, 3, 
14, '{"required":"0","defaultValue":100}');
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613204172926', '36', 'maxRetryBackoffMs', 'maxRetryBackoffMs', 1, 3, 
15, '{"required":"0","defaultValue":50000}');
 
 /** insert resource for resource */
 INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`, 
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`, 
`status`) 
VALUES('1346775491550474240','','SHENYU.MENU.PLUGIN.LIST','plug','/plug','PluginList','0','0','dashboard','0','0','','1');
diff --git a/shenyu-bootstrap/pom.xml b/shenyu-bootstrap/pom.xml
index 5490ba43e..90d0bc8e2 100644
--- a/shenyu-bootstrap/pom.xml
+++ b/shenyu-bootstrap/pom.xml
@@ -503,6 +503,14 @@
         </dependency>
         <!-- shenyu logging-pulsar plugin end -->
 
+        <!-- shenyu logging-tencentcls plugin start -->
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            
<artifactId>shenyu-spring-boot-starter-plugin-logging-tencent-cls</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- shenyu logging-tencentcls plugin end -->
+
     </dependencies>
     <profiles>
         <profile>
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
index da773d0e2..6f4cd19c6 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/PluginEnum.java
@@ -142,6 +142,11 @@ public enum PluginEnum {
      */
     LOGGING_ALIYUN_SLS(175, 0, "loggingAliyunSls"),
 
+    /**
+     * Logging Tencent cls enums.
+     */
+    LOGGING_TENCENT_CLS(176, 0, "loggingTencentCls"),
+
     /**
      * Logging Kafka plugin enum.
      */
diff --git a/shenyu-dist/shenyu-bootstrap-dist/src/main/release-docs/LICENSE 
b/shenyu-dist/shenyu-bootstrap-dist/src/main/release-docs/LICENSE
index 7df288262..e398da831 100644
--- a/shenyu-dist/shenyu-bootstrap-dist/src/main/release-docs/LICENSE
+++ b/shenyu-dist/shenyu-bootstrap-dist/src/main/release-docs/LICENSE
@@ -510,6 +510,7 @@ The text of each license is the standard Apache 2.0 license.
     pulsar-client 2.10.1: https://github.com/apache/pulsar, Apache 2.0
     aliyun-log 0.6.57: https://github.com/aliyun/aliyun-log-java-producer, 
Apache 2.0
     aliyun-log-producer 0.3.10: 
https://github.com/aliyun/aliyun-log-java-producer, Apache 2.0
+    tencentcloud-cls-sdk-java 1.0.9: 
https://github.com/TencentCloud/tencentcloud-cls-sdk-java, Apache 2.0
 
 ========================================================================
 BSD licenses
diff --git a/shenyu-plugin/shenyu-plugin-logging/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/pom.xml
index f9187f919..07d130657 100644
--- a/shenyu-plugin/shenyu-plugin-logging/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-logging/pom.xml
@@ -34,5 +34,6 @@
         <module>shenyu-plugin-logging-elasticsearch</module>
         <module>shenyu-plugin-logging-aliyun-sls</module>
         <module>shenyu-plugin-logging-pulsar</module>
+        <module>shenyu-plugin-logging-tencent-cls</module>
     </modules>
 </project>
\ No newline at end of file
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
index 14d7fcb04..542f31a45 100644
--- 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/constant/GenericLoggingConstant.java
@@ -71,7 +71,72 @@ public class GenericLoggingConstant {
      * aliyun sls topic.
      */
     public static final String TOPIC = "topic";
-    
+
+    /**
+     * tencent cls secretId.
+     */
+    public static final String SECRET_ID = "secretId";
+
+    /**
+     * tencent cls secretKey.
+     */
+    public static final String SECRET_KEY = "secretKey";
+
+    /**
+     * tencent cls endpoint.
+     */
+    public static final String ENDPOINT = "endpoint";
+
+    /**
+     * tencent cls totalSizeInBytes.
+     */
+    public static final String TOTAL_SIZE_IN_BYTES = "totalSizeInBytes";
+
+    /**
+     * tencent cls maxSendThreadCount.
+     */
+    public static final String MAX_SEND_THREAD_COUNT = "maxSendThreadCount";
+
+    /**
+     * tencent cls maxBlockSec.
+     */
+    public static final String MAX_BLOCK_SEC = "maxBlockSec";
+
+    /**
+     * tencent cls maxBatchSize.
+     */
+    public static final String MAX_BATCH_SIZE = "maxBatchSize";
+
+    /**
+     * tencent cls maxBatchCount.
+     */
+    public static final String MAX_BATCH_COUNT = "maxBatchCount";
+
+    /**
+     * tencent cls lingerMs.
+     */
+    public static final String LINGER_MS = "lingerMs";
+
+    /**
+     * tencent cls retries.
+     */
+    public static final String RETRIES = "retries";
+
+    /**
+     * tencent cls maxReservedAttempts.
+     */
+    public static final String MAX_RESERVED_ATTEMPTS = "maxReservedAttempts";
+
+    /**
+     * tencent cls baseRetryBackoffMs.
+     */
+    public static final String BASE_RETRY_BACKOFF_MS = "baseRetryBackoffMs";
+
+    /**
+     * tencent cls maxRetryBackoffMs.
+     */
+    public static final String MAX_RETRY_BACKOFF_MS = "maxRetryBackoffMs";
+
     /**
      * send thread config.
      */
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/pom.xml 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/pom.xml
new file mode 100644
index 000000000..d90d94d0a
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <groupId>org.apache.shenyu</groupId>
+        <artifactId>shenyu-plugin-logging</artifactId>
+        <version>2.5.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>shenyu-plugin-logging-tencent-cls</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <aliyun-log.version>0.6.70</aliyun-log.version>
+        <protobuf-java.version>3.19.2</protobuf-java.version>
+        <tencent-log-sdk.version>1.0.9</tencent-log-sdk.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-plugin-logging-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.tencentcloudapi.cls</groupId>
+            <artifactId>tencentcloud-cls-sdk-java</artifactId>
+            <version>${tencent-log-sdk.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-classic</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>io.projectreactor</groupId>
+            <artifactId>reactor-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>${protobuf-java.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPlugin.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPlugin.java
new file mode 100644
index 000000000..f18ddb4d1
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPlugin.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls;
+
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import 
org.apache.shenyu.plugin.tencent.cls.collector.TencentClsSlsLogCollector;
+import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.apache.shenyu.plugin.logging.common.AbstractLoggingPlugin;
+import org.apache.shenyu.plugin.logging.common.body.LoggingServerHttpRequest;
+import org.apache.shenyu.plugin.logging.common.body.LoggingServerHttpResponse;
+import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * LoggingTencentClsPlugin send log to Tencent cls service.
+ */
+public class LoggingTencentClsPlugin extends AbstractLoggingPlugin {
+
+    @Override
+    public Mono<Void> doLogExecute(final ServerWebExchange exchange, final 
ShenyuPluginChain chain,
+                                   final SelectorData selector, final RuleData 
rule,
+                                   final ServerHttpRequest request, final 
ShenyuRequestLog requestInfo) {
+        LoggingServerHttpRequest loggingServerHttpRequest = new 
LoggingServerHttpRequest(request, requestInfo);
+        LoggingServerHttpResponse loggingServerHttpResponse = new 
LoggingServerHttpResponse(exchange.getResponse(),
+                requestInfo, TencentClsSlsLogCollector.getInstance());
+        ServerWebExchange webExchange = 
exchange.mutate().request(loggingServerHttpRequest)
+                .response(loggingServerHttpResponse).build();
+        loggingServerHttpResponse.setExchange(webExchange);
+        return 
chain.execute(webExchange).doOnError(loggingServerHttpResponse::logError);
+    }
+
+    /**
+     * get plugin order.
+     *
+     * @return order
+     */
+    @Override
+    public int getOrder() {
+        return PluginEnum.LOGGING_TENCENT_CLS.getCode();
+    }
+
+    /**
+     * get plugin name.
+     *
+     * @return plugin name
+     */
+    @Override
+    public String named() {
+        return PluginEnum.LOGGING_TENCENT_CLS.getName();
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/client/TencentClsLogCollectClient.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/client/TencentClsLogCollectClient.java
new file mode 100644
index 000000000..ad4d038e8
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/client/TencentClsLogCollectClient.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.client;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.tencentcloudapi.cls.producer.AsyncProducerClient;
+import com.tencentcloudapi.cls.producer.AsyncProducerConfig;
+import com.tencentcloudapi.cls.producer.Result;
+import com.tencentcloudapi.cls.producer.common.LogItem;
+import com.tencentcloudapi.cls.producer.errors.LogSizeTooLargeException;
+import com.tencentcloudapi.cls.producer.errors.MaxBatchCountExceedException;
+import com.tencentcloudapi.cls.producer.errors.ProducerException;
+import com.tencentcloudapi.cls.producer.errors.ResultFailedException;
+import com.tencentcloudapi.cls.producer.util.NetworkUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.logging.common.client.LogConsumeClient;
+import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
+import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tencent cls log Collect client.
+ */
+public class TencentClsLogCollectClient implements LogConsumeClient {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(TencentClsLogCollectClient.class);
+
+    private AsyncProducerClient client;
+
+    private String topic;
+
+    private final AtomicBoolean isStarted = new AtomicBoolean(false);
+
+    private ThreadPoolExecutor threadExecutor;
+
+    /**
+     * init Tencent cls client.
+     *
+     * @param props props
+     */
+    public void initClient(final Properties props) {
+        if (MapUtils.isEmpty(props)) {
+            LOG.error("Tencent cls props is empty. failed init Tencent cls 
producer");
+            return;
+        }
+        if (isStarted.get()) {
+            close();
+        }
+        String secretId = props.getProperty(GenericLoggingConstant.SECRET_ID);
+        String secretKey = 
props.getProperty(GenericLoggingConstant.SECRET_KEY);
+        String endpoint = props.getProperty(GenericLoggingConstant.ENDPOINT);
+        topic = props.getProperty(GenericLoggingConstant.TOPIC);
+        if (StringUtils.isBlank(secretId) || StringUtils.isBlank(secretKey) || 
StringUtils.isBlank(topic) || StringUtils.isBlank(endpoint)) {
+            LOG.error("init Tencent cls client error, please check secretId, 
secretKey, topic or host");
+            return;
+        }
+
+        String totalSizeInBytes = 
props.getProperty(GenericLoggingConstant.TOTAL_SIZE_IN_BYTES);
+        String maxSendThreadCount = 
props.getProperty(GenericLoggingConstant.MAX_SEND_THREAD_COUNT);
+        String maxBlockSec = 
props.getProperty(GenericLoggingConstant.MAX_BLOCK_SEC);
+        String maxBatchSize = 
props.getProperty(GenericLoggingConstant.MAX_BATCH_SIZE);
+        String maxBatchCount = 
props.getProperty(GenericLoggingConstant.MAX_BATCH_COUNT);
+        String lingerMs = props.getProperty(GenericLoggingConstant.LINGER_MS);
+        String retries = props.getProperty(GenericLoggingConstant.RETRIES);
+        String maxReservedAttempts = 
props.getProperty(GenericLoggingConstant.MAX_RESERVED_ATTEMPTS);
+        String baseRetryBackoffMs = 
props.getProperty(GenericLoggingConstant.BASE_RETRY_BACKOFF_MS);
+        String maxRetryBackoffMs = 
props.getProperty(GenericLoggingConstant.MAX_RETRY_BACKOFF_MS);
+        // init AsyncProducerConfig, AsyncProducerClient
+        final AsyncProducerConfig config = new AsyncProducerConfig(endpoint, 
secretId, secretKey, NetworkUtils.getLocalMachineIP());
+
+        // Optional parameters
+        
Optional.ofNullable(totalSizeInBytes).map(Integer::valueOf).ifPresent(config::setTotalSizeInBytes);
+        
Optional.ofNullable(maxSendThreadCount).map(Integer::valueOf).ifPresent(config::setSendThreadCount);
+        
Optional.ofNullable(maxBlockSec).map(Long::valueOf).ifPresent(config::setMaxBlockMs);
+        
Optional.ofNullable(maxBatchSize).map(Integer::valueOf).ifPresent(config::setBatchSizeThresholdInBytes);
+        
Optional.ofNullable(maxBatchCount).map(Integer::valueOf).ifPresent(config::setBatchCountThreshold);
+        
Optional.ofNullable(lingerMs).map(Integer::valueOf).ifPresent(config::setLingerMs);
+        
Optional.ofNullable(retries).map(Integer::valueOf).ifPresent(config::setRetries);
+        
Optional.ofNullable(maxReservedAttempts).map(Integer::valueOf).ifPresent(config::setMaxReservedAttempts);
+        
Optional.ofNullable(baseRetryBackoffMs).map(Long::valueOf).ifPresent(config::setBaseRetryBackoffMs);
+        
Optional.ofNullable(maxRetryBackoffMs).map(Long::valueOf).ifPresent(config::setMaxRetryBackoffMs);
+
+        threadExecutor = createThreadPoolExecutor(props);
+
+        try {
+            isStarted.set(true);
+            client = new AsyncProducerClient(config);
+        } catch (Exception e) {
+            LOG.warn("TencentClsLogCollectClient initClient error message:{}", 
e.getMessage());
+        }
+    }
+
+    /**
+     * Tencent cls consume.
+     *
+     * @param logs list of log
+     */
+    @Override
+    public void consume(final List<ShenyuRequestLog> logs) {
+        if (CollectionUtils.isEmpty(logs) || !isStarted.get()) {
+            return;
+        }
+        logs.forEach(this::sendLog);
+    }
+
+    @Override
+    public void close() {
+        if (Objects.nonNull(client) && isStarted.get()) {
+            isStarted.set(false);
+            try {
+                client.close();
+            } catch (InterruptedException | ProducerException e) {
+                LOG.error("Close producer error.");
+            }
+        }
+    }
+
+    /**
+     * send log to Tencent cls.
+     *
+     * @param log log
+     */
+    private void sendLog(final ShenyuRequestLog log) {
+        final List<LogItem> logItems = new ArrayList<>();
+        LogItem logItem = new LogItem((int) (System.currentTimeMillis() / 
1000));
+        logItem.PushBack("level", "info");
+        logItem.PushBack("name", log.getRequestUri());
+        logItem.PushBack("message", GsonUtils.getGson().toJson(log));
+        logItems.add(logItem);
+        try {
+            final ListenableFuture<Result> f = client.putLogs(topic, logItems, 
result -> { });
+            Futures.addCallback(f, new ProducerFutureCallback(topic), 
threadExecutor);
+        } catch (InterruptedException e) {
+            LOG.warn("The current thread has been interrupted during send 
logs.");
+        } catch (Exception e) {
+            if (e instanceof MaxBatchCountExceedException) {
+                LOG.error("The logs exceeds the maximum batch count, e={}", 
e.getMessage());
+            } else if (e instanceof LogSizeTooLargeException) {
+                LOG.error("The size of log is larger than the maximum 
allowable size, e={}", e.getMessage());
+            } else {
+                LOG.error("Failed to send logs, e={}", e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * create send log queue.
+     *
+     * @param props props
+     * @return ThreadPoolExecutor
+     */
+    private static ThreadPoolExecutor createThreadPoolExecutor(final 
Properties props) {
+        int sendThreadCount = 
Integer.parseInt(props.getProperty(GenericLoggingConstant.SEND_THREAD_COUNT));
+        if (sendThreadCount > GenericLoggingConstant.MAX_ALLOW_THREADS) {
+            LOG.warn("send thread count number too large!");
+            sendThreadCount = GenericLoggingConstant.MAX_ALLOW_THREADS;
+        }
+        return new ThreadPoolExecutor(sendThreadCount, 
GenericLoggingConstant.MAX_ALLOW_THREADS, 60000L, TimeUnit.MICROSECONDS,
+                new 
LinkedBlockingQueue<>(GenericLoggingConstant.MAX_QUEUE_NUMBER), 
ShenyuThreadFactory.create("shenyu-tencent-cls", true),
+                new ThreadPoolExecutor.AbortPolicy());
+    }
+
+    /**
+     * Producer Future Callback.
+     */
+    private static final class ProducerFutureCallback implements 
FutureCallback<Result> {
+
+        private static final Logger LOGGER = 
LoggerFactory.getLogger(ProducerFutureCallback.class);
+
+        private final String topic;
+
+        ProducerFutureCallback(final String topic) {
+            this.topic = topic;
+        }
+
+        @Override
+        public void onSuccess(@Nullable final Result result) {
+            LOGGER.info("Send logs to Tencent cls successfully.");
+        }
+
+        @Override
+        public void onFailure(final Throwable throwable) {
+            if (throwable instanceof ResultFailedException) {
+                Result result = ((ResultFailedException) 
throwable).getResult();
+                LOGGER.error("Failed to send logs, topic={}, result={}", 
topic, result);
+            } else {
+                LOGGER.error("Failed to send log, e={}", 
throwable.getMessage());
+            }
+        }
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollector.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollector.java
new file mode 100644
index 000000000..0e932c68d
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollector.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.collector;
+
+import 
org.apache.shenyu.plugin.tencent.cls.handler.LoggingTencentClsPluginDataHandler;
+import org.apache.shenyu.plugin.logging.common.client.LogConsumeClient;
+import org.apache.shenyu.plugin.logging.common.collector.AbstractLogCollector;
+import org.apache.shenyu.plugin.logging.common.collector.LogCollector;
+
+/**
+ * Tencent cls log collector,depend a LogConsumeClient for consume logs.
+ */
+public class TencentClsSlsLogCollector extends AbstractLogCollector {
+
+    private static final LogCollector INSTANCE = new 
TencentClsSlsLogCollector();
+
+    /**
+     * get LogCollector instance.
+     *
+     * @return LogCollector instance
+     */
+    public static LogCollector getInstance() {
+        return INSTANCE;
+    }
+
+    @Override
+    protected LogConsumeClient getLogConsumeClient() {
+        return 
LoggingTencentClsPluginDataHandler.getTencentClsLogCollectClient();
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfig.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfig.java
new file mode 100644
index 000000000..4e156f2a0
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfig.java
@@ -0,0 +1,440 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.config;
+
+import org.apache.shenyu.plugin.logging.common.config.GenericGlobalConfig;
+
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * LogCollectConfig.
+ */
+public class TencentLogCollectConfig {
+
+    public static final TencentLogCollectConfig INSTANCE = new 
TencentLogCollectConfig();
+
+    private TencentClsLogConfig tencentClsLogConfig;
+
+    /**
+     * get Tencent cls log config.
+     *
+     * @return global log config
+     */
+    public TencentClsLogConfig getTencentClsLogConfig() {
+        return Optional.ofNullable(tencentClsLogConfig).orElse(new 
TencentClsLogConfig());
+    }
+
+    /**
+     * set Tencent cls log config.
+     *
+     * @param tencentClsLogConfig Tencent cls log config.
+     */
+    public void setTencentClsLogConfig(final TencentClsLogConfig 
tencentClsLogConfig) {
+        this.tencentClsLogConfig = tencentClsLogConfig;
+    }
+
+    /**
+     * global log config.
+     * please seee 
https://github.com/TencentCloud/tencentcloud-cls-sdk-java/blob/main/README.md#%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0%E8%AF%A6%E8%A7%A3
+     */
+    public static class TencentClsLogConfig extends GenericGlobalConfig {
+
+        /**
+         * Tencent cls endpoint.
+         * please seee https://cloud.tencent.com/document/product/614/18940
+         */
+        private String endpoint;
+
+        /**
+         * tencent secretId.
+         */
+        private String secretId;
+
+        /**
+         * tencent secretKey.
+         */
+        private String secretKey;
+
+        /**
+         * tencent totalSizeInBytes.
+         */
+        private String totalSizeInBytes = "104857600";
+
+        /**
+         * tencent maxSendThreadCount.
+         */
+        private String maxSendThreadCount = 
String.valueOf(Math.max(Runtime.getRuntime().availableProcessors(), 1));
+
+        /**
+         * tencent maxBlockSec.
+         */
+        private String maxBlockSec = "60000";
+
+        /**
+         * tencent maxBatchSize.
+         */
+        private String maxBatchSize = 512 * 1024 + "";
+
+        /**
+         * tencent maxBatchCount.
+         */
+        private String maxBatchCount = "4096";
+
+        /**
+         * tencent lingerMs.
+         */
+        private String lingerMs = "2000";
+
+        /**
+         * tencent retries.
+         */
+        private String retries = "10";
+
+        /**
+         * tencent maxReservedAttempts.
+         */
+        private String maxReservedAttempts = "11";
+
+        /**
+         * tencent baseRetryBackoffMs.
+         */
+        private String baseRetryBackoffMs = "100";
+
+        /**
+         * tencent maxRetryBackoffMs.
+         */
+        private String maxRetryBackoffMs = "50000";
+
+        /**
+         * tencent sendThreadCount.
+         */
+        private Integer sendThreadCount = 1;
+
+        /**
+         * Tencent cls topic.
+         * tencent query by topic
+         */
+        private String topic = "shenyu-topic";
+        
+        /**
+         * getEndpoint.
+         * 
+         * @return endpoint
+         */
+        public String getEndpoint() {
+            return endpoint;
+        }
+
+        /**
+         * set accessId.
+         *
+         * @param endpoint endpoint
+         */
+        public void setEndpoint(final String endpoint) {
+            this.endpoint = endpoint;
+        }
+        
+        /**
+         * getSecretId.
+         * 
+         * @return secretId
+         */
+        public String getSecretId() {
+            return secretId;
+        }
+
+        /**
+         * set secretId.
+         *
+         * @param secretId secretId
+         */
+        public void setSecretId(final String secretId) {
+            this.secretId = secretId;
+        }
+
+        /**
+         * getSecretKey.
+         *
+         * @return secretKey
+         */
+        public String getSecretKey() {
+            return secretKey;
+        }
+
+        /**
+         * set secretKey.
+         *
+         * @param secretKey secretKey
+         */
+        public void setSecretKey(final String secretKey) {
+            this.secretKey = secretKey;
+        }
+
+        /**
+         * getTotalSizeInBytes.
+         *
+         * @return totalSizeInBytes
+         */
+        public String getTotalSizeInBytes() {
+            return totalSizeInBytes;
+        }
+
+        /**
+         * set totalSizeInBytes.
+         *
+         * @param totalSizeInBytes totalSizeInBytes
+         */
+        public void setTotalSizeInBytes(final String totalSizeInBytes) {
+            this.totalSizeInBytes = totalSizeInBytes;
+        }
+
+        /**
+         * getMaxSendThreadCount.
+         *
+         * @return maxSendThreadCount
+         */
+        public String getMaxSendThreadCount() {
+            return maxSendThreadCount;
+        }
+
+        /**
+         * set maxSendThreadCount.
+         *
+         * @param maxSendThreadCount maxSendThreadCount
+         */
+        public void setMaxSendThreadCount(final String maxSendThreadCount) {
+            this.maxSendThreadCount = maxSendThreadCount;
+        }
+
+        /**
+         * getMaxBlockSec.
+         *
+         * @return maxBlockSec
+         */
+        public String getMaxBlockSec() {
+            return maxBlockSec;
+        }
+
+        /**
+         * set maxBlockSec.
+         *
+         * @param maxBlockSec maxBlockSec
+         */
+        public void setMaxBlockSec(final String maxBlockSec) {
+            this.maxBlockSec = maxBlockSec;
+        }
+
+        /**
+         * getMaxBatchSize.
+         *
+         * @return maxBatchSize
+         */
+        public String getMaxBatchSize() {
+            return maxBatchSize;
+        }
+
+        /**
+         * set maxBatchSize.
+         *
+         * @param maxBatchSize maxBatchSize
+         */
+        public void setMaxBatchSize(final String maxBatchSize) {
+            this.maxBatchSize = maxBatchSize;
+        }
+
+        /**
+         * getMaxBatchCount.
+         *
+         * @return maxBatchCount
+         */
+        public String getMaxBatchCount() {
+            return maxBatchCount;
+        }
+
+        /**
+         * set maxBatchCount.
+         *
+         * @param maxBatchCount maxBatchCount
+         */
+        public void setMaxBatchCount(final String maxBatchCount) {
+            this.maxBatchCount = maxBatchCount;
+        }
+
+        /**
+         * getLingerMs.
+         *
+         * @return lingerMs
+         */
+        public String getLingerMs() {
+            return lingerMs;
+        }
+
+        /**
+         * set lingerMs.
+         *
+         * @param lingerMs lingerMs
+         */
+        public void setLingerMs(final String lingerMs) {
+            this.lingerMs = lingerMs;
+        }
+
+        /**
+         * getRetries.
+         *
+         * @return retries
+         */
+        public String getRetries() {
+            return retries;
+        }
+
+        /**
+         * set retries.
+         *
+         * @param retries retries
+         */
+        public void setRetries(final String retries) {
+            this.retries = retries;
+        }
+
+        /**
+         * getMaxReservedAttempts.
+         *
+         * @return maxReservedAttempts
+         */
+        public String getMaxReservedAttempts() {
+            return maxReservedAttempts;
+        }
+
+        /**
+         * set maxReservedAttempts.
+         *
+         * @param maxReservedAttempts maxReservedAttempts
+         */
+        public void setMaxReservedAttempts(final String maxReservedAttempts) {
+            this.maxReservedAttempts = maxReservedAttempts;
+        }
+
+        /**
+         * getBaseRetryBackoffMs.
+         *
+         * @return baseRetryBackoffMs
+         */
+        public String getBaseRetryBackoffMs() {
+            return baseRetryBackoffMs;
+        }
+
+        /**
+         * set baseRetryBackoffMs.
+         *
+         * @param baseRetryBackoffMs baseRetryBackoffMs
+         */
+        public void setBaseRetryBackoffMs(final String baseRetryBackoffMs) {
+            this.baseRetryBackoffMs = baseRetryBackoffMs;
+        }
+
+        /**
+         * getMaxRetryBackoffMs.
+         *
+         * @return maxRetryBackoffMs
+         */
+        public String getMaxRetryBackoffMs() {
+            return maxRetryBackoffMs;
+        }
+
+        /**
+         * set maxRetryBackoffMs.
+         *
+         * @param maxRetryBackoffMs maxRetryBackoffMs
+         */
+        public void setMaxRetryBackoffMs(final String maxRetryBackoffMs) {
+            this.maxRetryBackoffMs = maxRetryBackoffMs;
+        }
+
+        /**
+         * get send thread count.
+         *
+         * @return send thread count
+         */
+        public Integer getSendThreadCount() {
+            return sendThreadCount;
+        }
+
+        /**
+         * send thread count.
+         *
+         * @param sendThreadCount send thread count
+         */
+        public void setSendThreadCount(final Integer sendThreadCount) {
+            this.sendThreadCount = sendThreadCount;
+        }
+
+        /**
+         * getTopic.
+         *
+         * @return topic
+         */
+        public String getTopic() {
+            return topic;
+        }
+
+        /**
+         * set topic.
+         *
+         * @param topic topic
+         */
+        public void setTopic(final String topic) {
+            this.topic = topic;
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return Boolean.TRUE;
+            }
+
+            if (o == null || getClass() != o.getClass()) {
+                return Boolean.FALSE;
+            }
+
+            TencentClsLogConfig that = (TencentClsLogConfig) o;
+            return Objects.equals(getSecretId(), that.getSecretId())
+                    && Objects.equals(getSecretKey(), that.getSecretKey())
+                    && Objects.equals(getEndpoint(), that.getEndpoint())
+                    && Objects.equals(getTopic(), that.getTopic())
+                    && Objects.equals(getSendThreadCount(), 
that.getSendThreadCount())
+                    && Objects.equals(getTotalSizeInBytes(), 
that.getTotalSizeInBytes())
+                    && Objects.equals(getMaxSendThreadCount(), 
that.getMaxSendThreadCount())
+                    && Objects.equals(getMaxBlockSec(), that.getMaxBlockSec())
+                    && Objects.equals(getMaxBatchSize(), 
that.getMaxBatchSize())
+                    && Objects.equals(getMaxBatchCount(), 
that.getMaxBatchCount())
+                    && Objects.equals(getLingerMs(), that.getLingerMs())
+                    && Objects.equals(getRetries(), that.getRetries())
+                    && Objects.equals(getMaxReservedAttempts(), 
that.getMaxReservedAttempts())
+                    && Objects.equals(getBaseRetryBackoffMs(), 
that.getBaseRetryBackoffMs())
+                    && Objects.equals(getMaxRetryBackoffMs(), 
that.getMaxRetryBackoffMs());
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(secretId, secretKey, endpoint, topic, 
sendThreadCount, totalSizeInBytes,
+                    maxSendThreadCount, maxBlockSec, maxBatchSize, 
maxBatchCount, lingerMs, retries,
+                    maxReservedAttempts, baseRetryBackoffMs, 
maxRetryBackoffMs);
+        }
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandler.java
new file mode 100644
index 000000000..707387cd1
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandler.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.handler;
+
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.Singleton;
+import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
+import org.apache.shenyu.plugin.tencent.cls.client.TencentClsLogCollectClient;
+import 
org.apache.shenyu.plugin.tencent.cls.collector.TencentClsSlsLogCollector;
+import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import org.apache.shenyu.plugin.tencent.cls.config.TencentLogCollectConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.Properties;
+
+/**
+ * LoggingTencentClsPluginDataHandler Tencent cls plugin data handler.
+ */
+public class LoggingTencentClsPluginDataHandler implements PluginDataHandler {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(LoggingTencentClsPluginDataHandler.class);
+
+    private static final TencentClsLogCollectClient 
TENCENT_CLS_LOG_COLLECT_CLIENT = new TencentClsLogCollectClient();
+
+    @Override
+    public void handlerPlugin(final PluginData pluginData) {
+        LOG.info("Tencent cls plugin data: {}", 
GsonUtils.getGson().toJson(pluginData));
+        if (Objects.nonNull(pluginData) && 
Boolean.TRUE.equals(pluginData.getEnabled())) {
+            TencentLogCollectConfig.TencentClsLogConfig globalLogConfig = 
GsonUtils.getInstance().fromJson(pluginData.getConfig(),
+                    TencentLogCollectConfig.TencentClsLogConfig.class);
+            TencentLogCollectConfig.TencentClsLogConfig exist = 
Singleton.INST.get(TencentLogCollectConfig.TencentClsLogConfig.class);
+            if (Objects.isNull(globalLogConfig)) {
+                return;
+            }
+            if (Objects.isNull(exist) || !globalLogConfig.equals(exist)) {
+                // no data, init client
+                
TencentLogCollectConfig.INSTANCE.setTencentClsLogConfig(globalLogConfig);
+                Properties properties = new Properties();
+                properties.setProperty(GenericLoggingConstant.SECRET_ID, 
globalLogConfig.getSecretId().trim());
+                properties.setProperty(GenericLoggingConstant.SECRET_KEY, 
globalLogConfig.getSecretKey().trim());
+                properties.setProperty(GenericLoggingConstant.ENDPOINT, 
globalLogConfig.getEndpoint().trim());
+                properties.setProperty(GenericLoggingConstant.TOPIC, 
globalLogConfig.getTopic().trim());
+                
properties.setProperty(GenericLoggingConstant.SEND_THREAD_COUNT, 
String.valueOf(globalLogConfig.getSendThreadCount()));
+
+                // Optional parameters
+                
properties.setProperty(GenericLoggingConstant.TOTAL_SIZE_IN_BYTES, 
globalLogConfig.getTotalSizeInBytes());
+                
properties.setProperty(GenericLoggingConstant.MAX_SEND_THREAD_COUNT, 
globalLogConfig.getMaxSendThreadCount());
+                properties.setProperty(GenericLoggingConstant.MAX_BLOCK_SEC, 
globalLogConfig.getMaxBlockSec());
+                properties.setProperty(GenericLoggingConstant.MAX_BATCH_SIZE, 
globalLogConfig.getMaxBatchSize());
+                properties.setProperty(GenericLoggingConstant.MAX_BATCH_COUNT, 
globalLogConfig.getMaxBatchCount());
+                properties.setProperty(GenericLoggingConstant.LINGER_MS, 
globalLogConfig.getLingerMs());
+                properties.setProperty(GenericLoggingConstant.RETRIES, 
globalLogConfig.getRetries());
+                
properties.setProperty(GenericLoggingConstant.MAX_RESERVED_ATTEMPTS, 
globalLogConfig.getMaxReservedAttempts());
+                
properties.setProperty(GenericLoggingConstant.BASE_RETRY_BACKOFF_MS, 
globalLogConfig.getBaseRetryBackoffMs());
+                
properties.setProperty(GenericLoggingConstant.MAX_RETRY_BACKOFF_MS, 
globalLogConfig.getMaxRetryBackoffMs());
+                // init tencent cls client
+                TENCENT_CLS_LOG_COLLECT_CLIENT.initClient(properties);
+                TencentClsSlsLogCollector.getInstance().start();
+                
Singleton.INST.single(TencentLogCollectConfig.TencentClsLogConfig.class, 
globalLogConfig);
+            }
+        } else {
+            try {
+                TencentClsSlsLogCollector.getInstance().close();
+            } catch (Exception e) {
+                LOG.error("close log collector error", e);
+            }
+        }
+    }
+
+    @Override
+    public String pluginNamed() {
+        return PluginEnum.LOGGING_TENCENT_CLS.getName();
+    }
+
+    /**
+     * get Tencent log collect client.
+     * @return Tencent cls log collect client.
+     */
+    public static TencentClsLogCollectClient getTencentClsLogCollectClient() {
+        return TENCENT_CLS_LOG_COLLECT_CLIENT;
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPluginTest.java
new file mode 100644
index 000000000..3a1c5c91e
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/LoggingTencentClsPluginTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls;
+
+import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.RuleData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.plugin.api.RemoteAddressResolver;
+import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.apache.shenyu.plugin.api.context.ShenyuContext;
+import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
+import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+
+import java.net.InetSocketAddress;
+
+/**
+ * The Test Case For LoggingRocketMQPlugin.
+ */
+@ExtendWith(MockitoExtension.class)
+public final class LoggingTencentClsPluginTest {
+
+    private LoggingTencentClsPlugin loggingTencentClsPlugin;
+
+    private ServerWebExchange exchange;
+
+    private RuleData ruleData;
+
+    private ShenyuPluginChain chain;
+
+    private SelectorData selectorData;
+
+    private ServerHttpRequest request;
+
+    private ShenyuRequestLog requestLog;
+
+    @BeforeEach
+    public void setUp() {
+        this.loggingTencentClsPlugin = new LoggingTencentClsPlugin();
+        this.ruleData = Mockito.mock(RuleData.class);
+        this.chain = Mockito.mock(ShenyuPluginChain.class);
+        this.selectorData = Mockito.mock(SelectorData.class);
+        this.request = Mockito.mock(ServerHttpRequest.class);
+        this.requestLog = new ShenyuRequestLog();
+        MockServerHttpRequest request = MockServerHttpRequest
+                .get("localhost")
+                .remoteAddress(new InetSocketAddress(8090))
+                .header("X-source", "mock test")
+                .queryParam("queryParam", "Hello,World")
+                .build();
+        ConfigurableApplicationContext context = 
Mockito.mock(ConfigurableApplicationContext.class);
+        SpringBeanUtils.getInstance().setApplicationContext(context);
+        RemoteAddressResolver remoteAddressResolver = new 
RemoteAddressResolver() {
+        };
+        
Mockito.lenient().when(context.getBean(RemoteAddressResolver.class)).thenReturn(remoteAddressResolver);
+        this.exchange = Mockito.spy(MockServerWebExchange.from(request));
+        ShenyuContext shenyuContext = Mockito.mock(ShenyuContext.class);
+        exchange.getAttributes().put(Constants.CONTEXT, shenyuContext);
+    }
+
+    @Test
+    public void testDoExecute() {
+        
Mockito.when(chain.execute(ArgumentMatchers.any())).thenReturn(Mono.empty());
+        Mono<Void> result = loggingTencentClsPlugin.doLogExecute(exchange, 
chain, selectorData, ruleData, request, requestLog);
+        StepVerifier.create(result).expectSubscription().verifyComplete();
+    }
+
+    @Test
+    public void testGetOrder() {
+        Assertions.assertEquals(loggingTencentClsPlugin.getOrder(), 
PluginEnum.LOGGING_TENCENT_CLS.getCode());
+    }
+
+    @Test
+    public void testNamed() {
+        Assertions.assertEquals(loggingTencentClsPlugin.named(), 
PluginEnum.LOGGING_TENCENT_CLS.getName());
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollectorTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollectorTest.java
new file mode 100644
index 000000000..80ae2357d
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/collector/TencentClsSlsLogCollectorTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.collector;
+
+import org.apache.shenyu.plugin.logging.common.client.LogConsumeClient;
+import org.apache.shenyu.plugin.logging.common.collector.AbstractLogCollector;
+import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.apache.shenyu.plugin.tencent.cls.client.TencentClsLogCollectClient;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+
+/**
+ * The Test Case For DefaultLogCollector.
+ */
+public class TencentClsSlsLogCollectorTest {
+
+    private final ShenyuRequestLog shenyuRequestLog = new ShenyuRequestLog();
+
+    @BeforeEach
+    public void setUp() {
+        shenyuRequestLog.setClientIp("0.0.0.0");
+        shenyuRequestLog.setPath("org/apache/shenyu/plugin/logging");
+    }
+
+    @Test
+    public void testAbstractLogCollector() throws Exception {
+        TencentClsSlsLogCollector.getInstance().start();
+        Field field1 = AbstractLogCollector.class.getDeclaredField("started");
+        field1.setAccessible(true);
+        
Assertions.assertEquals(field1.get(TencentClsSlsLogCollector.getInstance()).toString(),
 "true");
+        TencentClsSlsLogCollector.getInstance().collect(shenyuRequestLog);
+        TencentClsSlsLogCollector.getInstance().close();
+        Field field2 = AbstractLogCollector.class.getDeclaredField("started");
+        field2.setAccessible(true);
+        
Assertions.assertEquals(field2.get(TencentClsSlsLogCollector.getInstance()).toString(),
 "false");
+    }
+
+    @Test
+    public void testGetLogConsumeClient() {
+        LogConsumeClient logConsumeClient = new 
TencentClsSlsLogCollector().getLogConsumeClient();
+        Assertions.assertEquals(TencentClsLogCollectClient.class, 
logConsumeClient.getClass());
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfigTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfigTest.java
new file mode 100644
index 000000000..7384c042f
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/config/TencentLogCollectConfigTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.config;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test cases for LogCollectConfig.
+ */
+public class TencentLogCollectConfigTest {
+
+    private final TencentLogCollectConfig.TencentClsLogConfig 
tencentClsLogConfig = new TencentLogCollectConfig.TencentClsLogConfig();
+
+    @Test
+    public void testLogCollectorConfigHost() {
+        tencentClsLogConfig.setSecretId("secretId");
+        tencentClsLogConfig.setSecretKey("secretKey");
+        tencentClsLogConfig.setEndpoint("endpoint");
+        tencentClsLogConfig.setTopic("topic");
+        tencentClsLogConfig.setTotalSizeInBytes("totalSizeInBytes");
+        tencentClsLogConfig.setMaxSendThreadCount("maxSendThreadCount");
+        tencentClsLogConfig.setMaxBlockSec("maxBlockSec");
+        tencentClsLogConfig.setMaxBatchSize("maxBatchSize");
+        tencentClsLogConfig.setMaxBatchCount("maxBatchCount");
+        tencentClsLogConfig.setLingerMs("lingerMs");
+        tencentClsLogConfig.setRetries("retries");
+        tencentClsLogConfig.setMaxReservedAttempts("maxReservedAttempts");
+        tencentClsLogConfig.setBaseRetryBackoffMs("baseRetryBackoffMs");
+        tencentClsLogConfig.setMaxRetryBackoffMs("maxRetryBackoffMs");
+        tencentClsLogConfig.setSendThreadCount(1);
+        Assertions.assertEquals(tencentClsLogConfig.getSecretId(), "secretId");
+        Assertions.assertEquals(tencentClsLogConfig.getSecretKey(), 
"secretKey");
+        Assertions.assertEquals(tencentClsLogConfig.getEndpoint(), "endpoint");
+        Assertions.assertEquals(tencentClsLogConfig.getTopic(), "topic");
+        Assertions.assertEquals(tencentClsLogConfig.getTotalSizeInBytes(), 
"totalSizeInBytes");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxSendThreadCount(), 
"maxSendThreadCount");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxBlockSec(), 
"maxBlockSec");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxBatchSize(), 
"maxBatchSize");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxBatchCount(), 
"maxBatchCount");
+        Assertions.assertEquals(tencentClsLogConfig.getLingerMs(), "lingerMs");
+        Assertions.assertEquals(tencentClsLogConfig.getRetries(), "retries");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxReservedAttempts(), 
"maxReservedAttempts");
+        Assertions.assertEquals(tencentClsLogConfig.getBaseRetryBackoffMs(), 
"baseRetryBackoffMs");
+        Assertions.assertEquals(tencentClsLogConfig.getMaxRetryBackoffMs(), 
"maxRetryBackoffMs");
+        Assertions.assertEquals(tencentClsLogConfig.getSendThreadCount(), 1);
+    }
+
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandlerTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandlerTest.java
new file mode 100644
index 000000000..747dbd45e
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/handler/LoggingTencentClsPluginDataHandlerTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.handler;
+
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.plugin.tencent.cls.client.TencentClsLogCollectClient;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+
+/**
+ * The Test Case For LoggingTencentClsPluginDataHandler.
+ */
+public class LoggingTencentClsPluginDataHandlerTest {
+
+    private LoggingTencentClsPluginDataHandler 
loggingTencentClsPluginDataHandler;
+
+    private final PluginData pluginData = new PluginData();
+
+    @BeforeEach
+    public void setUp() {
+        this.loggingTencentClsPluginDataHandler = new 
LoggingTencentClsPluginDataHandler();
+        pluginData.setEnabled(true);
+        pluginData.setConfig("{\"topic\":\"shenyu-topic-test\", 
\"secretId\":\"test\", \"secretKey\":\"test\", "
+                + "\"endpoint\":\"ap-guangzhou.cls.tencentcs.com\"}");
+    }
+
+    @Test
+    public void testHandlerPlugin() throws NoSuchFieldException, 
IllegalAccessException {
+        loggingTencentClsPluginDataHandler.handlerPlugin(pluginData);
+        Field field = 
loggingTencentClsPluginDataHandler.getClass().getDeclaredField("TENCENT_CLS_LOG_COLLECT_CLIENT");
+        field.setAccessible(true);
+        
Assertions.assertEquals(field.get(loggingTencentClsPluginDataHandler).getClass(),
 TencentClsLogCollectClient.class);
+        pluginData.setEnabled(false);
+        loggingTencentClsPluginDataHandler.handlerPlugin(pluginData);
+    }
+
+    @Test
+    public void testPluginNamed() {
+        
Assertions.assertEquals(loggingTencentClsPluginDataHandler.pluginNamed(), 
PluginEnum.LOGGING_TENCENT_CLS.getName());
+    }
+
+    @Test
+    public void testGetAliyunSlsLogCollectClient() {
+        
Assertions.assertEquals(LoggingTencentClsPluginDataHandler.getTencentClsLogCollectClient().getClass(),
 TencentClsLogCollectClient.class);
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/tencentcls/TencentClsLogCollectClientTest.java
 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/tencentcls/TencentClsLogCollectClientTest.java
new file mode 100644
index 000000000..f7251ce1b
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/plugin/tencent/cls/tencentcls/TencentClsLogCollectClientTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.tencent.cls.tencentcls;
+
+import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.logging.common.constant.GenericLoggingConstant;
+import org.apache.shenyu.plugin.logging.common.entity.ShenyuRequestLog;
+import org.apache.shenyu.plugin.tencent.cls.client.TencentClsLogCollectClient;
+import org.apache.shenyu.plugin.tencent.cls.config.TencentLogCollectConfig;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * test cases for TencentClsLogCollectClient.
+ */
+public class TencentClsLogCollectClientTest {
+
+    private TencentClsLogCollectClient tencentClsLogCollectClient;
+
+    private final Properties props = new Properties();
+
+    private final PluginData pluginData = new PluginData();
+
+    private TencentLogCollectConfig.TencentClsLogConfig tencentClsLogConfig;
+
+    private final List<ShenyuRequestLog> logs = new ArrayList<>();
+
+    private final ShenyuRequestLog shenyuRequestLog = new ShenyuRequestLog();
+
+    @BeforeEach
+    public void setup() {
+        this.tencentClsLogCollectClient = new TencentClsLogCollectClient();
+        pluginData.setEnabled(true);
+        pluginData.setConfig("{\"topic\":\"shenyu-topic-test\", 
\"secretId\":\"test\", \"secretKey\":\"test\", "
+                + "\"endpoint\":\"ap-guangzhou.cls.tencentcs.com\"}");
+        tencentClsLogConfig = 
GsonUtils.getInstance().fromJson(pluginData.getConfig(),
+                TencentLogCollectConfig.TencentClsLogConfig.class);
+        props.setProperty(GenericLoggingConstant.SECRET_ID, 
tencentClsLogConfig.getSecretId().trim());
+        props.setProperty(GenericLoggingConstant.SECRET_KEY, 
tencentClsLogConfig.getSecretKey().trim());
+        props.setProperty(GenericLoggingConstant.ENDPOINT, 
tencentClsLogConfig.getEndpoint().trim());
+        props.setProperty(GenericLoggingConstant.TOPIC, 
tencentClsLogConfig.getTopic().trim());
+        props.setProperty(GenericLoggingConstant.SEND_THREAD_COUNT, 
String.valueOf(tencentClsLogConfig.getSendThreadCount()));
+        shenyuRequestLog.setClientIp("0.0.0.0");
+        shenyuRequestLog.setPath("org/apache/shenyu/plugin/logging");
+        shenyuRequestLog.setRequestUri("org/apache/shenyu/plugin/logging");
+        logs.add(shenyuRequestLog);
+    }
+
+    @Test
+    public void testInitClient() throws NoSuchFieldException, 
IllegalAccessException {
+        tencentClsLogCollectClient.initClient(props);
+        Field field = 
tencentClsLogCollectClient.getClass().getDeclaredField("topic");
+        field.setAccessible(true);
+        Assertions.assertEquals(field.get(tencentClsLogCollectClient), 
"shenyu-topic-test");
+        tencentClsLogCollectClient.close();
+    }
+
+    @Test
+    public void testConsume() {
+        String msg = "";
+        
TencentLogCollectConfig.INSTANCE.setTencentClsLogConfig(tencentClsLogConfig);
+        tencentClsLogCollectClient.initClient(props);
+        try {
+            tencentClsLogCollectClient.consume(logs);
+        } catch (Exception e) {
+            msg = "false";
+        }
+        Assertions.assertEquals(msg, "");
+        Assertions.assertEquals(tencentClsLogConfig,
+                TencentLogCollectConfig.INSTANCE.getTencentClsLogConfig());
+        tencentClsLogCollectClient.close();
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/pom.xml 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/pom.xml
index 13d84f909..8c7e76746 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/pom.xml
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/pom.xml
@@ -65,5 +65,6 @@
         <module>shenyu-spring-boot-starter-plugin-mock</module>
         <module>shenyu-spring-boot-starter-plugin-logging-aliyun-sls</module>
         <module>shenyu-spring-boot-starter-plugin-logging-pulsar</module>
+        <module>shenyu-spring-boot-starter-plugin-logging-tencent-cls</module>
     </modules>
 </project>
diff --git a/shenyu-plugin/shenyu-plugin-logging/pom.xml 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/pom.xml
similarity index 50%
copy from shenyu-plugin/shenyu-plugin-logging/pom.xml
copy to 
shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/pom.xml
index f9187f919..657bb9f84 100644
--- a/shenyu-plugin/shenyu-plugin-logging/pom.xml
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/pom.xml
@@ -16,23 +16,33 @@
   ~ limitations under the License.
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
+        <artifactId>shenyu-spring-boot-starter-plugin</artifactId>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu-plugin</artifactId>
         <version>2.5.1-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
-    <artifactId>shenyu-plugin-logging</artifactId>
-    <packaging>pom</packaging>
 
-    <modules>
-        <module>shenyu-plugin-logging-common</module>
-        <module>shenyu-plugin-logging-console</module>
-        <module>shenyu-plugin-logging-rocketmq</module>
-        <module>shenyu-plugin-logging-kafka</module>
-        <module>shenyu-plugin-logging-elasticsearch</module>
-        <module>shenyu-plugin-logging-aliyun-sls</module>
-        <module>shenyu-plugin-logging-pulsar</module>
-    </modules>
-</project>
\ No newline at end of file
+    
<artifactId>shenyu-spring-boot-starter-plugin-logging-tencent-cls</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-plugin-logging-tencent-cls</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfiguration.java
new file mode 100644
index 000000000..f19866a85
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfiguration.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.springboot.starter.plugin.logging.tencent.cls;
+
+import org.apache.shenyu.plugin.tencent.cls.LoggingTencentClsPlugin;
+import org.apache.shenyu.plugin.api.ShenyuPlugin;
+import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import 
org.apache.shenyu.plugin.tencent.cls.handler.LoggingTencentClsPluginDataHandler;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * The type Logging Tencent cls plugin configuration.
+ */
+@Configuration
+@ConditionalOnProperty(value = {"shenyu.plugins.logging-tencent-cls.enabled"}, 
havingValue = "true", matchIfMissing = true)
+public class LoggingTencentClsPluginConfiguration {
+
+    /**
+     * logging Tencent cls plugin data handler.
+     * @return logging Tencent cls PluginDataHandler
+     */
+    @Bean
+    public PluginDataHandler loggingTencentClsPluginDataHandler() {
+        return new LoggingTencentClsPluginDataHandler();
+    }
+
+    /**
+     * Logging Tencent cls plugin.
+     * @return LoggingTencentClsPlugin
+     */
+    @Bean
+    public ShenyuPlugin loggingTencentClsPlugin() {
+        return new LoggingTencentClsPlugin();
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.factories
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.factories
new file mode 100644
index 000000000..ed22e6f34
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.shenyu.springboot.starter.plugin.logging.tencent.cls.LoggingTencentClsPluginConfiguration
\ No newline at end of file
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.provides
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.provides
new file mode 100644
index 000000000..1b26f90aa
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/main/resources/META-INF/spring.provides
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+provides: shenyu-spring-boot-starter-plugin-logging-tencent-cls
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfigurationTest.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfigurationTest.java
new file mode 100644
index 000000000..47fa244e2
--- /dev/null
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-logging-tencent-cls/src/test/java/org/apache/shenyu/springboot/starter/plugin/logging/tencent/cls/LoggingTencentClsPluginConfigurationTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.springboot.starter.plugin.logging.tencent.cls;
+
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.plugin.api.ShenyuPlugin;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import 
org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Test case for {@link LoggingTencentClsPluginConfiguration}.
+ */
+@Configuration
+@EnableConfigurationProperties
+public class LoggingTencentClsPluginConfigurationTest {
+
+    @Test
+    public void testLoggingPlugin() {
+        new ApplicationContextRunner()
+                
.withConfiguration(AutoConfigurations.of(LoggingTencentClsPluginConfiguration.class))
+                .withBean(LoggingTencentClsPluginConfigurationTest.class)
+                .withPropertyValues("debug=true")
+                .run(context -> {
+                    ShenyuPlugin plugin = 
context.getBean("loggingTencentClsPlugin", ShenyuPlugin.class);
+                    assertNotNull(plugin);
+                    
assertThat(plugin.named()).isEqualTo(PluginEnum.LOGGING_TENCENT_CLS.getName());
+                });
+    }
+}

Reply via email to