diff --git a/common/src/main/java/org/dromara/dynamictp/common/constant/DingNotifyConst.java b/common/src/main/java/org/dromara/dynamictp/common/constant/DingNotifyConst.java
index a0df744fe..f91250b31 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/constant/DingNotifyConst.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/constant/DingNotifyConst.java
@@ -41,14 +41,28 @@ private DingNotifyConst() { }
public static final String DING_NOTICE_TITLE = "动态线程池通知";
- public static final String DING_ALARM_TEMPLATE =
+ public static final String DING_ALARM_TEMPLATE_PREFIX =
"【报警】 动态线程池运行告警 \n\n" +
"服务名称:%s \n\n " +
"实例信息:%s \n\n " +
"环境:%s \n\n " +
"线程池名称:%s \n\n " +
"报警项:%s \n\n " +
- "报警阈值 / 当前值:%s \n\n " +
+ "报警阈值 / 当前值:%s \n\n ";
+
+ public static final String DING_ALARM_COMMON_TEMPLATE =
+ "%s \n\n ";
+
+ public static final String DING_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n\n" +
+ "报警时间:%s \n\n" +
+ "接收人:@%s \n\n" +
+ "trace 信息:%s \n\n" +
+ "报警间隔:%ss \n\n" +
+ "扩展信息:%s \n\n";
+
+ public static final String DING_ALARM_TEMPLATE =
+ DING_ALARM_TEMPLATE_PREFIX +
"核心线程数:%d \n\n " +
"最大线程数:%d \n\n " +
"当前线程数:%d \n\n " +
@@ -65,12 +79,7 @@ private DingNotifyConst() { }
"总拒绝任务数量:%s \n\n " +
"总执行超时任务数量:%s \n\n " +
"总等待超时任务数量:%s \n\n " +
- "上次报警时间:%s \n\n" +
- "报警时间:%s \n\n" +
- "接收人:@%s \n\n" +
- "trace 信息:%s \n\n" +
- "报警间隔:%ss \n\n" +
- "扩展信息:%s \n\n";
+ DING_ALARM_TEMPLATE_SUFFIX;
public static final String DING_CHANGE_NOTICE_TEMPLATE =
"【通知】 动态线程池参数变更 \n\n " +
diff --git a/common/src/main/java/org/dromara/dynamictp/common/constant/DynamicTpConst.java b/common/src/main/java/org/dromara/dynamictp/common/constant/DynamicTpConst.java
index 579d9af4b..052b554ff 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/constant/DynamicTpConst.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/constant/DynamicTpConst.java
@@ -129,7 +129,15 @@ private DynamicTpConst() { }
public static final String FALSE_STR = "false";
/**
- * jre
+ * jre 21
*/
public static final String THREAD_PER_TASK_EXECUTOR = "java.util.concurrent.ThreadPerTaskExecutor";
+
+ public static final String PINNED_EVENT = "jdk.VirtualThreadPinned";
+
+ public static final String MAX_PINNED_TIME = "maxPinnedTime";
+
+ public static final String TOTAL_PINNED_TIME = "totalPinnedTime";
+
+ public static final String PINNED_DURATION = "pinnedDuration";
}
diff --git a/common/src/main/java/org/dromara/dynamictp/common/constant/LarkNotifyConst.java b/common/src/main/java/org/dromara/dynamictp/common/constant/LarkNotifyConst.java
index 4e9642bf6..d08bda69e 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/constant/LarkNotifyConst.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/constant/LarkNotifyConst.java
@@ -60,11 +60,20 @@ private LarkNotifyConst() { }
public static final String SIGN_PARAM_PREFIX = "{\"timestamp\": \"%s\",\"sign\": \"%s\",";
+ public static final String LARK_ALARM_JSON_STR_PREFIX =
+ "{\"msg_type\":\"interactive\",\"card\":{\"config\":{\"wide_screen_mode\":true},\"header\":{\"template\":\"red\",\"title\":{\"tag\":\"plain_text\",\"content\":\"【报警】 动态线程池告警\"}},\"elements\":[{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**服务名称:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**实例信息:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**环境:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**线程池名称:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"alarmType **报警项:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"alarmValue **报警阈值 / 当前值:**\\n%s\"}}]},{\"tag\":\"hr\"},";
+
+ public static final String LARK_ALARM_JSON_COMMON_STR =
+ "{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"%s\"}}]},";
+
+ public static final String LARK_ALARM_JSON_STR_SUFFIX =
+ "{\"tag\":\"hr\"},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**上次报警时间:**\\n %s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**报警时间:**\\n %s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**接收人:**\\n %s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**trace 信息:**\\n %s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**报警间隔:**\\n %ss\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**扩展信息:**\\n %s\"}}]}]}}";
+
/**
* 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\":{\"tag\":\"plain_text\",\"content\":\"【报警】 动态线程池告警\"}},\"elements\":[{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**服务名称:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**实例信息:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**环境:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**线程池名称:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"alarmType **报警项:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"alarmValue **报警阈值 / 当前值:**\\n%s\"}}]},{\"tag\":\"hr\"},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"corePoolSize **核心线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"maximumPoolSize **最大线程数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"poolSize **当前线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"activeCount **活跃线程数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**历史最大线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**任务总数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**执行完成任务数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**等待执行任务数:**\\n%s\"}}]},{\"tag\":\"hr\"},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueType **队列类型:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueCapacity **队列容量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueSize **队列任务数量:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueRemaining **队列剩余容量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"rejectType **拒绝策略:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"rejectCount **总拒绝任务数量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"runTimeoutCount **总执行超时任务数量:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueTimeoutCount **总等待超时任务数量:**\\n%s\"}}]},{\"tag\":\"hr\"},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**上次报警时间:**\\n %s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**报警时间:**\\n %s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**接收人:**\\n %s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**trace 信息:**\\n %s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**报警间隔:**\\n %ss\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**扩展信息:**\\n %s\"}}]}]}}";
+ LARK_ALARM_JSON_STR_PREFIX + "{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"corePoolSize **核心线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"maximumPoolSize **最大线程数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"poolSize **当前线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"activeCount **活跃线程数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**历史最大线程数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**任务总数:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**执行完成任务数:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"**等待执行任务数:**\\n%s\"}}]},{\"tag\":\"hr\"},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueType **队列类型:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueCapacity **队列容量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueSize **队列任务数量:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueRemaining **队列剩余容量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"rejectType **拒绝策略:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"rejectCount **总拒绝任务数量:**\\n%s\"}}]},{\"tag\":\"div\",\"fields\":[{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"runTimeoutCount **总执行超时任务数量:**\\n%s\"}},{\"is_short\":true,\"text\":{\"tag\":\"lark_md\",\"content\":\"queueTimeoutCount **总等待超时任务数量:**\\n%s\"}}]}," + LARK_ALARM_JSON_STR_SUFFIX;
/**
* lark notice json str
diff --git a/common/src/main/java/org/dromara/dynamictp/common/constant/WechatNotifyConst.java b/common/src/main/java/org/dromara/dynamictp/common/constant/WechatNotifyConst.java
index d5ca983a3..708e5afaa 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/constant/WechatNotifyConst.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/constant/WechatNotifyConst.java
@@ -37,17 +37,31 @@ private WechatNotifyConst() { }
public static final String COMMENT_COLOR = "comment";
- /**
- * receivers only supports userid, view more, see more.
- */
- public static final String WECHAT_ALARM_TEMPLATE =
+ public static final String WECHAT_ALARM_TEMPLATE_PREFIX =
"【报警】 动态线程池告警 \n" +
"> 服务名称:%s \n" +
"> 实例信息:%s \n" +
"> 环境:%s \n" +
"> 线程池名称:%s \n" +
"> 报警项:%s \n" +
- "> 报警阈值 / 当前值:%s \n" +
+ "> 报警阈值 / 当前值:%s \n";
+
+ public static final String WECHAT_ALARM_COMMON_TEMPLATE =
+ "> %s \n";
+
+ public static final String WECHAT_ALARM_TEMPLATE_SUFFIX =
+ "> 上次报警时间:%s \n" +
+ "> 报警时间:%s \n" +
+ "> 接收人:%s \n" +
+ "> trace 信息:%s \n" +
+ "> 报警间隔:%ss \n" +
+ "> 扩展信息:%s \n";
+
+ /**
+ * receivers only supports userid, view more, see more.
+ */
+ public static final String WECHAT_ALARM_TEMPLATE =
+ WECHAT_ALARM_TEMPLATE_PREFIX +
"> 核心线程数:%s \n" +
"> 最大线程数:%s \n" +
"> 当前线程数:%s \n" +
@@ -64,12 +78,7 @@ private WechatNotifyConst() { }
"> 总拒绝任务数量:%s \n" +
"> 总执行超时任务数量:%s \n" +
"> 总等待超时任务数量:%s \n" +
- "> 上次报警时间:%s \n" +
- "> 报警时间:%s \n" +
- "> 接收人:%s \n" +
- "> trace 信息:%s \n" +
- "> 报警间隔:%ss \n" +
- "> 扩展信息:%s \n";
+ WECHAT_ALARM_TEMPLATE_SUFFIX;
public static final String WECHAT_CHANGE_NOTICE_TEMPLATE =
"【通知】 动态线程池参数变更 \n" +
diff --git a/common/src/main/java/org/dromara/dynamictp/common/em/NotifyItemEnum.java b/common/src/main/java/org/dromara/dynamictp/common/em/NotifyItemEnum.java
index 10329bd15..a33aa03e5 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/em/NotifyItemEnum.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/em/NotifyItemEnum.java
@@ -59,7 +59,12 @@ public enum NotifyItemEnum {
/**
* Task queue wait timeout alarm.
*/
- QUEUE_TIMEOUT("queue_timeout", "");
+ QUEUE_TIMEOUT("queue_timeout", ""),
+
+ /**
+ * Pin timeout alarm.
+ */
+ PIN_TIMEOUT("pin_timeout", "");
private final String value;
diff --git a/common/src/main/java/org/dromara/dynamictp/common/entity/ExecutorStats.java b/common/src/main/java/org/dromara/dynamictp/common/entity/ExecutorStats.java
index ac86972e6..979e61bcd 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/entity/ExecutorStats.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/entity/ExecutorStats.java
@@ -20,6 +20,9 @@
import lombok.Data;
import lombok.EqualsAndHashCode;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
/**
* ExecutorStats related
@@ -74,7 +77,12 @@ public class ExecutorStats extends Metrics {
/**
* 是否为虚拟线程执行器
*/
- private boolean isVirtualExecutor;
+ private boolean isVirtualThreadExecutor;
+
+ /**
+ * 拓展字段
+ */
+ private final Map extMap = new ConcurrentHashMap<>(2);
/**
* 空闲时间 (ms)
diff --git a/common/src/main/java/org/dromara/dynamictp/common/entity/NotifyItem.java b/common/src/main/java/org/dromara/dynamictp/common/entity/NotifyItem.java
index 0b1e50fc4..39b0dbf9f 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/entity/NotifyItem.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/entity/NotifyItem.java
@@ -82,7 +82,7 @@ public static List mergeAllNotifyItems(List source) {
val defaultItems = getAllNotifyItems().stream()
.filter(t -> !StringUtil.containsIgnoreCase(t.getType(), configuredTypes))
.collect(Collectors.toList());
- List notifyItems = new ArrayList<>(6);
+ List notifyItems = new ArrayList<>(7);
notifyItems.addAll(defaultItems);
notifyItems.addAll(source);
return notifyItems;
@@ -102,11 +102,16 @@ public static List getAllNotifyItems() {
queueTimeoutNotify.setType(NotifyItemEnum.QUEUE_TIMEOUT.getValue());
queueTimeoutNotify.setThreshold(10);
- List notifyItems = new ArrayList<>(6);
+ NotifyItem pinTimeoutNotify = new NotifyItem();
+ pinTimeoutNotify.setType(NotifyItemEnum.PIN_TIMEOUT.getValue());
+ pinTimeoutNotify.setThreshold(10);
+
+ List notifyItems = new ArrayList<>(7);
notifyItems.addAll(getSimpleNotifyItems());
notifyItems.add(rejectNotify);
notifyItems.add(runTimeoutNotify);
notifyItems.add(queueTimeoutNotify);
+ notifyItems.add(pinTimeoutNotify);
return notifyItems;
}
diff --git a/common/src/main/java/org/dromara/dynamictp/common/util/ExecutorUtil.java b/common/src/main/java/org/dromara/dynamictp/common/util/ExecutorUtil.java
index 5005638b8..951de5668 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/util/ExecutorUtil.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/util/ExecutorUtil.java
@@ -51,7 +51,7 @@ private static void tryPrintError(Runnable r, Throwable t) {
if (r instanceof FutureTask) {
try {
FutureTask> future = (FutureTask>) r;
- if (future.isDone()) {
+ if (future.isDone() && !future.isCancelled()) {
future.get();
}
} catch (InterruptedException e) {
diff --git a/common/src/main/java/org/dromara/dynamictp/common/util/StringUtil.java b/common/src/main/java/org/dromara/dynamictp/common/util/StringUtil.java
index 61743f647..c30419926 100644
--- a/common/src/main/java/org/dromara/dynamictp/common/util/StringUtil.java
+++ b/common/src/main/java/org/dromara/dynamictp/common/util/StringUtil.java
@@ -17,9 +17,12 @@
package org.dromara.dynamictp.common.util;
+import jdk.jfr.consumer.RecordedFrame;
+import jdk.jfr.consumer.RecordedStackTrace;
import org.apache.commons.collections4.CollectionUtils;
import java.util.Collection;
+import java.util.stream.Collectors;
/**
* StringUtil related
@@ -64,4 +67,22 @@ public static boolean containsIgnoreCase(CharSequence str, CharSequence testStr)
}
return str.toString().toLowerCase().contains(testStr.toString().toLowerCase());
}
+
+ public static String formatJfrStackTrace(RecordedStackTrace stackTrace, int maxDepth) {
+ if (stackTrace == null) {
+ return "\t";
+ }
+ String formatted = "\t" + stackTrace.getFrames().stream()
+ .limit(maxDepth)
+ .map(StringUtil::formatStackTraceFrame)
+ .collect(Collectors.joining("\n\t"));
+ if (maxDepth < stackTrace.getFrames().size()) {
+ return formatted + "\n\t(...)";
+ }
+ return formatted;
+ }
+
+ private static String formatStackTraceFrame(RecordedFrame frame) {
+ return frame.getMethod().getType().getName() + "#" + frame.getMethod().getName() + ": " + frame.getLineNumber();
+ }
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/DtpRegistry.java b/core/src/main/java/org/dromara/dynamictp/core/DtpRegistry.java
index 392e515ec..cba36ad46 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/DtpRegistry.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/DtpRegistry.java
@@ -44,6 +44,7 @@
import org.dromara.dynamictp.core.reject.RejectHandlerGetter;
import org.dromara.dynamictp.core.support.adapter.ExecutorAdapter;
import org.dromara.dynamictp.core.support.ExecutorWrapper;
+import org.dromara.dynamictp.core.support.proxy.VirtualThreadExecutorProxy;
import org.dromara.dynamictp.core.support.task.wrapper.TaskWrapper;
import org.dromara.dynamictp.core.support.task.wrapper.TaskWrappers;
@@ -220,6 +221,10 @@ private static void refresh(ExecutorWrapper executorWrapper, DtpExecutorProps pr
private static void doRefresh(ExecutorWrapper executorWrapper, DtpExecutorProps props) {
ExecutorAdapter> executor = executorWrapper.getExecutor();
+ if (executorWrapper.isVirtualThreadExecutor()) {
+ doRefreshCommon(executorWrapper, props);
+ return;
+ }
doRefreshPoolSize(executor, props);
if (!Objects.equals(executor.getKeepAliveTime(props.getUnit()), props.getKeepAliveTime())) {
executor.setKeepAliveTime(props.getKeepAliveTime(), props.getUnit());
@@ -300,9 +305,13 @@ private static void doRefreshDtp(ExecutorWrapper executorWrapper, DtpExecutorPro
}
private static void updateWrapper(ExecutorWrapper executorWrapper, DtpExecutorProps props) {
- if (executorWrapper.isDtpExecutor()) {
+ if (executorWrapper.isDtpExecutor() || executorWrapper.isVirtualThreadExecutor()) {
executorWrapper.setThreadPoolAliasName(props.getThreadPoolAliasName());
- executorWrapper.setNotifyItems(((DtpExecutor) executorWrapper.getExecutor()).getNotifyItems());
+ if (executorWrapper.isDtpExecutor()) {
+ executorWrapper.setNotifyItems(((DtpExecutor) executorWrapper.getExecutor()).getNotifyItems());
+ } else {
+ executorWrapper.setNotifyItems(((VirtualThreadExecutorProxy) executorWrapper.getExecutor().getOriginal()).getNotifyItems());
+ }
executorWrapper.setPlatformIds(props.getPlatformIds());
executorWrapper.setNotifyEnabled(props.isNotifyEnabled());
}
@@ -339,7 +348,6 @@ private static void doRefreshPoolSize(ExecutorAdapter> executor, DtpExecutorPr
}
private static void updateQueueProps(ExecutorAdapter> executor, DtpExecutorProps props) {
-
val blockingQueue = executor.getQueue();
if (blockingQueue instanceof MemorySafeLinkedBlockingQueue) {
((MemorySafeLinkedBlockingQueue) blockingQueue).setMaxFreeMemory(props.getMaxFreeMemory() * M_1);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskRejectAware.java b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskRejectAware.java
index ffb0af7b0..e925f5916 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskRejectAware.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskRejectAware.java
@@ -21,7 +21,7 @@
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.core.notifier.manager.AlarmManager;
import org.dromara.dynamictp.core.support.adapter.ExecutorAdapter;
-import org.dromara.dynamictp.core.support.ThreadPoolStatProvider;
+import org.dromara.dynamictp.core.support.ExecutorStatProvider;
import org.slf4j.MDC;
import java.util.Objects;
@@ -51,7 +51,7 @@ public String getName() {
@Override
public void beforeReject(Runnable runnable, Executor executor) {
- ThreadPoolStatProvider statProvider = statProviders.get(executor);
+ ExecutorStatProvider statProvider = statProviders.get(executor);
if (Objects.isNull(statProvider)) {
return;
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskStatAware.java b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskStatAware.java
index 3c726492d..e0ec2c820 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskStatAware.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskStatAware.java
@@ -19,7 +19,7 @@
import org.dromara.dynamictp.common.entity.TpExecutorProps;
import org.dromara.dynamictp.core.support.ExecutorWrapper;
-import org.dromara.dynamictp.core.support.ThreadPoolStatProvider;
+import org.dromara.dynamictp.core.support.ExecutorStatProvider;
import java.util.Map;
import java.util.Objects;
@@ -34,11 +34,11 @@
*/
public abstract class TaskStatAware implements ExecutorAware {
- protected final Map statProviders = new ConcurrentHashMap<>();
+ protected final Map statProviders = new ConcurrentHashMap<>();
@Override
public void register(ExecutorWrapper wrapper) {
- ThreadPoolStatProvider statProvider = wrapper.getThreadPoolStatProvider();
+ ExecutorStatProvider statProvider = wrapper.getExecutorStatProvider();
statProviders.put(wrapper.getExecutor(), statProvider);
statProviders.put(wrapper.getExecutor().getOriginal(), statProvider);
}
@@ -48,7 +48,7 @@ public void refresh(ExecutorWrapper wrapper, TpExecutorProps props) {
if (Objects.isNull(statProviders.get(wrapper.getExecutor()))) {
register(wrapper);
}
- ThreadPoolStatProvider statProvider = wrapper.getThreadPoolStatProvider();
+ ExecutorStatProvider statProvider = wrapper.getExecutorStatProvider();
refresh(props, statProvider);
}
@@ -58,5 +58,5 @@ public void remove(ExecutorWrapper wrapper) {
statProviders.remove(wrapper.getExecutor().getOriginal());
}
- protected void refresh(TpExecutorProps props, ThreadPoolStatProvider statProvider) { }
+ protected void refresh(TpExecutorProps props, ExecutorStatProvider statProvider) { }
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskTimeoutAware.java b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskTimeoutAware.java
index bce9260aa..b8b89384d 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/aware/TaskTimeoutAware.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/aware/TaskTimeoutAware.java
@@ -19,7 +19,7 @@
import lombok.extern.slf4j.Slf4j;
import org.dromara.dynamictp.common.entity.TpExecutorProps;
-import org.dromara.dynamictp.core.support.ThreadPoolStatProvider;
+import org.dromara.dynamictp.core.support.ExecutorStatProvider;
import java.util.Objects;
import java.util.Optional;
@@ -48,7 +48,7 @@ public String getName() {
}
@Override
- protected void refresh(TpExecutorProps props, ThreadPoolStatProvider statProvider) {
+ protected void refresh(TpExecutorProps props, ExecutorStatProvider statProvider) {
super.refresh(props, statProvider);
if (Objects.nonNull(props)) {
statProvider.setRunTimeout(props.getRunTimeout());
diff --git a/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java b/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java
index b5da89dab..474f28b18 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java
@@ -24,8 +24,9 @@
import org.dromara.dynamictp.core.monitor.PerformanceProvider;
import org.dromara.dynamictp.core.support.adapter.ExecutorAdapter;
import org.dromara.dynamictp.core.support.ExecutorWrapper;
-import org.dromara.dynamictp.core.support.ThreadPoolStatProvider;
+import org.dromara.dynamictp.core.support.ExecutorStatProvider;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
@@ -58,7 +59,7 @@ public static ExecutorStats toMetrics(ExecutorWrapper wrapper) {
if (executor == null) {
return null;
}
- ThreadPoolStatProvider provider = wrapper.getThreadPoolStatProvider();
+ ExecutorStatProvider provider = wrapper.getExecutorStatProvider();
PerformanceProvider performanceProvider = provider.getPerformanceProvider();
val performanceSnapshot = performanceProvider.getSnapshotAndReset();
ExecutorStats executorStats = convertCommon(executor);
@@ -68,7 +69,8 @@ public static ExecutorStats toMetrics(ExecutorWrapper wrapper) {
executorStats.setQueueTimeoutCount(provider.getQueueTimeoutCount());
executorStats.setRejectCount(provider.getRejectedTaskCount());
- executorStats.setVirtualExecutor(wrapper.isVirtualThreadExecutor());
+ executorStats.setVirtualThreadExecutor(wrapper.isVirtualThreadExecutor());
+ toVirtualThreadMetrics(executorStats);
executorStats.setDynamic(executor instanceof DtpExecutor);
executorStats.setTps(performanceSnapshot.getTps());
@@ -84,6 +86,15 @@ public static ExecutorStats toMetrics(ExecutorWrapper wrapper) {
return executorStats;
}
+ private static void toVirtualThreadMetrics(ExecutorStats executorStats) {
+ if (!executorStats.isVirtualThreadExecutor()) {
+ return;
+ }
+ Map vteStats = PerformanceProvider.getVteStat(executorStats.getExecutorName());
+ executorStats.getExtMap().put("maxPinnedTime", vteStats.getOrDefault("maxPinnedTime", 0d));
+ executorStats.getExtMap().put("totalPinnedTime", vteStats.getOrDefault("totalPinnedTime", 0d));
+ }
+
private static ExecutorStats convertCommon(ExecutorAdapter> executor) {
ExecutorStats executorStats = new ExecutorStats();
executorStats.setCorePoolSize(executor.getCorePoolSize());
diff --git a/core/src/main/java/org/dromara/dynamictp/core/handler/NotifierHandler.java b/core/src/main/java/org/dromara/dynamictp/core/handler/NotifierHandler.java
index 0a92d8254..110a68cdd 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/handler/NotifierHandler.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/handler/NotifierHandler.java
@@ -29,9 +29,11 @@
import org.dromara.dynamictp.common.notifier.DingNotifier;
import org.dromara.dynamictp.common.notifier.LarkNotifier;
import org.dromara.dynamictp.common.notifier.WechatNotifier;
+import org.dromara.dynamictp.core.notifier.context.BaseNotifyCtx;
import org.dromara.dynamictp.core.notifier.context.DtpNotifyCtxHolder;
import org.dromara.dynamictp.core.notifier.manager.NotifyHelper;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -72,12 +74,22 @@ public void sendNotice(TpMainFields oldFields, List diffs) {
}
public void sendAlarm(NotifyItemEnum notifyItemEnum) {
- NotifyItem notifyItem = DtpNotifyCtxHolder.get().getNotifyItem();
+ BaseNotifyCtx notifyCtx = DtpNotifyCtxHolder.get();
+ if (notifyCtx.isToLog()) {
+ log.warn("DynamicTp alarm, executor [" + notifyCtx.getExecutorWrapper().getThreadPoolName() + "]: \n" + Arrays.toString(notifyCtx.getContent()));
+ }
+ NotifyItem notifyItem = notifyCtx.getNotifyItem();
for (String platformId : notifyItem.getPlatformIds()) {
NotifyHelper.getPlatform(platformId).ifPresent(p -> {
DtpNotifier notifier = NOTIFIERS.get(p.getPlatform().toLowerCase());
if (notifier != null) {
- notifier.sendAlarmMsg(p, notifyItemEnum);
+ if (notifyCtx.isCommonNotify()) {
+ notifier.sendCommonAlarmMsg(p, notifyItemEnum, notifyCtx.getContent());
+ } else {
+ if (!notifyCtx.getExecutorWrapper().isVirtualThreadExecutor()) {
+ notifier.sendAlarmMsg(p, notifyItemEnum);
+ }
+ }
}
});
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/monitor/DtpMonitor.java b/core/src/main/java/org/dromara/dynamictp/core/monitor/DtpMonitor.java
index b4ea4f55d..9a9aadfd5 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/monitor/DtpMonitor.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/monitor/DtpMonitor.java
@@ -102,9 +102,9 @@ private void collectMetrics(Set executorNames) {
}
- private void doCollect(ExecutorStats threadPoolStats) {
+ private void doCollect(ExecutorStats executorStats) {
try {
- CollectorHandler.getInstance().collect(threadPoolStats, dtpProperties.getCollectorTypes());
+ CollectorHandler.getInstance().collect(executorStats, dtpProperties.getCollectorTypes());
} catch (Exception e) {
log.error("DynamicTp monitor, metrics collect error.", e);
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/monitor/PerformanceProvider.java b/core/src/main/java/org/dromara/dynamictp/core/monitor/PerformanceProvider.java
index 1fcc06e0f..3e89790ab 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/monitor/PerformanceProvider.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/monitor/PerformanceProvider.java
@@ -17,21 +17,42 @@
package org.dromara.dynamictp.core.monitor;
+import com.google.common.collect.ImmutableList;
+import io.micrometer.core.instrument.Timer;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordingStream;
import lombok.Getter;
import lombok.val;
+import org.dromara.dynamictp.common.em.NotifyItemEnum;
+import org.dromara.dynamictp.core.DtpRegistry;
import org.dromara.dynamictp.core.metric.MMAPCounter;
+import org.dromara.dynamictp.core.notifier.manager.AlarmManager;
+import org.dromara.dynamictp.core.support.ExecutorWrapper;
+import org.dromara.dynamictp.core.support.proxy.VirtualThreadExecutorProxy;
+import java.io.Closeable;
import java.math.BigDecimal;
import java.math.RoundingMode;
+import java.time.Duration;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
+import static org.dromara.dynamictp.common.constant.DynamicTpConst.MAX_PINNED_TIME;
+import static org.dromara.dynamictp.common.constant.DynamicTpConst.PINNED_EVENT;
+import static org.dromara.dynamictp.common.constant.DynamicTpConst.TOTAL_PINNED_TIME;
+import static org.dromara.dynamictp.common.util.StringUtil.formatJfrStackTrace;
+
+
/**
* PerformanceProvider related
*
* @author kyao
* @since 1.1.5
*/
-public class PerformanceProvider {
+public class PerformanceProvider implements Closeable {
/**
* last refresh timestamp
@@ -40,6 +61,13 @@ public class PerformanceProvider {
private final MMAPCounter mmapCounter = new MMAPCounter();
+ private static final Map> VTE_STATS_CACHE = new ConcurrentHashMap<>();
+
+ private static final int DEFAULT_STACK_TRACE_MAX_DEPTH = 15;
+
+ private static final Timer TIMER = new SimpleMeterRegistry().timer(PINNED_EVENT);
+ private static final RecordingStream RECORDING_STREAM = createRecordingStream();
+
public void completeTask(long rt) {
mmapCounter.add(rt);
}
@@ -57,6 +85,61 @@ private void reset(long currentMillis) {
lastRefreshMillis.compareAndSet(lastRefreshMillis.get(), currentMillis);
}
+ public static RecordingStream createRecordingStream() {
+ RecordingStream recordingStream = new RecordingStream();
+ recordingStream.enable(PINNED_EVENT).withStackTrace();
+ recordingStream.setMaxAge(Duration.ofSeconds(5));
+ recordingStream.startAsync();
+ recordingStream.onEvent(PINNED_EVENT, PerformanceProvider::handlePinnedEvent);
+ return recordingStream;
+ }
+
+ @Override
+ public void close() {
+ RECORDING_STREAM.close();
+ }
+
+ /**
+ * When an event is pinned, the data is saved to the cache
+ */
+ static void handlePinnedEvent(RecordedEvent event) {
+ String executorName = event.getThread() != null ? event.getThread().getJavaName() : "";
+ if (executorName.isEmpty()) {
+ return;
+ }
+ Duration duration = event.getDuration();
+ String stackTrace = formatJfrStackTrace(event.getStackTrace(), DEFAULT_STACK_TRACE_MAX_DEPTH);
+ TIMER.record(duration);
+
+ ConcurrentHashMap vtExecutorStat = new ConcurrentHashMap<>(3);
+ double maxPinnedTime = TIMER.max(TimeUnit.MILLISECONDS);
+ double totalPinnedTime = TIMER.totalTime(TimeUnit.MILLISECONDS);
+ long durationPinnedTime = duration.toMillis();
+ vtExecutorStat.put(MAX_PINNED_TIME, maxPinnedTime);
+ vtExecutorStat.put(TOTAL_PINNED_TIME, totalPinnedTime);
+
+ String[] pinContent = populatePinContent(maxPinnedTime, totalPinnedTime, durationPinnedTime, stackTrace);
+ ExecutorWrapper executorWrapper = DtpRegistry.getExecutorWrapper(executorName);
+ ((VirtualThreadExecutorProxy) executorWrapper.getExecutor().getOriginal()).setCurPinDuration(duration.toSeconds());
+ AlarmManager.tryCommonAlarmAsync(executorWrapper, ImmutableList.of(NotifyItemEnum.PIN_TIMEOUT), true, pinContent);
+
+ VTE_STATS_CACHE.put(executorName, vtExecutorStat);
+ }
+
+ private static String[] populatePinContent(double maxPinnedTime, double totalPinnedTime, long durationPinnedTime, String stackTrace) {
+ return new String[] {
+ "maxPinnedTime: " + maxPinnedTime + "ms",
+ "totalPinnedTime: " + totalPinnedTime + "ms",
+ "durationPinnedTime: " + durationPinnedTime + "ms",
+ "stackTrace: \n" + stackTrace
+ };
+ }
+
+ public static Map getVteStat(String executorName) {
+ VTE_STATS_CACHE.putIfAbsent(executorName, new ConcurrentHashMap<>(3));
+ return VTE_STATS_CACHE.get(executorName);
+ }
+
@Getter
public static class PerformanceSnapshot {
diff --git a/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/MicroMeterCollector.java b/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/MicroMeterCollector.java
index bd40efe99..923a3b03c 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/MicroMeterCollector.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/MicroMeterCollector.java
@@ -52,7 +52,7 @@ public class MicroMeterCollector extends AbstractCollector {
public static final String APP_NAME_TAG = "app.name";
- private static final Map GAUGE_CACHE = new ConcurrentHashMap<>();
+ public static final Map GAUGE_CACHE = new ConcurrentHashMap<>();
@Override
public void collect(ExecutorStats executorStats) {
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/AbstractDtpNotifier.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/AbstractDtpNotifier.java
index 9133673fa..1ff80b153 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/AbstractDtpNotifier.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/AbstractDtpNotifier.java
@@ -40,6 +40,7 @@
import org.slf4j.MDC;
import java.lang.reflect.Field;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -88,12 +89,22 @@ public void sendAlarmMsg(NotifyPlatform notifyPlatform, NotifyItemEnum notifyIte
notifier.send(newTargetPlatform(notifyPlatform), content);
}
+ @Override
+ public void sendCommonAlarmMsg(NotifyPlatform notifyPlatform, NotifyItemEnum notifyItemEnum, String... content) {
+ String formattedContent = buildCommonAlarmContent(notifyPlatform, notifyItemEnum, content);
+ if (StringUtils.isBlank(formattedContent) || StringUtils.isEmpty(Arrays.toString(content))) {
+ log.debug("Alarm content is empty, ignore send alarm message.");
+ return;
+ }
+ notifier.send(newTargetPlatform(notifyPlatform), formattedContent);
+ }
+
protected String buildAlarmContent(NotifyPlatform platform, NotifyItemEnum notifyItemEnum) {
AlarmCtx context = (AlarmCtx) DtpNotifyCtxHolder.get();
ExecutorWrapper executorWrapper = context.getExecutorWrapper();
val executor = executorWrapper.getExecutor();
NotifyItem notifyItem = context.getNotifyItem();
- val statProvider = executorWrapper.getThreadPoolStatProvider();
+ val statProvider = executorWrapper.getExecutorStatProvider();
val alarmValue = notifyItem.getThreshold() + notifyItemEnum.getUnit() + " / "
+ AlarmCounter.calcCurrentValue(executorWrapper, notifyItemEnum) + notifyItemEnum.getUnit();
String content = String.format(
@@ -130,6 +141,39 @@ protected String buildAlarmContent(NotifyPlatform platform, NotifyItemEnum notif
return highlightAlarmContent(content, notifyItemEnum);
}
+ private String buildCommonAlarmContent(NotifyPlatform notifyPlatform, NotifyItemEnum notifyItemEnum, String... content) {
+ AlarmCtx context = (AlarmCtx) DtpNotifyCtxHolder.get();
+ ExecutorWrapper executorWrapper = context.getExecutorWrapper();
+ NotifyItem notifyItem = context.getNotifyItem();
+ val alarmValue = notifyItem.getThreshold() + notifyItemEnum.getUnit() + " / "
+ + AlarmCounter.calcCurrentValue(executorWrapper, notifyItemEnum) + notifyItemEnum.getUnit();
+ String[] template = getCommonAlarmTemplate(content.length);
+ String formatContentPrefix = String.format(
+ template[0],
+ CommonUtil.getInstance().getServiceName(),
+ CommonUtil.getInstance().getIp() + ":" + CommonUtil.getInstance().getPort(),
+ CommonUtil.getInstance().getEnv(),
+ populatePoolName(executorWrapper),
+ populateAlarmItem(notifyItemEnum, executorWrapper),
+ alarmValue
+ );
+ String formatCommonContent = String.format(
+ template[1],
+ content
+ );
+ String formatContentSuffix = String.format(
+ template[2],
+ Optional.ofNullable(context.getAlarmInfo()).map(AlarmInfo::getLastAlarmTime).orElse(UNKNOWN),
+ DateUtil.now(),
+ getReceives(notifyItem, notifyPlatform),
+ getTraceInfo(),
+ notifyItem.getInterval(),
+ getExtInfo()
+ );
+ String formatContent = formatContentPrefix + formatCommonContent + formatContentSuffix;
+ return highlightAlarmContent(formatContent, notifyItemEnum);
+ }
+
protected String buildNoticeContent(NotifyPlatform platform, TpMainFields oldFields, List diffs) {
BaseNotifyCtx context = DtpNotifyCtxHolder.get();
ExecutorWrapper executorWrapper = context.getExecutorWrapper();
@@ -202,9 +246,9 @@ protected String populatePoolName(ExecutorWrapper executorWrapper) {
protected String populateAlarmItem(NotifyItemEnum notifyType, ExecutorWrapper executorWrapper) {
String suffix = StringUtils.EMPTY;
if (notifyType == NotifyItemEnum.RUN_TIMEOUT) {
- suffix = " (" + executorWrapper.getThreadPoolStatProvider().getRunTimeout() + "ms)";
+ suffix = " (" + executorWrapper.getExecutorStatProvider().getRunTimeout() + "ms)";
} else if (notifyType == NotifyItemEnum.QUEUE_TIMEOUT) {
- suffix = " (" + executorWrapper.getThreadPoolStatProvider().getQueueTimeout() + "ms)";
+ suffix = " (" + executorWrapper.getExecutorStatProvider().getQueueTimeout() + "ms)";
}
return notifyType.getValue() + suffix;
}
@@ -254,6 +298,14 @@ private String highlightAlarmContent(String content, NotifyItemEnum notifyItemEn
*/
protected abstract String getAlarmTemplate();
+ /**
+ * Implement by subclass, get common alarm template.
+ *
+ * @param num number of args
+ * @return alarm template
+ */
+ protected abstract String[] getCommonAlarmTemplate(int num);
+
/**
* Implement by subclass, get content color config.
*
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpDingNotifier.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpDingNotifier.java
index 46a321b95..c6881fe22 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpDingNotifier.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpDingNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return DingNotifyConst.DING_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{DingNotifyConst.DING_ALARM_TEMPLATE_PREFIX, DingNotifyConst.DING_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), DingNotifyConst.DING_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return new ImmutablePair<>(DingNotifyConst.WARNING_COLOR, DingNotifyConst.CONTENT_COLOR);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpLarkNotifier.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpLarkNotifier.java
index 2bac20543..ed2a25b78 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpLarkNotifier.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpLarkNotifier.java
@@ -61,6 +61,11 @@ protected String getAlarmTemplate() {
return LarkNotifyConst.LARK_ALARM_JSON_STR;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{LarkNotifyConst.LARK_ALARM_JSON_STR_PREFIX, LarkNotifyConst.LARK_ALARM_JSON_COMMON_STR.repeat(Math.max(0, num)), LarkNotifyConst.LARK_ALARM_JSON_STR_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return new ImmutablePair<>(LarkNotifyConst.WARNING_COLOR, LarkNotifyConst.COMMENT_COLOR);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpNotifier.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpNotifier.java
index f1e804e9e..f79b64254 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpNotifier.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpNotifier.java
@@ -54,4 +54,13 @@ public interface DtpNotifier {
* @param notifyItemEnum notify item enum
*/
void sendAlarmMsg(NotifyPlatform notifyPlatform, NotifyItemEnum notifyItemEnum);
+
+ /**
+ * Send common alarm message.
+ *
+ * @param notifyPlatform notify platform
+ * @param notifyItemEnum notify item enum
+ * @param content common content
+ */
+ void sendCommonAlarmMsg(NotifyPlatform notifyPlatform, NotifyItemEnum notifyItemEnum, String... content);
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpWechatNotifier.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpWechatNotifier.java
index 1faa1ceaa..c738ce3a0 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpWechatNotifier.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/DtpWechatNotifier.java
@@ -56,6 +56,11 @@ protected String getAlarmTemplate() {
return WechatNotifyConst.WECHAT_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{WechatNotifyConst.WECHAT_ALARM_TEMPLATE_PREFIX, WechatNotifyConst.WECHAT_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), WechatNotifyConst.WECHAT_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return new ImmutablePair<>(WechatNotifyConst.WARNING_COLOR, WechatNotifyConst.COMMENT_COLOR);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/alarm/AlarmCounter.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/alarm/AlarmCounter.java
index b236431f2..3a46e07c0 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/alarm/AlarmCounter.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/alarm/AlarmCounter.java
@@ -77,6 +77,9 @@ public static void incAlarmCounter(String threadPoolName, String notifyItemType)
public static int calcCurrentValue(ExecutorWrapper wrapper, NotifyItemEnum itemEnum) {
val executor = wrapper.getExecutor();
+ if (wrapper.isVirtualThreadExecutor()) {
+ return Integer.MAX_VALUE;
+ }
switch (itemEnum) {
case CAPACITY:
return (int) (NumberUtil.div(executor.getQueueSize(), executor.getQueueCapacity(), 2) * 100);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/context/AlarmCtx.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/context/AlarmCtx.java
index 5e43ef88e..2d067a184 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/context/AlarmCtx.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/context/AlarmCtx.java
@@ -36,6 +36,13 @@ public class AlarmCtx extends BaseNotifyCtx {
private AlarmInfo alarmInfo;
public AlarmCtx(ExecutorWrapper wrapper, NotifyItem notifyItem) {
- super(wrapper, notifyItem);
+ this(wrapper, notifyItem, false, "");
+ }
+
+ public AlarmCtx(ExecutorWrapper wrapper, NotifyItem notifyItem, boolean isCommonNotify, String... content) {
+ this(wrapper, notifyItem, isCommonNotify, false, content);
+ }
+ public AlarmCtx(ExecutorWrapper wrapper, NotifyItem notifyItem, boolean isCommonNotify, boolean isToLog, String... content) {
+ super(wrapper, notifyItem, isCommonNotify, isToLog, content);
}
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/context/BaseNotifyCtx.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/context/BaseNotifyCtx.java
index 432d42c1d..ef22a37bc 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/context/BaseNotifyCtx.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/context/BaseNotifyCtx.java
@@ -35,11 +35,24 @@ public class BaseNotifyCtx {
private NotifyItem notifyItem;
+ private boolean isCommonNotify;
+
+ private boolean isToLog;
+
+ private String[] content;
+
public BaseNotifyCtx() { }
public BaseNotifyCtx(ExecutorWrapper wrapper, NotifyItem notifyItem) {
+ this(wrapper, notifyItem, false, false, "");
+ }
+
+ public BaseNotifyCtx(ExecutorWrapper wrapper, NotifyItem notifyItem, boolean isCommonNotify, boolean isToLog, String... content) {
this.executorWrapper = wrapper.capture();
this.notifyItem = notifyItem;
+ this.isCommonNotify = isCommonNotify;
+ this.isToLog = isToLog;
+ this.content = content;
}
public NotifyItemEnum getNotifyItemEnum() {
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/AlarmManager.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/AlarmManager.java
index 378986196..bb02e787d 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/AlarmManager.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/AlarmManager.java
@@ -32,6 +32,8 @@
import org.dromara.dynamictp.core.notifier.context.BaseNotifyCtx;
import org.dromara.dynamictp.core.support.ExecutorWrapper;
import org.dromara.dynamictp.core.support.ThreadPoolBuilder;
+import org.dromara.dynamictp.core.support.adapter.VirtualThreadExecutorAdapter;
+import org.dromara.dynamictp.core.support.proxy.VirtualThreadExecutorProxy;
import org.dromara.dynamictp.core.support.task.runnable.DtpRunnable;
import org.dromara.dynamictp.core.support.task.wrapper.TaskWrappers;
import org.slf4j.MDC;
@@ -91,10 +93,18 @@ public static void tryAlarmAsync(ExecutorWrapper executorWrapper, List notifyTypes.forEach(x -> doTryAlarm(executorWrapper, x)));
}
+ public static void tryCommonAlarmAsync(ExecutorWrapper executorWrapper, List notifyTypes, boolean isToLog, String... content) {
+ ALARM_EXECUTOR.execute(() -> notifyTypes.forEach(x -> doTryAlarm(executorWrapper, x, true, isToLog, content)));
+ }
+
public static void doTryAlarm(ExecutorWrapper executorWrapper, NotifyItemEnum notifyType) {
+ doTryAlarm(executorWrapper, notifyType, false, false, "");
+ }
+
+ public static void doTryAlarm(ExecutorWrapper executorWrapper, NotifyItemEnum notifyType, boolean isCommonNotify, boolean isToLog, String... content) {
AlarmCounter.incAlarmCounter(executorWrapper.getThreadPoolName(), notifyType.getValue());
NotifyHelper.getNotifyItem(executorWrapper, notifyType).ifPresent(notifyItem -> {
- val alarmCtx = new AlarmCtx(executorWrapper, notifyItem);
+ val alarmCtx = new AlarmCtx(executorWrapper, notifyItem, isCommonNotify, isToLog, content);
ALARM_INVOKER_CHAIN.proceed(alarmCtx);
});
}
@@ -106,6 +116,8 @@ public static boolean checkThreshold(ExecutorWrapper executor, NotifyItemEnum no
return checkCapacity(executor, notifyItem);
case LIVENESS:
return checkLiveness(executor, notifyItem);
+ case PIN_TIMEOUT:
+ return checkPinTimeout(executor, notifyItem);
case REJECT:
case RUN_TIMEOUT:
case QUEUE_TIMEOUT:
@@ -116,11 +128,15 @@ public static boolean checkThreshold(ExecutorWrapper executor, NotifyItemEnum no
}
}
+
public static void destroy() {
ALARM_EXECUTOR.shutdownNow();
}
private static boolean checkLiveness(ExecutorWrapper executorWrapper, NotifyItem notifyItem) {
+ if (executorWrapper.isVirtualThreadExecutor()) {
+ return true;
+ }
val executor = executorWrapper.getExecutor();
int maximumPoolSize = executor.getMaximumPoolSize();
double div = NumberUtil.div(executor.getActiveCount(), maximumPoolSize, 2) * 100;
@@ -128,7 +144,9 @@ private static boolean checkLiveness(ExecutorWrapper executorWrapper, NotifyItem
}
private static boolean checkCapacity(ExecutorWrapper executorWrapper, NotifyItem notifyItem) {
-
+ if (executorWrapper.isVirtualThreadExecutor()) {
+ return true;
+ }
val executor = executorWrapper.getExecutor();
if (executor.getQueueSize() <= 0) {
return false;
@@ -137,6 +155,11 @@ private static boolean checkCapacity(ExecutorWrapper executorWrapper, NotifyItem
return div >= notifyItem.getThreshold();
}
+ private static boolean checkPinTimeout(ExecutorWrapper executorWrapper, NotifyItem notifyItem) {
+ return ((VirtualThreadExecutorProxy) ((VirtualThreadExecutorAdapter) executorWrapper.getExecutor().getOriginal())
+ .getOriginal()).getCurPinDuration() >= notifyItem.getThreshold();
+ }
+
private static boolean checkWithAlarmInfo(ExecutorWrapper executorWrapper, NotifyItem notifyItem) {
AlarmInfo alarmInfo = AlarmCounter.getAlarmInfo(executorWrapper.getThreadPoolName(), notifyItem.getType());
return alarmInfo.getCount() >= notifyItem.getThreshold();
diff --git a/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/NotifyHelper.java b/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/NotifyHelper.java
index cb923291f..2483d7e34 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/NotifyHelper.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/notifier/manager/NotifyHelper.java
@@ -34,6 +34,7 @@
import org.dromara.dynamictp.common.manager.ContextManagerHelper;
import org.dromara.dynamictp.core.support.ExecutorWrapper;
+import org.dromara.dynamictp.core.support.proxy.VirtualThreadExecutorProxy;
import java.util.Collection;
import java.util.Collections;
@@ -44,11 +45,7 @@
import java.util.Set;
import java.util.stream.Collectors;
-import static org.dromara.dynamictp.common.em.NotifyItemEnum.CAPACITY;
-import static org.dromara.dynamictp.common.em.NotifyItemEnum.LIVENESS;
-import static org.dromara.dynamictp.common.em.NotifyItemEnum.QUEUE_TIMEOUT;
-import static org.dromara.dynamictp.common.em.NotifyItemEnum.REJECT;
-import static org.dromara.dynamictp.common.em.NotifyItemEnum.RUN_TIMEOUT;
+import static org.dromara.dynamictp.common.em.NotifyItemEnum.*;
import static org.dromara.dynamictp.common.entity.NotifyItem.mergeAllNotifyItems;
/**
@@ -74,6 +71,8 @@ public class NotifyHelper {
private static final Set QUEUE_TIMEOUT_ALARM_KEYS = Sets.newHashSet("queueTimeoutCount");
+ private static final Set PIN_TIMEOUT_ALARM_KEYS = Sets.newHashSet("pinTimeoutCount");
+
private static final Set ALL_ALARM_KEYS;
private static final Map> ALARM_KEYS = Maps.newHashMap();
@@ -84,6 +83,7 @@ public class NotifyHelper {
ALARM_KEYS.put(REJECT.name(), REJECT_ALARM_KEYS);
ALARM_KEYS.put(RUN_TIMEOUT.name(), RUN_TIMEOUT_ALARM_KEYS);
ALARM_KEYS.put(QUEUE_TIMEOUT.name(), QUEUE_TIMEOUT_ALARM_KEYS);
+ ALARM_KEYS.put(PIN_TIMEOUT.name(), PIN_TIMEOUT_ALARM_KEYS);
ALL_ALARM_KEYS = ALARM_KEYS.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
ALL_ALARM_KEYS.addAll(COMMON_ALARM_KEYS);
@@ -161,6 +161,23 @@ public static void initNotify(DtpExecutor executor) {
AlarmManager.initAlarm(executor.getThreadPoolName(), executor.getNotifyItems());
}
+ public static void initNotify(VirtualThreadExecutorProxy executor) {
+ val dtpProperties = ContextManagerHelper.getBean(DtpProperties.class);
+ val platforms = dtpProperties.getPlatforms();
+ if (CollectionUtils.isEmpty(platforms)) {
+ executor.setNotifyItems(Lists.newArrayList());
+ executor.setPlatformIds(Lists.newArrayList());
+ log.warn("DynamicTp notify, no notify platforms configured for [{}]", executor.getThreadPoolName());
+ return;
+ }
+ if (CollectionUtils.isEmpty(executor.getNotifyItems())) {
+ log.warn("DynamicTp notify, no notify items configured for [{}]", executor.getThreadPoolName());
+ return;
+ }
+ fillPlatforms(executor.getPlatformIds(), platforms, executor.getNotifyItems());
+ AlarmManager.initAlarm(executor.getThreadPoolName(), executor.getNotifyItems());
+ }
+
public static void updateNotifyInfo(ExecutorWrapper executorWrapper,
TpExecutorProps props,
List platforms) {
diff --git a/core/src/main/java/org/dromara/dynamictp/core/support/ThreadPoolStatProvider.java b/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorStatProvider.java
similarity index 96%
rename from core/src/main/java/org/dromara/dynamictp/core/support/ThreadPoolStatProvider.java
rename to core/src/main/java/org/dromara/dynamictp/core/support/ExecutorStatProvider.java
index a4488b92d..981194133 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/support/ThreadPoolStatProvider.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorStatProvider.java
@@ -39,7 +39,7 @@
* @author hanli
* @since 1.1.4
*/
-public class ThreadPoolStatProvider {
+public class ExecutorStatProvider {
private final ExecutorWrapper executorWrapper;
@@ -93,12 +93,12 @@ public class ThreadPoolStatProvider {
*/
private final PerformanceProvider performanceProvider = new PerformanceProvider();
- private ThreadPoolStatProvider(ExecutorWrapper executorWrapper) {
+ private ExecutorStatProvider(ExecutorWrapper executorWrapper) {
this.executorWrapper = executorWrapper;
}
- public static ThreadPoolStatProvider of(ExecutorWrapper executorWrapper) {
- val provider = new ThreadPoolStatProvider(executorWrapper);
+ public static ExecutorStatProvider of(ExecutorWrapper executorWrapper) {
+ val provider = new ExecutorStatProvider(executorWrapper);
if (executorWrapper.isDtpExecutor()) {
val dtpExecutor = (DtpExecutor) executorWrapper.getExecutor();
provider.setRunTimeout(dtpExecutor.getRunTimeout());
diff --git a/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorWrapper.java b/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorWrapper.java
index 8e6cc5fc0..5ef7a9f60 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorWrapper.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/support/ExecutorWrapper.java
@@ -28,6 +28,7 @@
import org.dromara.dynamictp.core.notifier.capture.CapturedExecutor;
import org.dromara.dynamictp.core.notifier.manager.AlarmManager;
import org.dromara.dynamictp.core.reject.RejectHandlerGetter;
+import org.dromara.dynamictp.core.support.adapter.VirtualThreadExecutorAdapter;
import org.dromara.dynamictp.core.support.proxy.VirtualThreadExecutorProxy;
import org.dromara.dynamictp.core.support.adapter.ExecutorAdapter;
import org.dromara.dynamictp.core.support.adapter.ThreadPoolExecutorAdapter;
@@ -104,9 +105,9 @@ public class ExecutorWrapper {
protected int awaitTerminationSeconds = 0;
/**
- * Thread pool stat provider
+ * Executor stat provider
*/
- private ThreadPoolStatProvider threadPoolStatProvider;
+ private ExecutorStatProvider executorStatProvider;
private ExecutorWrapper() {
}
@@ -127,7 +128,7 @@ public ExecutorWrapper(DtpExecutor executor) {
this.rejectEnhanced = executor.isRejectEnhanced();
this.waitForTasksToCompleteOnShutdown = executor.isWaitForTasksToCompleteOnShutdown();
this.awaitTerminationSeconds = executor.getAwaitTerminationSeconds();
- this.threadPoolStatProvider = ThreadPoolStatProvider.of(this);
+ this.executorStatProvider = ExecutorStatProvider.of(this);
}
/**
@@ -140,16 +141,23 @@ public ExecutorWrapper(String threadPoolName, Executor executor) {
this.threadPoolName = threadPoolName;
if (executor instanceof ThreadPoolExecutor) {
this.executor = new ThreadPoolExecutorAdapter((ThreadPoolExecutor) executor);
+ this.notifyItems = NotifyItem.getAllNotifyItems();
} else if (executor instanceof ExecutorAdapter>) {
this.executor = (ExecutorAdapter>) executor;
+ this.notifyItems = NotifyItem.getAllNotifyItems();
} else if (executor instanceof VirtualThreadExecutorProxy) {
- this.executor = new VirtualThreadExecutorAdapter(((VirtualThreadExecutorProxy) executor).getThreadPerTaskExecutor());
+ this.executor = new VirtualThreadExecutorAdapter(executor);
+ this.threadPoolAliasName = ((VirtualThreadExecutorProxy) executor).getThreadPoolAliasName();
+ this.notifyItems = ((VirtualThreadExecutorProxy) executor).getNotifyItems();
+ this.notifyEnabled = ((VirtualThreadExecutorProxy) executor).isNotifyEnabled();
+ this.platformIds = ((VirtualThreadExecutorProxy) executor).getPlatformIds();
+ this.awareNames = ((VirtualThreadExecutorProxy) executor).getAwareNames();
+ this.executorStatProvider = ExecutorStatProvider.of(this);
} else {
throw new IllegalArgumentException("unsupported Executor type !");
}
- this.notifyItems = NotifyItem.getAllNotifyItems();
AlarmManager.initAlarm(threadPoolName, notifyItems);
- this.threadPoolStatProvider = ThreadPoolStatProvider.of(this);
+ this.executorStatProvider = ExecutorStatProvider.of(this);
}
/**
@@ -180,7 +188,10 @@ public void initialize() {
if (isDtpExecutor()) {
((DtpExecutor) getExecutor()).initialize();
AwareManager.register(this);
- } else if (isThreadPoolExecutor() || isVirtualThreadExecutor()) {
+ } else if (isVirtualThreadExecutor()) {
+ ((VirtualThreadExecutorProxy) getExecutor().getOriginal()).initialize();
+ AwareManager.register(this);
+ } else if (isThreadPoolExecutor()) {
AwareManager.register(this);
}
}
@@ -213,7 +224,8 @@ public boolean isThreadPoolExecutor() {
* @return boolean
*/
public boolean isVirtualThreadExecutor() {
- return this.executor instanceof VirtualThreadExecutorAdapter;
+ return this.executor instanceof VirtualThreadExecutorAdapter
+ || this.executor.getOriginal() instanceof VirtualThreadExecutorAdapter;
}
/**
diff --git a/core/src/main/java/org/dromara/dynamictp/core/support/VirtualThreadExecutorAdapter.java b/core/src/main/java/org/dromara/dynamictp/core/support/adapter/VirtualThreadExecutorAdapter.java
similarity index 95%
rename from core/src/main/java/org/dromara/dynamictp/core/support/VirtualThreadExecutorAdapter.java
rename to core/src/main/java/org/dromara/dynamictp/core/support/adapter/VirtualThreadExecutorAdapter.java
index 6d3a2dff6..54dea40e9 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/support/VirtualThreadExecutorAdapter.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/support/adapter/VirtualThreadExecutorAdapter.java
@@ -14,9 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.dromara.dynamictp.core.support;
-
-import org.dromara.dynamictp.core.support.adapter.ExecutorAdapter;
+package org.dromara.dynamictp.core.support.adapter;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
diff --git a/core/src/main/java/org/dromara/dynamictp/core/support/proxy/VirtualThreadExecutorProxy.java b/core/src/main/java/org/dromara/dynamictp/core/support/proxy/VirtualThreadExecutorProxy.java
index 906d3b4c0..3938f9a51 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/support/proxy/VirtualThreadExecutorProxy.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/support/proxy/VirtualThreadExecutorProxy.java
@@ -22,6 +22,7 @@
import org.dromara.dynamictp.common.entity.NotifyItem;
import org.dromara.dynamictp.core.aware.AwareManager;
import org.dromara.dynamictp.core.aware.TaskEnhanceAware;
+import org.dromara.dynamictp.core.notifier.manager.NotifyHelper;
import org.dromara.dynamictp.core.support.task.runnable.EnhancedRunnable;
import org.dromara.dynamictp.core.support.task.wrapper.TaskWrapper;
@@ -70,6 +71,11 @@ public class VirtualThreadExecutorProxy implements TaskEnhanceAware, ExecutorSer
*/
private String threadPoolAliasName;
+ /**
+ * Current pinned duration.
+ */
+ private long curPinDuration = 0;
+
/**
* If enable notify.
*/
@@ -78,7 +84,7 @@ public class VirtualThreadExecutorProxy implements TaskEnhanceAware, ExecutorSer
/**
* Notify items, see {@link NotifyItemEnum}.
*/
- private List notifyItems;
+ private List notifyItems = NotifyItem.getAllNotifyItems();
/**
* Plugin names.
@@ -190,6 +196,10 @@ public T invokeAny(Collection extends Callable> collection, long l, Tim
return threadPerTaskExecutor.invokeAny(collection, l, timeUnit);
}
+ public void initialize() {
+ NotifyHelper.initNotify(this);
+ }
+
public String getThreadPoolName() {
return threadPoolName;
}
@@ -245,4 +255,13 @@ public List getNotifyItems() {
public void setNotifyItems(List notifyItems) {
this.notifyItems = notifyItems;
}
+
+ public long getCurPinDuration() {
+ return curPinDuration;
+ }
+
+ public void setCurPinDuration(long curPinDuration) {
+ this.curPinDuration = curPinDuration;
+ }
+
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/timer/AbstractTimeoutTimerTask.java b/core/src/main/java/org/dromara/dynamictp/core/timer/AbstractTimeoutTimerTask.java
index 160e25140..8ba4a2ebd 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/timer/AbstractTimeoutTimerTask.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/timer/AbstractTimeoutTimerTask.java
@@ -46,7 +46,7 @@ protected AbstractTimeoutTimerTask(ExecutorWrapper executorWrapper, Runnable run
@Override
public void run(Timeout timeout) throws Exception {
- val statProvider = executorWrapper.getThreadPoolStatProvider();
+ val statProvider = executorWrapper.getExecutorStatProvider();
if (Objects.isNull(statProvider)) {
return;
}
diff --git a/core/src/main/java/org/dromara/dynamictp/core/timer/QueueTimeoutTimerTask.java b/core/src/main/java/org/dromara/dynamictp/core/timer/QueueTimeoutTimerTask.java
index 2bbb82a3c..36c3f0059 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/timer/QueueTimeoutTimerTask.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/timer/QueueTimeoutTimerTask.java
@@ -40,7 +40,7 @@ public QueueTimeoutTimerTask(ExecutorWrapper executorWrapper, Runnable runnable)
@Override
protected void doRun() {
- val statProvider = executorWrapper.getThreadPoolStatProvider();
+ val statProvider = executorWrapper.getExecutorStatProvider();
ExecutorAdapter> executor = statProvider.getExecutorWrapper().getExecutor();
val pair = getTaskNameAndTraceId();
statProvider.incQueueTimeoutCount(1);
diff --git a/core/src/main/java/org/dromara/dynamictp/core/timer/RunTimeoutTimerTask.java b/core/src/main/java/org/dromara/dynamictp/core/timer/RunTimeoutTimerTask.java
index 3bf958a38..e343edbc6 100644
--- a/core/src/main/java/org/dromara/dynamictp/core/timer/RunTimeoutTimerTask.java
+++ b/core/src/main/java/org/dromara/dynamictp/core/timer/RunTimeoutTimerTask.java
@@ -43,7 +43,7 @@ public RunTimeoutTimerTask(ExecutorWrapper executorWrapper, Runnable runnable, T
@Override
protected void doRun() {
- val statProvider = executorWrapper.getThreadPoolStatProvider();
+ val statProvider = executorWrapper.getExecutorStatProvider();
ExecutorAdapter> executor = statProvider.getExecutorWrapper().getExecutor();
val pair = getTaskNameAndTraceId();
statProvider.incRunTimeoutCount(1);
diff --git a/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..820caeadf 100644
--- a/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-apollo/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-consul-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-etcd/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-huawei-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-nacos-cloud/pom.xml b/example/example-nacos-cloud/pom.xml
index 22490e3b1..a2baf0fb6 100644
--- a/example/example-nacos-cloud/pom.xml
+++ b/example/example-nacos-cloud/pom.xml
@@ -20,7 +20,7 @@
com.alibaba.cloud
spring-cloud-alibaba-dependencies
- 2021.1
+ 2022.0.0.0
pom
import
@@ -89,4 +89,16 @@
spring-boot-starter-data-redis
-
\ No newline at end of file
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 21
+
+
+
+
+
diff --git a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/service/impl/TestServiceImpl.java b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/service/impl/TestServiceImpl.java
index 1c7b49f2a..4342dac02 100644
--- a/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/service/impl/TestServiceImpl.java
+++ b/example/example-nacos-cloud/src/main/java/org/dromara/dynamictp/example/service/impl/TestServiceImpl.java
@@ -30,6 +30,7 @@
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
+import java.time.Duration;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
@@ -63,7 +64,7 @@ public TestServiceImpl(ThreadPoolExecutor jucThreadPoolExecutor,
DtpExecutor eagerDtpExecutor,
ScheduledExecutorService scheduledDtpExecutor,
OrderedDtpExecutor orderedDtpExecutor,
- @Qualifier("virtualThreadExecutor") ExecutorService virtualThreadExecutor) {
+ @Qualifier("virtualThreadExecutor1") ExecutorService virtualThreadExecutor) {
this.jucThreadPoolExecutor = jucThreadPoolExecutor;
this.threadPoolTaskExecutor = threadPoolTaskExecutor;
this.eagerDtpExecutor = eagerDtpExecutor;
@@ -153,11 +154,20 @@ public void testVTExecutor() {
for (int i = 0; i < 10; i++) {
int finalI = i;
virtualThreadExecutor.execute(() -> {
- log.info("i am a VTExecutor's {} task", finalI);
- try {
- Thread.sleep(30000);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+// log.info("i am a VTExecutor's {} task", finalI);
+// try {
+// Thread.sleep(30000);
+// } catch (InterruptedException e) {
+// throw new RuntimeException(e);
+// }
+ synchronized (this) {
+ log.info("i am a VTExecutor's {} task", finalI);
+ log.info("Causing thread pinning for example purposes");
+ try {
+ Thread.sleep(Duration.ofMillis(4000));
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
});
}
diff --git a/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-nacos/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-polaris-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-zookeeper-cloud/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java b/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
index 761568164..e17ee3556 100644
--- a/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
+++ b/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsDtpNotifier.java
@@ -52,6 +52,11 @@ protected String getAlarmTemplate() {
return SmsNotifyConst.SMS_ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{SmsNotifyConst.SMS_ALARM_TEMPLATE_PREFIX, SmsNotifyConst.SMS_ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), SmsNotifyConst.SMS_ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return null;
diff --git a/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java b/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
index 505ea7c13..a2588c47f 100644
--- a/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
+++ b/example/example-zookeeper/src/main/java/org/dromara/dynamictp/example/notifier/SmsNotifyConst.java
@@ -27,13 +27,26 @@ public class SmsNotifyConst {
private SmsNotifyConst() { }
- public static final String SMS_ALARM_TEMPLATE =
+ public static final String SMS_ALARM_TEMPLATE_PREFIX =
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警项:%s \n" +
- "报警阈值 / 当前值:%s \n" +
+ "报警阈值 / 当前值:%s \n";
+
+ public static final String SMS_ALARM_COMMON_TEMPLATE = "%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+
+ public static final String SMS_ALARM_TEMPLATE =
+ SMS_ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -50,12 +63,7 @@ private SmsNotifyConst() { }
"总拒绝任务数量:%s \n" +
"总执行超时任务数量:%s \n" +
"总等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ SMS_ALARM_TEMPLATE_SUFFIX;
public static final String SMS_NOTICE_TEMPLATE =
"服务名称:%s \n" +
diff --git a/extension/extension-notify-email/src/main/java/org/dromara/dynamictp/extension/notify/email/DtpEmailNotifier.java b/extension/extension-notify-email/src/main/java/org/dromara/dynamictp/extension/notify/email/DtpEmailNotifier.java
index ca1aa3049..d32ba1cac 100644
--- a/extension/extension-notify-email/src/main/java/org/dromara/dynamictp/extension/notify/email/DtpEmailNotifier.java
+++ b/extension/extension-notify-email/src/main/java/org/dromara/dynamictp/extension/notify/email/DtpEmailNotifier.java
@@ -72,6 +72,11 @@ protected String getAlarmTemplate() {
return null;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int length) {
+ return null;
+ }
+
@Override
protected Pair getColors() {
return null;
@@ -84,7 +89,7 @@ protected String buildAlarmContent(NotifyPlatform platform, NotifyItemEnum notif
val executor = executorWrapper.getExecutor();
NotifyItem notifyItem = alarmCtx.getNotifyItem();
AlarmInfo alarmInfo = alarmCtx.getAlarmInfo();
- val statProvider = executorWrapper.getThreadPoolStatProvider();
+ val statProvider = executorWrapper.getExecutorStatProvider();
val alarmValue = notifyItem.getThreshold() + notifyItemEnum.getUnit() + " / "
+ AlarmCounter.calcCurrentValue(executorWrapper, notifyItemEnum) + notifyItemEnum.getUnit();
diff --git a/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/DtpYunZhiJiaNotifier.java b/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/DtpYunZhiJiaNotifier.java
index fa6ce1da2..0b734e26e 100644
--- a/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/DtpYunZhiJiaNotifier.java
+++ b/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/DtpYunZhiJiaNotifier.java
@@ -51,6 +51,11 @@ protected String getAlarmTemplate() {
return YunZhiJiaNotifyConst.ALARM_TEMPLATE;
}
+ @Override
+ protected String[] getCommonAlarmTemplate(int num) {
+ return new String[]{YunZhiJiaNotifyConst.ALARM_TEMPLATE_PREFIX, YunZhiJiaNotifyConst.ALARM_COMMON_TEMPLATE.repeat(Math.max(0, num)), YunZhiJiaNotifyConst.ALARM_TEMPLATE_SUFFIX};
+ }
+
@Override
protected Pair getColors() {
return new ImmutablePair<>(YunZhiJiaNotifyConst.WARNING_COLOR, YunZhiJiaNotifyConst.COMMENT_COLOR);
diff --git a/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/YunZhiJiaNotifyConst.java b/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/YunZhiJiaNotifyConst.java
index c3d957fc7..3028e8489 100644
--- a/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/YunZhiJiaNotifyConst.java
+++ b/extension/extension-notify-yunzhijia/src/main/java/org/dromara/dynamictp/extension/notify/yunzhijia/YunZhiJiaNotifyConst.java
@@ -42,14 +42,25 @@ private YunZhiJiaNotifyConst() {
public static final String PLATFORM_NAME = "YUNZHIJIA";
- public static final String ALARM_TEMPLATE =
+ public static final String ALARM_TEMPLATE_PREFIX =
"【报警】 动态线程池告警 \n" +
"服务名称:%s \n" +
"实例信息:%s \n" +
"环境:%s \n" +
"线程池名称:%s \n" +
"报警类型:%s \n" +
- "报警阈值:%s \n" +
+ "报警阈值:%s \n";
+
+ public static final String ALARM_COMMON_TEMPLATE = "%s \n";
+ public static final String ALARM_TEMPLATE_SUFFIX =
+ "上次报警时间:%s \n" +
+ "报警时间:%s \n" +
+ "接收人:@%s \n" +
+ "trace 信息:%s \n" +
+ "报警间隔:%ss \n" +
+ "扩展信息:%s \n";
+ public static final String ALARM_TEMPLATE =
+ ALARM_TEMPLATE_PREFIX +
"核心线程数:%s \n" +
"最大线程数:%s \n" +
"当前线程数:%s \n" +
@@ -66,12 +77,7 @@ private YunZhiJiaNotifyConst() {
"拒绝任务数量:%s \n" +
"执行超时任务数量:%s \n" +
"等待超时任务数量:%s \n" +
- "上次报警时间:%s \n" +
- "报警时间:%s \n" +
- "接收人:@%s \n" +
- "trace 信息:%s \n" +
- "报警间隔:%ss \n" +
- "扩展信息:%s \n";
+ ALARM_TEMPLATE_SUFFIX;
public static final String CHANGE_NOTICE_TEMPLATE =
"【通知】 动态线程池参数变更 \n" +
diff --git a/spring/src/main/java/org/dromara/dynamictp/spring/DtpPostProcessor.java b/spring/src/main/java/org/dromara/dynamictp/spring/DtpPostProcessor.java
index 80e0cbef7..ed80321f4 100644
--- a/spring/src/main/java/org/dromara/dynamictp/spring/DtpPostProcessor.java
+++ b/spring/src/main/java/org/dromara/dynamictp/spring/DtpPostProcessor.java
@@ -57,7 +57,9 @@
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import static org.dromara.dynamictp.core.support.DtpLifecycleSupport.shutdownGracefulAsync;
@@ -198,7 +200,11 @@ private ScheduledThreadPoolExecutorProxy newScheduledTpProxy(String name, Schedu
}
private VirtualThreadExecutorProxy newVirtualThreadProxy(String name, ExecutorService originExecutor) {
- return new VirtualThreadExecutorProxy(originExecutor);
+ ThreadFactory factory = Thread.ofVirtual().name(name).factory();
+ ExecutorService executor = Executors.newThreadPerTaskExecutor(factory);
+ val proxy = new VirtualThreadExecutorProxy(executor);
+ shutdownGracefulAsync(originExecutor, name, 0);
+ return proxy;
}
private void tryWrapTaskDecorator(String poolName, ThreadPoolTaskExecutor poolTaskExecutor, ThreadPoolExecutorProxy proxy) throws IllegalAccessException {
diff --git a/test/test-core/pom.xml b/test/test-core/pom.xml
index 6ae1ac3b5..7dcdb18d8 100644
--- a/test/test-core/pom.xml
+++ b/test/test-core/pom.xml
@@ -20,5 +20,22 @@
spring-aspects
test
+
+ org.assertj
+ assertj-core
+ test
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 21
+
+
+
+
diff --git a/test/test-core/src/test/java/org/dromara/dynamictp/test/core/notify/AbstractDtpNotifierTest.java b/test/test-core/src/test/java/org/dromara/dynamictp/test/core/notify/AbstractDtpNotifierTest.java
index 31402d14c..e1b1fb5ac 100644
--- a/test/test-core/src/test/java/org/dromara/dynamictp/test/core/notify/AbstractDtpNotifierTest.java
+++ b/test/test-core/src/test/java/org/dromara/dynamictp/test/core/notify/AbstractDtpNotifierTest.java
@@ -117,6 +117,17 @@ public void testSendAlarmMsg() {
Mockito.verify(this.notifier, Mockito.times(1)).send(any(), anyString());
}
+ @Test
+ public void testSendCommonAlarmMsg() {
+ AbstractDtpNotifier notifier = new DtpDingNotifier(this.notifier);
+ NotifyPlatform notifyPlatform = new NotifyPlatform();
+ NotifyItemEnum notifyItemEnum = NotifyItemEnum.LIVENESS;
+ DtpNotifyCtxHolder.set(new AlarmCtx(ExecutorWrapper.of(dtpExecutor), new NotifyItem()));
+ notifier.sendCommonAlarmMsg(notifyPlatform, notifyItemEnum, "arg1", "arg2", "arg3");
+
+ Mockito.verify(this.notifier, Mockito.times(1)).send(any(), anyString());
+ }
+
@Test
public void testGetQueueName2() {
Assert.assertEquals(dtpExecutor.getQueueType(), VARIABLE_LINKED_BLOCKING_QUEUE.getName());
diff --git a/test/test-core/src/test/java/org/dromara/dynamictp/test/core/thread/ScheduledDtpExecutorTest.java b/test/test-core/src/test/java/org/dromara/dynamictp/test/core/thread/ScheduledDtpExecutorTest.java
index cb60abdba..fd9d2f946 100644
--- a/test/test-core/src/test/java/org/dromara/dynamictp/test/core/thread/ScheduledDtpExecutorTest.java
+++ b/test/test-core/src/test/java/org/dromara/dynamictp/test/core/thread/ScheduledDtpExecutorTest.java
@@ -29,6 +29,7 @@
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.time.LocalDateTime;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@PropertySource(value = "classpath:/dynamic-tp-nacos-demo-dtp-dev.yml", factory = YamlPropertySourceFactory.class)
@@ -67,4 +68,14 @@ void testSubNotify() {
dtpExecutor14.shutdownNow();
}
+ @Test
+ void testScheduleCancel() {
+ ScheduledDtpExecutor dtpExecutor12 = (ScheduledDtpExecutor) DtpRegistry.getExecutor("dtpExecutor12");
+ ScheduledFuture> scheduledFuture = dtpExecutor12.scheduleWithFixedDelay(() -> {
+ System.out.println(Thread.currentThread().getName() + "进来了," +
+ "当前时间是 ");
+ }, 0, 1000, TimeUnit.MILLISECONDS);
+ scheduledFuture.cancel(false);
+ }
+
}