From 89fcf99fa952459c89a40d6f58e8b4fb50bd8122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E9=A9=AC=E5=93=A5?= Date: Wed, 3 Aug 2022 09:17:29 +0800 Subject: [PATCH 1/2] Optimized alarm notification capabilities (#435) --- .../cn/hippo4j/common/toolkit/Singleton.java | 82 +++++++ .../platform/DingSendMessageHandler.java | 7 +- .../platform/LarkSendMessageHandler.java | 22 +- .../platform/WeChatSendMessageHandler.java | 7 +- .../lark-alarm-timeout-replace.json | 30 +++ .../lark-alarm-trace-replace.json | 8 + .../robot/dynamic-thread-pool/lark-alarm.json | 205 +++++++++++++++++- .../dynamic-thread-pool/lark-config.json | 156 +++++++++++++ 8 files changed, 505 insertions(+), 12 deletions(-) create mode 100644 hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Singleton.java create mode 100644 hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json create mode 100644 hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json create mode 100644 hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-config.json diff --git a/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Singleton.java b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Singleton.java new file mode 100644 index 00000000..44a23934 --- /dev/null +++ b/hippo4j-common/src/main/java/cn/hippo4j/common/toolkit/Singleton.java @@ -0,0 +1,82 @@ +/* + * 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 cn.hippo4j.common.toolkit; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +/** + * Singleton object container. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class Singleton { + + private static final ConcurrentHashMap SINGLE_OBJECT_POOL = new ConcurrentHashMap(); + + /** + * Get a singleton object by key. + * + * @param key + * @param + * @return + */ + public static T get(String key) { + Object result = SINGLE_OBJECT_POOL.get(key); + return result == null ? null : (T) result; + } + + /** + * Get a singleton object by key. + * + *

When empty, build a singleton object through supplier and put it into the container. + * + * @param key + * @param supplier + * @param + * @return + */ + public static T get(String key, Supplier supplier) { + Object result = SINGLE_OBJECT_POOL.get(key); + if (result == null && (result = supplier.get()) != null) { + SINGLE_OBJECT_POOL.put(key, result); + } + return result != null ? (T) result : null; + } + + /** + * Object into container. + * + * @param value + */ + public static void put(Object value) { + put(value.getClass().getName(), value); + } + + /** + * Object into container. + * + * @param key + * @param value + */ + public static void put(String key, Object value) { + SINGLE_OBJECT_POOL.put(key, value); + } +} diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java index 4c3c7322..f2b6bd87 100644 --- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/DingSendMessageHandler.java @@ -17,6 +17,7 @@ package cn.hippo4j.message.platform; +import cn.hippo4j.common.toolkit.Singleton; import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.message.dto.NotifyConfigDTO; import cn.hippo4j.message.enums.NotifyPlatformEnum; @@ -54,13 +55,15 @@ public class DingSendMessageHandler extends AbstractRobotSendMessageHandler { @Override protected RobotMessageActualContent buildMessageActualContent() { + String dingAlarmTxtKey = "message/robot/dynamic-thread-pool/ding-alarm.txt"; + String dingConfigTxtKey = "message/robot/dynamic-thread-pool/ding-config.txt"; RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder() .receiveSeparator(", @") .changeSeparator(" -> ") .replaceTxt(DING_ALARM_TIMOUT_REPLACE_TXT) .traceReplaceTxt(DING_ALARM_TIMOUT_TRACE_REPLACE_TXT) - .alarmMessageContent(FileUtil.readUtf8String("message/robot/dynamic-thread-pool/ding-alarm.txt")) - .configMessageContent(FileUtil.readUtf8String("message/robot/dynamic-thread-pool/ding-config.txt")) + .alarmMessageContent(Singleton.get(dingAlarmTxtKey, () -> FileUtil.readUtf8String(dingAlarmTxtKey))) + .configMessageContent(Singleton.get(dingConfigTxtKey, () -> FileUtil.readUtf8String(dingConfigTxtKey))) .build(); return robotMessageActualContent; } diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java index a2fd03ee..ab5b4413 100644 --- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/LarkSendMessageHandler.java @@ -17,6 +17,7 @@ package cn.hippo4j.message.platform; +import cn.hippo4j.common.toolkit.Singleton; import cn.hippo4j.message.dto.NotifyConfigDTO; import cn.hippo4j.message.enums.NotifyPlatformEnum; import cn.hippo4j.message.enums.NotifyTypeEnum; @@ -25,6 +26,7 @@ import cn.hippo4j.message.request.AlarmNotifyRequest; import cn.hippo4j.message.request.ChangeParameterNotifyRequest; import cn.hippo4j.common.toolkit.StringUtil; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import lombok.AllArgsConstructor; @@ -53,20 +55,25 @@ public class LarkSendMessageHandler implements SendMessageHandler FileUtil.readUtf8String(larkAlarmTxtKey)); + String larkAlarmTimoutReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json"; + String larkAlarmTimoutReplaceJson = Singleton.get(larkAlarmTimoutReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutReplaceJsonKey)); if (Objects.equals(alarmNotifyRequest.getNotifyTypeEnum(), NotifyTypeEnum.TIMEOUT)) { String executeTimeoutTrace = alarmNotifyRequest.getExecuteTimeoutTrace(); + String larkAlarmTimoutTraceReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json"; + String larkAlarmTimoutTraceReplaceJson = Singleton.get(larkAlarmTimoutTraceReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutTraceReplaceJsonKey)); if (StringUtil.isNotBlank(executeTimeoutTrace)) { - String larkAlarmTimoutTraceReplaceTxt = String.format(LARK_ALARM_TIMOUT_TRACE_REPLACE_TXT, executeTimeoutTrace); - larkAlarmTimoutReplaceTxt = StrUtil.replace(LARK_ALARM_TIMOUT_REPLACE_TXT, LARK_ALARM_TIMOUT_TRACE_REPLACE_TXT, larkAlarmTimoutTraceReplaceTxt); + String larkAlarmTimoutTraceReplaceTxt = String.format(larkAlarmTimoutTraceReplaceJson, executeTimeoutTrace); + larkAlarmTimoutReplaceTxt = StrUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, larkAlarmTimoutTraceReplaceTxt); } else { - larkAlarmTimoutReplaceTxt = StrUtil.replace(LARK_ALARM_TIMOUT_REPLACE_TXT, LARK_ALARM_TIMOUT_TRACE_REPLACE_TXT, ""); + larkAlarmTimoutReplaceTxt = StrUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, ""); } larkAlarmTimoutReplaceTxt = String.format(larkAlarmTimoutReplaceTxt, alarmNotifyRequest.getExecuteTime(), alarmNotifyRequest.getExecuteTimeOut()); - larkAlarmTxt = StrUtil.replace(LARK_ALARM_JSON_STR, LARK_ALARM_TIMOUT_REPLACE_TXT, larkAlarmTimoutReplaceTxt); + larkAlarmTxt = StrUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, larkAlarmTimoutReplaceTxt); } else { - larkAlarmTxt = StrUtil.replace(LARK_ALARM_JSON_STR, LARK_ALARM_TIMOUT_REPLACE_TXT, ""); + larkAlarmTxt = StrUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, ""); } String text = String.format(larkAlarmTxt, @@ -118,7 +125,8 @@ public class LarkSendMessageHandler implements SendMessageHandler FileUtil.readUtf8String(larkNoticeJsonKey)); String text = String.format(larkNoticeJson, // 环境 changeParameterNotifyRequest.getActive(), diff --git a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/WeChatSendMessageHandler.java b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/WeChatSendMessageHandler.java index c09beb1d..b10bad18 100644 --- a/hippo4j-message/src/main/java/cn/hippo4j/message/platform/WeChatSendMessageHandler.java +++ b/hippo4j-message/src/main/java/cn/hippo4j/message/platform/WeChatSendMessageHandler.java @@ -18,6 +18,7 @@ package cn.hippo4j.message.platform; import cn.hippo4j.common.toolkit.JSONUtil; +import cn.hippo4j.common.toolkit.Singleton; import cn.hippo4j.message.enums.NotifyPlatformEnum; import cn.hippo4j.message.platform.base.AbstractRobotSendMessageHandler; import cn.hippo4j.message.platform.base.RobotMessageActualContent; @@ -43,13 +44,15 @@ public class WeChatSendMessageHandler extends AbstractRobotSendMessageHandler { @Override protected RobotMessageActualContent buildMessageActualContent() { + String weChatAlarmTxtKet = "message/robot/dynamic-thread-pool/wechat-alarm.txt"; + String weChatConfigTxtKet = "message/robot/dynamic-thread-pool/wechat-alarm.txt"; RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder() .receiveSeparator("><@") .changeSeparator(" ➲ ") .replaceTxt(WE_CHAT_ALARM_TIMOUT_REPLACE_TXT) .traceReplaceTxt(WE_CHAT_ALARM_TIMOUT_TRACE_REPLACE_TXT) - .alarmMessageContent(FileUtil.readUtf8String("message/robot/dynamic-thread-pool/wechat-alarm.txt")) - .configMessageContent(FileUtil.readUtf8String("message/robot/dynamic-thread-pool/wechat-config.txt")) + .alarmMessageContent(Singleton.get(weChatAlarmTxtKet, () -> FileUtil.readUtf8String(weChatAlarmTxtKet))) + .configMessageContent(Singleton.get(weChatConfigTxtKet, () -> FileUtil.readUtf8String(weChatConfigTxtKet))) .build(); return robotMessageActualContent; } diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json new file mode 100644 index 00000000..14d038b4 --- /dev/null +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json @@ -0,0 +1,30 @@ + + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 任务执行时间:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 超时时间:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 链路信息:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json new file mode 100644 index 00000000..9f95a8b6 --- /dev/null +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json @@ -0,0 +1,8 @@ + + { + "is_short": true, + "text": { + "content": "** 链路信息:** %s", + "tag": "lark_md" + } + } diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json index 93ceef7a..1c60f9a5 100644 --- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json @@ -1,3 +1,206 @@ { - "name": "123" + "msg_type": "interactive", + "card": { + "config": { + "wide_screen_mode": true + }, + "header": { + "template": "red", + "title": { + "content": "[🔥警报] %s 动态线程池运行告警(%s)", + "tag": "plain_text" + } + }, + "elements": [ + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 线程池ID:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 应用名称:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 应用实例:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 核心线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 最大线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 当前线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 活跃线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 同存最大线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 线程池任务总量:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 队列类型:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 队列容量:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 队列元素个数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 队列剩余个数:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 任务执行时间:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 超时时间:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 链路信息:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 拒绝策略:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 拒绝策略执行次数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** OWNER:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 播报时间: ** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "tag": "note", + "elements": [ + { + "tag": "plain_text", + "content": "提示: %s 分钟内此线程池不会重复告警(可配置)" + } + ] + } + ] + } } \ No newline at end of file diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-config.json b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-config.json new file mode 100644 index 00000000..eb0caeaa --- /dev/null +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-config.json @@ -0,0 +1,156 @@ +{ + "msg_type": "interactive", + "card": { + "config": { + "wide_screen_mode": true + }, + "header": { + "template": "greed", + "title": { + "content": "[通知] %s 动态线程池参数变更", + "tag": "plain_text" + } + }, + "elements": [ + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 线程池ID:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 应用名称:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 应用实例:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 核心线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 最大线程数:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 核心线程超时:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 线程存活时间:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** 队列类型:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 队列容量:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 执行超时时间:** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "fields": [ + { + "is_short": true, + "text": { + "content": "** AGO 拒绝策略:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** NOW 拒绝策略:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** OWNER:** %s", + "tag": "lark_md" + } + }, + { + "is_short": true, + "text": { + "content": "** 播报时间: ** %s", + "tag": "lark_md" + } + } + ], + "tag": "div" + }, + { + "tag": "hr" + }, + { + "tag": "note", + "elements": [ + { + "tag": "plain_text", + "content": "提示:动态线程池配置变更实时通知(无限制)" + } + ] + } + ] + } +} \ No newline at end of file From 19046a38a44efdbaccc19efc1fdb8e84805b8061 Mon Sep 17 00:00:00 2001 From: maxisvest <1447829379@qq.com> Date: Wed, 3 Aug 2022 17:02:41 +0800 Subject: [PATCH 2/2] add dot for prometheus condition matches --- .../starter/config/condition/PrometheusMonitorCondition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hippo4j-spring-boot/hippo4j-core-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/condition/PrometheusMonitorCondition.java b/hippo4j-spring-boot/hippo4j-core-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/condition/PrometheusMonitorCondition.java index 5db7b9dc..dc21554c 100644 --- a/hippo4j-spring-boot/hippo4j-core-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/condition/PrometheusMonitorCondition.java +++ b/hippo4j-spring-boot/hippo4j-core-spring-boot-starter/src/main/java/cn/hippo4j/core/springboot/starter/config/condition/PrometheusMonitorCondition.java @@ -31,7 +31,7 @@ public class PrometheusMonitorCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - String collectType = context.getEnvironment().getProperty(BootstrapCoreProperties.PREFIX + "collect-type", ""); + String collectType = context.getEnvironment().getProperty(BootstrapCoreProperties.PREFIX + ".collect-type", ""); return StringUtil.isNotEmpty(collectType) && collectType.contains(MonitorTypeEnum.PROMETHEUS.name().toLowerCase()) ? true : false; } }