抽象通知报警消息模块. (#102)

pull/110/merge
chen.ma 3 years ago
parent 9c0d660ef8
commit 8d788381a1

@ -80,4 +80,6 @@ public class Constants {
public static final String DEFAULT_GROUP = "default group";
public static final String UNKNOWN = "unknown";
}

@ -1,7 +1,17 @@
package cn.hippo4j.common.notify;
import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.notify.request.AlarmNotifyRequest;
import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import java.util.List;
import java.util.Map;
/**
* Base send message service impl.
@ -9,16 +19,95 @@ import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
* @author chen.ma
* @date 2022/2/22 21:32
*/
public class BaseSendMessageServiceImpl implements SendMessageService {
@Slf4j
@RequiredArgsConstructor
public class BaseSendMessageServiceImpl implements HippoSendMessageService, CommandLineRunner {
private final NotifyConfigBuilder notifyConfigBuilder;
private final AlarmControlHandler alarmControlHandler;
private final Map<String, List<NotifyConfigDTO>> notifyConfigs = Maps.newHashMap();
private final Map<String, SendMessageHandler> sendMessageHandlers = Maps.newHashMap();
@Override
public void sendAlarmMessage(NotifyTypeEnum typeEnum, AlarmNotifyRequest alarmNotifyRequest) {
String threadPoolId = alarmNotifyRequest.getThreadPoolId();
String buildKey = StrUtil.builder(threadPoolId, "+", "ALARM").toString();
List<NotifyConfigDTO> notifyList = notifyConfigs.get(buildKey);
if (CollUtil.isEmpty(notifyList)) {
log.warn("Please configure alarm notification on the server. key :: [{}]", threadPoolId);
return;
}
notifyList.forEach(each -> {
try {
SendMessageHandler messageHandler = sendMessageHandlers.get(each.getPlatform());
if (messageHandler == null) {
log.warn("Please configure alarm notification on the server. key :: [{}]", threadPoolId);
return;
}
if (isSendAlarm(each.getThreadPoolId(), each.setTypeEnum(typeEnum))) {
messageHandler.sendAlarmMessage(each, alarmNotifyRequest);
}
} catch (Exception ex) {
log.warn("Failed to send thread pool alarm notification. key :: [{}]", threadPoolId, ex);
}
});
}
@Override
public void sendChangeMessage(ChangeParameterNotifyRequest changeParameterNotifyRequest) {
String threadPoolId = changeParameterNotifyRequest.getThreadPoolId();
String buildKey = StrUtil.builder(threadPoolId, "+", "CONFIG").toString();
List<NotifyConfigDTO> notifyList = notifyConfigs.get(buildKey);
if (CollUtil.isEmpty(notifyList)) {
log.warn("Please configure alarm notification on the server. key :: [{}]", threadPoolId);
return;
}
notifyList.forEach(each -> {
try {
SendMessageHandler messageHandler = sendMessageHandlers.get(each.getPlatform());
if (messageHandler == null) {
log.warn("Please configure alarm notification on the server. key :: [{}]", threadPoolId);
return;
}
messageHandler.sendChangeMessage(each, changeParameterNotifyRequest);
} catch (Exception ex) {
log.warn("Failed to send thread pool change notification. key :: [{}]", threadPoolId, ex);
}
});
}
/**
* Is send alarm.
*
* @param threadPoolId
* @param notifyInfo
* @return
*/
private boolean isSendAlarm(String threadPoolId, NotifyConfigDTO notifyInfo) {
AlarmControlDTO alarmControl = AlarmControlDTO.builder()
.threadPool(threadPoolId)
.platform(notifyInfo.getPlatform())
.typeEnum(notifyInfo.getTypeEnum())
.build();
return alarmControlHandler.isSendAlarm(alarmControl);
}
@Override
public void run(String... args) throws Exception {
Map<String, SendMessageHandler> sendMessageHandlerMap =
ApplicationContextHolder.getBeansOfType(SendMessageHandler.class);
sendMessageHandlerMap.values().forEach(each -> sendMessageHandlers.put(each.getType(), each));
Map<String, List<NotifyConfigDTO>> buildNotify = notifyConfigBuilder.buildNotify();
notifyConfigs.putAll(buildNotify);
}
}

@ -9,7 +9,7 @@ import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
* @author chen.ma
* @date 2022/2/22 19:56
*/
public interface SendMessageService {
public interface HippoSendMessageService {
/**
* Send alarm message.

@ -0,0 +1,21 @@
package cn.hippo4j.common.notify;
import java.util.List;
import java.util.Map;
/**
* Notify config builder.
*
* @author chen.ma
* @date 2022/2/24 19:50
*/
public interface NotifyConfigBuilder {
/**
* Build notify.
*
* @return
*/
Map<String, List<NotifyConfigDTO>> buildNotify();
}

@ -1,6 +1,5 @@
package cn.hippo4j.starter.alarm;
package cn.hippo4j.common.notify;
import cn.hippo4j.common.notify.NotifyTypeEnum;
import lombok.Data;
import lombok.experimental.Accessors;
@ -12,7 +11,7 @@ import lombok.experimental.Accessors;
*/
@Data
@Accessors(chain = true)
public class NotifyDTO {
public class NotifyConfigDTO {
/**
* id
@ -27,7 +26,7 @@ public class NotifyDTO {
/**
* 线id
*/
private String tpId;
private String threadPoolId;
/**
*

@ -1,6 +1,6 @@
package cn.hippo4j.common.notify;
import cn.hippo4j.common.notify.request.NotifyRequest;
import cn.hippo4j.common.notify.request.base.NotifyRequest;
/**
* Send message handler.
@ -20,15 +20,17 @@ public interface SendMessageHandler<T extends NotifyRequest, R extends NotifyReq
/**
* Send alarm message.
*
* @param notifyConfig
* @param alarmNotifyRequest
*/
void sendAlarmMessage(T alarmNotifyRequest);
void sendAlarmMessage(NotifyConfigDTO notifyConfig, T alarmNotifyRequest);
/**
* Send change message.
*
* @param notifyConfig
* @param changeParameterNotifyRequest
*/
void sendChangeMessage(R changeParameterNotifyRequest);
void sendChangeMessage(NotifyConfigDTO notifyConfig, R changeParameterNotifyRequest);
}

@ -1,17 +1,17 @@
package cn.hippo4j.starter.alarm;
package cn.hippo4j.common.notify;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* Thread pool alarm.
* Thread pool notify alarm.
*
* @author chen.ma
* @date 2021/8/15 13:13
*/
@Data
@AllArgsConstructor
public class ThreadPoolAlarm {
public class ThreadPoolNotifyAlarm {
/**
* isAlarm

@ -0,0 +1,26 @@
package cn.hippo4j.common.notify;
import lombok.Data;
import java.util.List;
/**
* Thread pool notify DTO.
*
* @author chen.ma
* @date 2022/2/24 19:08
*/
@Data
public class ThreadPoolNotifyDTO {
/**
* notifyKey
*/
private String notifyKey;
/**
* notifyList
*/
private List<NotifyConfigDTO> notifyList;
}

@ -1,9 +1,10 @@
package cn.hippo4j.common.notify.platform;
import cn.hippo4j.common.notify.NotifyConfigDTO;
import cn.hippo4j.common.notify.NotifyPlatformEnum;
import cn.hippo4j.common.notify.request.RobotAlarmNotifyRequest;
import cn.hippo4j.common.notify.request.RobotChangeParameterNotifyRequest;
import cn.hippo4j.common.notify.SendMessageHandler;
import cn.hippo4j.common.notify.request.AlarmNotifyRequest;
import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
import cn.hutool.core.date.DateUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
@ -25,7 +26,7 @@ import static cn.hippo4j.common.notify.platform.DingAlarmConstants.DING_NOTICE_T
* @date 2021/8/15 15:49
*/
@Slf4j
public class DingSendMessageHandler implements SendMessageHandler<RobotAlarmNotifyRequest, RobotChangeParameterNotifyRequest> {
public class DingSendMessageHandler implements SendMessageHandler<AlarmNotifyRequest, ChangeParameterNotifyRequest> {
@Override
public String getType() {
@ -33,8 +34,8 @@ public class DingSendMessageHandler implements SendMessageHandler<RobotAlarmNoti
}
@Override
public void sendAlarmMessage(RobotAlarmNotifyRequest alarmNotifyRequest) {
String[] receives = alarmNotifyRequest.getReceives().split(",");
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String[] receives = notifyConfig.getReceives().split(",");
String afterReceives = Joiner.on(", @").join(receives);
String text = String.format(
@ -81,14 +82,14 @@ public class DingSendMessageHandler implements SendMessageHandler<RobotAlarmNoti
DateUtil.now()
);
execute(alarmNotifyRequest.getSecretKey(), DingAlarmConstants.DING_ALARM_TITLE, text, Lists.newArrayList(receives));
execute(notifyConfig.getSecretKey(), DingAlarmConstants.DING_ALARM_TITLE, text, Lists.newArrayList(receives));
}
@Override
public void sendChangeMessage(RobotChangeParameterNotifyRequest changeParameterNotifyRequest) {
public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
String threadPoolId = changeParameterNotifyRequest.getThreadPoolId();
String[] receives = changeParameterNotifyRequest.getReceives().split(",");
String[] receives = notifyConfig.getReceives().split(",");
String afterReceives = Joiner.on(", @").join(receives);
/**
@ -111,7 +112,7 @@ public class DingSendMessageHandler implements SendMessageHandler<RobotAlarmNoti
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
@ -125,7 +126,7 @@ public class DingSendMessageHandler implements SendMessageHandler<RobotAlarmNoti
DateUtil.now()
);
execute(changeParameterNotifyRequest.getSecretKey(), DingAlarmConstants.DING_NOTICE_TITLE, text, Lists.newArrayList(receives));
execute(notifyConfig.getSecretKey(), DingAlarmConstants.DING_NOTICE_TITLE, text, Lists.newArrayList(receives));
}
private void execute(String secretKey, String title, String text, List<String> mobiles) {

@ -13,16 +13,6 @@ public class LarkAlarmConstants {
*/
public static final String LARK_BOT_URL = "https://open.feishu.cn/open-apis/bot/v2/hook/";
/**
* lark json
*/
public static final String ALARM_JSON_PATH = "classpath:properties/lark/alarm.json";
/**
* lark json
*/
public static final String NOTICE_JSON_PATH = "classpath:properties/lark/notice.json";
/**
* lark at format. openid
* openid,@
@ -39,4 +29,15 @@ public class LarkAlarmConstants {
* lark openid prefix
*/
public static final String LARK_OPENID_PREFIX = "ou_";
/**
* lark alarm json str
*/
public static final String LARK_ALARM_JSON_STR = "{\"msg_type\":\"interactive\",\"card\":{\"config\":{\"wide_screen_mode\":true},\"header\":{\"template\":\"red\",\"title\":{\"content\":\"[\uD83D\uDD25警报] %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\"}},{\"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\":\"** 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 分钟内此线程池不会重复告警(可配置)\"}]}]}}";
/**
* lark notice json str
*/
public static final String LARK_NOTICE_JSON_STR = "{\"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 / SECONDS\",\"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\"}}],\"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\":\"提示:动态线程池配置变更实时通知(无限制)\"}]}]}}";
}

@ -0,0 +1,151 @@
package cn.hippo4j.common.notify.platform;
import cn.hippo4j.common.notify.NotifyConfigDTO;
import cn.hippo4j.common.notify.NotifyPlatformEnum;
import cn.hippo4j.common.notify.SendMessageHandler;
import cn.hippo4j.common.notify.request.AlarmNotifyRequest;
import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.stream.Collectors;
import static cn.hippo4j.common.notify.platform.LarkAlarmConstants.*;
/**
* Send lark notification message.
*
* @author imyzt
* @date 2021/11/22 21:12
*/
@Slf4j
@AllArgsConstructor
public class LarkSendMessageHandler implements SendMessageHandler<AlarmNotifyRequest, ChangeParameterNotifyRequest> {
@Override
public String getType() {
return NotifyPlatformEnum.LARK.name();
}
@Override
@SneakyThrows
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String afterReceives = getReceives(alarmNotifyRequest.getReceives());
String larkAlarmJson = LARK_ALARM_JSON_STR;
String text = String.format(larkAlarmJson,
// 环境
alarmNotifyRequest.getActive(),
// 线程池ID
alarmNotifyRequest.getThreadPoolId(),
// 应用名称
alarmNotifyRequest.getAppName(),
// 实例信息
alarmNotifyRequest.getIdentify(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
alarmNotifyRequest.getMaximumPoolSize(),
// 当前线程数
alarmNotifyRequest.getPoolSize(),
// 活跃线程数
alarmNotifyRequest.getActiveCount(),
// 最大任务数
alarmNotifyRequest.getLargestPoolSize(),
// 线程池任务总量
alarmNotifyRequest.getCompletedTaskCount(),
// 队列类型名称
alarmNotifyRequest.getClass().getSimpleName(),
// 队列容量
alarmNotifyRequest.getCapacity(),
// 队列元素个数
alarmNotifyRequest.getQueueSize(),
// 队列剩余个数
alarmNotifyRequest.getRemainingCapacity(),
// 拒绝策略名称
alarmNotifyRequest.getRejectedExecutionHandlerName(),
// 拒绝策略次数
alarmNotifyRequest.getRejectCountNum(),
// 告警手机号
afterReceives,
// 当前时间
DateUtil.now(),
// 报警频率
alarmNotifyRequest.getInterval()
);
execute(notifyConfig.getSecretKey(), text);
}
@Override
@SneakyThrows
public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
String threadPoolId = changeParameterNotifyRequest.getThreadPoolId();
String afterReceives = getReceives(notifyConfig.getReceives());
String larkNoticeJson = LARK_NOTICE_JSON_STR;
/**
* hesitant e.g.
*/
String text = String.format(larkNoticeJson,
// 环境
changeParameterNotifyRequest.getActive(),
// 线程池名称
threadPoolId,
// 应用名称
changeParameterNotifyRequest.getAppName(),
// 实例信息
changeParameterNotifyRequest.getIdentify(),
// 核心线程数
changeParameterNotifyRequest.getBeforeCorePoolSize() + " ➲ " + changeParameterNotifyRequest.getNowCorePoolSize(),
// 最大线程数
changeParameterNotifyRequest.getBeforeMaximumPoolSize() + " ➲ " + changeParameterNotifyRequest.getNowMaximumPoolSize(),
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
changeParameterNotifyRequest.getBeforeQueueCapacity() + " ➲ " + changeParameterNotifyRequest.getNowQueueCapacity(),
// 拒绝策略
changeParameterNotifyRequest.getBeforeRejectedName(),
changeParameterNotifyRequest.getNowRejectedName(),
// 告警手机号
afterReceives,
// 当前时间
DateUtil.now()
);
execute(notifyConfig.getSecretKey(), text);
}
private String getReceives(String receives) {
if (StringUtil.isBlank(receives)) {
return "";
}
return Arrays.stream(receives.split(","))
.map(receive -> StrUtil.startWith(receive, LARK_OPENID_PREFIX) ?
String.format(LARK_AT_FORMAT_OPENID, receive) : String.format(LARK_AT_FORMAT_USERNAME, receive))
.collect(Collectors.joining(" "));
}
private void execute(String secretKey, String text) {
String serverUrl = LARK_BOT_URL + secretKey;
try {
HttpRequest.post(serverUrl).body(text).execute();
} catch (Exception ex) {
log.error("Lark failed to send message", ex);
}
}
}

@ -1,9 +1,10 @@
package cn.hippo4j.common.notify.platform;
import cn.hippo4j.common.notify.NotifyConfigDTO;
import cn.hippo4j.common.notify.NotifyPlatformEnum;
import cn.hippo4j.common.notify.SendMessageHandler;
import cn.hippo4j.common.notify.request.RobotAlarmNotifyRequest;
import cn.hippo4j.common.notify.request.RobotChangeParameterNotifyRequest;
import cn.hippo4j.common.notify.request.AlarmNotifyRequest;
import cn.hippo4j.common.notify.request.ChangeParameterNotifyRequest;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
@ -21,7 +22,7 @@ import static cn.hippo4j.common.notify.platform.WeChatAlarmConstants.*;
* @date 2021/11/26 20:06
*/
@Slf4j
public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNotifyRequest, RobotChangeParameterNotifyRequest> {
public class WeChatSendMessageHandler implements SendMessageHandler<AlarmNotifyRequest, ChangeParameterNotifyRequest> {
@Override
public String getType() {
@ -29,8 +30,8 @@ public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNo
}
@Override
public void sendAlarmMessage(RobotAlarmNotifyRequest alarmNotifyRequest) {
String[] receives = alarmNotifyRequest.getReceives().split(",");
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String[] receives = notifyConfig.getReceives().split(",");
String afterReceives = Joiner.on(", @").join(receives);
String text = String.format(
@ -44,7 +45,7 @@ public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNo
// 实例信息
alarmNotifyRequest.getIdentify(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(),
notifyConfig.getTypeEnum(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
@ -72,18 +73,18 @@ public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNo
// 告警手机号
afterReceives,
// 报警频率
alarmNotifyRequest.getInterval(),
notifyConfig.getInterval(),
// 当前时间
DateUtil.now()
);
execute(alarmNotifyRequest.getSecretKey(), text);
execute(notifyConfig.getSecretKey(), text);
}
@Override
public void sendChangeMessage(RobotChangeParameterNotifyRequest changeParameterNotifyRequest) {
public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
String threadPoolId = changeParameterNotifyRequest.getThreadPoolId();
String[] receives = changeParameterNotifyRequest.getReceives().split(",");
String[] receives = notifyConfig.getReceives().split(",");
String afterReceives = Joiner.on("><@").join(receives);
String text = String.format(
@ -103,7 +104,7 @@ public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNo
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
@ -117,7 +118,7 @@ public class WeChatSendMessageHandler implements SendMessageHandler<RobotAlarmNo
DateUtil.now()
);
execute(changeParameterNotifyRequest.getSecretKey(), text);
execute(notifyConfig.getSecretKey(), text);
}
/**

@ -1,7 +1,9 @@
package cn.hippo4j.common.notify.request;
import cn.hippo4j.common.notify.NotifyTypeEnum;
import cn.hippo4j.common.notify.request.base.BaseNotifyRequest;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* Alarm notify request.
@ -10,6 +12,7 @@ import lombok.Data;
* @date 2022/2/22 19:41
*/
@Data
@Accessors(chain = true)
public class AlarmNotifyRequest extends BaseNotifyRequest {
/**

@ -1,5 +1,6 @@
package cn.hippo4j.common.notify.request;
import cn.hippo4j.common.notify.request.base.BaseNotifyRequest;
import lombok.Data;
/**

@ -0,0 +1,23 @@
package cn.hippo4j.common.notify.request;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.List;
/**
* Thread pool notify request.
*
* @author chen.ma
* @date 2022/2/24 19:06
*/
@Data
@AllArgsConstructor
public class ThreadPoolNotifyRequest {
/**
* groupKeys
*/
private List<String> groupKeys;
}

@ -1,4 +1,4 @@
package cn.hippo4j.common.notify.request;
package cn.hippo4j.common.notify.request.base;
/**
* Notify request.

@ -1,203 +0,0 @@
package cn.hippo4j.starter.alarm.lark;
import cn.hippo4j.common.enums.EnableEnum;
import cn.hippo4j.common.model.InstanceInfo;
import cn.hippo4j.common.model.PoolParameterInfo;
import cn.hippo4j.common.toolkit.StringUtil;
import cn.hippo4j.starter.alarm.NotifyDTO;
import cn.hippo4j.common.notify.NotifyPlatformEnum;
import cn.hippo4j.starter.alarm.SendMessageHandler;
import cn.hippo4j.core.executor.DynamicThreadPoolExecutor;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
import cn.hippo4j.core.executor.support.QueueTypeEnum;
import cn.hippo4j.core.executor.support.RejectedTypeEnum;
import cn.hippo4j.core.executor.DynamicThreadPoolWrapper;
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;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import static cn.hippo4j.starter.alarm.lark.LarkAlarmConstants.*;
/**
* Send lark notification message.
*
* @author imyzt
* @date 2021/11/22 21:12
*/
@Slf4j
@AllArgsConstructor
public class LarkSendMessageHandler implements SendMessageHandler {
private final String active;
private final InstanceInfo instanceInfo;
private static volatile String larkJson;
@Override
public String getType() {
return NotifyPlatformEnum.LARK.name();
}
@Override
public void sendAlarmMessage(NotifyDTO notifyConfig, DynamicThreadPoolExecutor pool) {
larkAlarmSendMessage(notifyConfig, pool);
}
@Override
public void sendChangeMessage(NotifyDTO notifyConfig, PoolParameterInfo parameter) {
larkChangeSendMessage(notifyConfig, parameter);
}
@SneakyThrows
private void larkAlarmSendMessage(NotifyDTO notifyConfig, DynamicThreadPoolExecutor pool) {
String afterReceives = getReceives(notifyConfig);
BlockingQueue<Runnable> queue = pool.getQueue();
String larkAlarmJson = getLarkJson(ALARM_JSON_PATH);
String text = String.format(larkAlarmJson,
// 环境
active.toUpperCase(),
// 线程池ID
pool.getThreadPoolId(),
// 应用名称
instanceInfo.getAppName(),
// 实例信息
instanceInfo.getIdentify(),
// 报警类型
notifyConfig.getTypeEnum(),
// 核心线程数
pool.getCorePoolSize(),
// 最大线程数
pool.getMaximumPoolSize(),
// 当前线程数
pool.getPoolSize(),
// 活跃线程数
pool.getActiveCount(),
// 最大任务数
pool.getLargestPoolSize(),
// 线程池任务总量
pool.getCompletedTaskCount(),
// 队列类型名称
queue.getClass().getSimpleName(),
// 队列容量
queue.size() + queue.remainingCapacity(),
// 队列元素个数
queue.size(),
// 队列剩余个数
queue.remainingCapacity(),
// 拒绝策略名称
pool.getRejectedExecutionHandler().getClass().getSimpleName(),
// 拒绝策略次数
pool.getRejectCountNum(),
// 告警姓名
afterReceives,
// 当前时间
DateUtil.now(),
// 报警频率
notifyConfig.getInterval()
);
execute(notifyConfig, text);
}
@SneakyThrows
private void larkChangeSendMessage(NotifyDTO notifyConfig, PoolParameterInfo parameter) {
String threadPoolId = parameter.getTpId();
DynamicThreadPoolWrapper poolWrap = GlobalThreadPoolManage.getExecutorService(threadPoolId);
if (poolWrap == null) {
log.warn("Thread pool is empty when sending change notification, threadPoolId :: {}", threadPoolId);
return;
}
String afterReceives = getReceives(notifyConfig);
ThreadPoolExecutor customPool = poolWrap.getExecutor();
String larkNoticeJson = getLarkJson(NOTICE_JSON_PATH);
/**
* hesitant e.g.
*/
String text = String.format(larkNoticeJson,
// 环境
active.toUpperCase(),
// 线程池名称
threadPoolId,
// 应用名称
instanceInfo.getAppName(),
// 实例信息
instanceInfo.getIdentify(),
// 核心线程数
customPool.getCorePoolSize() + " ➲ " + parameter.getCoreSize(),
// 最大线程数
customPool.getMaximumPoolSize() + " ➲ " + parameter.getMaxSize(),
// 核心线程超时
customPool.allowsCoreThreadTimeOut() + " ➲ " + EnableEnum.getBool(parameter.getAllowCoreThreadTimeOut()),
// 线程存活时间
customPool.getKeepAliveTime(TimeUnit.SECONDS) + " ➲ " + parameter.getKeepAliveTime(),
// 阻塞队列
QueueTypeEnum.getBlockingQueueNameByType(parameter.getQueueType()),
// 阻塞队列容量
(customPool.getQueue().size() + customPool.getQueue().remainingCapacity()) + " ➲ " + parameter.getCapacity(),
// 拒绝策略
customPool.getRejectedExecutionHandler().getClass().getSimpleName(),
RejectedTypeEnum.getRejectedNameByType(parameter.getRejectedType()),
// 告警姓名
afterReceives,
// 当前时间
DateUtil.now()
);
execute(notifyConfig, text);
}
private String getLarkJson(String filePath) throws FileNotFoundException {
if (Objects.isNull(larkJson)) {
synchronized (LarkSendMessageHandler.class) {
if (Objects.isNull(larkJson)) {
larkJson = FileUtil.readString(ResourceUtils.getFile(filePath), StandardCharsets.UTF_8);
}
}
}
return larkJson;
}
private String getReceives(NotifyDTO notifyConfig) {
if (StringUtil.isBlank(notifyConfig.getReceives())) {
return "";
}
return Arrays.stream(notifyConfig.getReceives().split(","))
.map(receive -> StrUtil.startWith(receive, LARK_OPENID_PREFIX) ?
String.format(LARK_AT_FORMAT_OPENID, receive) : String.format(LARK_AT_FORMAT_USERNAME, receive))
.collect(Collectors.joining(" "));
}
private void execute(NotifyDTO notifyConfig, String text) {
String serverUrl = LARK_BOT_URL + notifyConfig.getSecretKey();
try {
HttpRequest.post(serverUrl).body(text).execute();
} catch (Exception ex) {
log.error("Lark failed to send message", ex);
}
}
}
Loading…
Cancel
Save