mirror of https://github.com/longtai-cn/hippo4j
抽象通知报警消息模块. (#102)
parent
9c0d660ef8
commit
8d788381a1
@ -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,17 +1,17 @@
|
|||||||
package cn.hippo4j.starter.alarm;
|
package cn.hippo4j.common.notify;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thread pool alarm.
|
* Thread pool notify alarm.
|
||||||
*
|
*
|
||||||
* @author chen.ma
|
* @author chen.ma
|
||||||
* @date 2021/8/15 13:13
|
* @date 2021/8/15 13:13
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ThreadPoolAlarm {
|
public class ThreadPoolNotifyAlarm {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isAlarm
|
* 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;
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package cn.hippo4j.common.notify.request;
|
package cn.hippo4j.common.notify.request.base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify request.
|
* 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…
Reference in new issue