This is an automated email from the ASF dual-hosted git repository.
hefengen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 79ded8126a [type: feat] send alarm message when gateway global error
happen (#5382)
79ded8126a is described below
commit 79ded8126a15a0a5be26100fa80ad101fdc7c7eb
Author: tomsun28 <[email protected]>
AuthorDate: Mon Dec 25 14:50:46 2023 +0800
[type: feat] send alarm message when gateway global error happen (#5382)
* send alarm message when gateway global error happen
* add alarm title
* fix unit test
---
.../alert/strategy/AbstractAlertNotifyHandler.java | 8 +++++++-
.../resources/static/alertNotifyDingTalkRobot.txt | 1 +
shenyu-bootstrap/src/main/resources/application.yml | 2 +-
.../apache/shenyu/plugin/base/alert/AlarmSender.java | 19 ++++++++++++++-----
.../apache/shenyu/web/handler/GlobalErrorHandler.java | 14 +++++++++++++-
.../shenyu/web/handler/GlobalErrorHandlerTest.java | 6 ++++++
6 files changed, 42 insertions(+), 8 deletions(-)
diff --git
a/shenyu-alert/src/main/java/org/apache/shenyu/alert/strategy/AbstractAlertNotifyHandler.java
b/shenyu-alert/src/main/java/org/apache/shenyu/alert/strategy/AbstractAlertNotifyHandler.java
index 885d9bba63..67a43d4d2c 100644
---
a/shenyu-alert/src/main/java/org/apache/shenyu/alert/strategy/AbstractAlertNotifyHandler.java
+++
b/shenyu-alert/src/main/java/org/apache/shenyu/alert/strategy/AbstractAlertNotifyHandler.java
@@ -24,6 +24,7 @@ import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;
@@ -44,8 +45,13 @@ abstract class AbstractAlertNotifyHandler implements
AlertNotifyHandler {
Context context = new Context();
context.setVariable("title", "[ShenYu Alarm]");
+ context.setVariable("titleLabel", "Alarm Title");
+ context.setVariable("alarmTitle", alert.getTitle());
+
context.setVariable("triggerTimeLabel", "Alarm Time");
- context.setVariable("triggerTime",
DTF.format(LocalDateTime.ofInstant(alert.getDateCreated().toInstant(),
TimeZone.getDefault().toZoneId())));
+ context.setVariable("triggerTime", DTF.format(LocalDateTime.ofInstant(
+ alert.getDateCreated() == null ? Instant.now() :
alert.getDateCreated().toInstant(),
+ TimeZone.getDefault().toZoneId())));
context.setVariable("contentLabel", "Alarm Content");
context.setVariable("content", alert.getContent());
diff --git
a/shenyu-alert/src/main/resources/static/alertNotifyDingTalkRobot.txt
b/shenyu-alert/src/main/resources/static/alertNotifyDingTalkRobot.txt
index b3b98706dd..fef7a0cc85 100644
--- a/shenyu-alert/src/main/resources/static/alertNotifyDingTalkRobot.txt
+++ b/shenyu-alert/src/main/resources/static/alertNotifyDingTalkRobot.txt
@@ -1,3 +1,4 @@
#### [(${title})]
+ ##### **[(${titleLabel})]** : [(${alarmTitle})]
##### **[(${triggerTimeLabel})]** : [(${triggerTime})]
##### **[(${contentLabel})]** : [(${content})]
diff --git a/shenyu-bootstrap/src/main/resources/application.yml
b/shenyu-bootstrap/src/main/resources/application.yml
index d5cb50f9ac..91ea244774 100644
--- a/shenyu-bootstrap/src/main/resources/application.yml
+++ b/shenyu-bootstrap/src/main/resources/application.yml
@@ -287,7 +287,7 @@ shenyu:
- /actuator
- /health_check
alert:
- enabled: true
+ enabled: false
admins: localhost:9095
extPlugin:
path:
diff --git
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/alert/AlarmSender.java
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/alert/AlarmSender.java
index 1277aabb02..2711a64e34 100644
---
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/alert/AlarmSender.java
+++
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/alert/AlarmSender.java
@@ -17,8 +17,11 @@
package org.apache.shenyu.plugin.base.alert;
+import org.apache.shenyu.common.config.ShenyuConfig;
import org.apache.shenyu.common.dto.AlarmContent;
import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
+
+import java.util.Date;
import java.util.Map;
/**
@@ -47,6 +50,8 @@ public class AlarmSender {
private static AlarmService alarmService;
+ private static Boolean enabled;
+
/**
* Send alarm content.
* @param alarmContent alarm content
@@ -55,6 +60,10 @@ public class AlarmSender {
if (alarmService == null) {
alarmService =
SpringBeanUtils.getInstance().getBean(AlarmService.class);
}
+ if (enabled == null) {
+ ShenyuConfig shenyuConfig =
SpringBeanUtils.getInstance().getBean(ShenyuConfig.class);
+ enabled = shenyuConfig.getAlert().getEnabled();
+ }
AlarmThreadPoolExecutor.getInstance().execute(() -> {
alarmService.alarm(alarmContent);
});
@@ -70,7 +79,7 @@ public class AlarmSender {
public static void alarm(final byte level, final String title, final
String content, final Map<String, String> labels) {
AlarmContent alarmContent = new AlarmContent.Builder()
.level(level).title(title).content(content)
- .labels(labels).build();
+ .labels(labels).dateCreated(new
Date()).build();
alarm(alarmContent);
}
@@ -83,7 +92,7 @@ public class AlarmSender {
public static void alarm(final byte level, final String title, final
String content) {
AlarmContent alarmContent = new AlarmContent.Builder()
.level(level).title(title)
- .content(content).build();
+ .content(content).dateCreated(new
Date()).build();
alarm(alarmContent);
}
@@ -96,7 +105,7 @@ public class AlarmSender {
public static void alarmHighEmergency(final String title, final String
content, final Map<String, String> labels) {
AlarmContent alarmContent = new AlarmContent.Builder()
.level((byte)
0).title(title).content(content)
- .labels(labels).build();
+ .labels(labels).dateCreated(new
Date()).build();
alarm(alarmContent);
}
@@ -109,7 +118,7 @@ public class AlarmSender {
public static void alarmMediumCritical(final String title, final String
content, final Map<String, String> labels) {
AlarmContent alarmContent = new AlarmContent.Builder()
.level((byte)
1).title(title).content(content)
- .labels(labels).build();
+ .labels(labels).dateCreated(new
Date()).build();
alarm(alarmContent);
}
@@ -122,7 +131,7 @@ public class AlarmSender {
public static void alarmLowWarning(final String title, final String
content, final Map<String, String> labels) {
AlarmContent alarmContent = new AlarmContent.Builder()
.level((byte)
2).title(title).content(content)
- .labels(labels).build();
+ .labels(labels).dateCreated(new
Date()).build();
alarm(alarmContent);
}
}
diff --git
a/shenyu-web/src/main/java/org/apache/shenyu/web/handler/GlobalErrorHandler.java
b/shenyu-web/src/main/java/org/apache/shenyu/web/handler/GlobalErrorHandler.java
index 661914870f..059a00ead6 100644
---
a/shenyu-web/src/main/java/org/apache/shenyu/web/handler/GlobalErrorHandler.java
+++
b/shenyu-web/src/main/java/org/apache/shenyu/web/handler/GlobalErrorHandler.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.web.handler;
import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
+import org.apache.shenyu.plugin.base.alert.AlarmSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
@@ -30,6 +31,9 @@ import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* GlobalErrorHandler.
*/
@@ -47,21 +51,29 @@ public class GlobalErrorHandler implements
ErrorWebExceptionHandler {
@Override
@NonNull
public Mono<Void> handle(@NonNull final ServerWebExchange exchange,
@NonNull final Throwable throwable) {
- LOG.error("handle error: {} formatError:{} throwable:{}",
exchange.getLogPrefix(), formatError(throwable, exchange.getRequest()),
throwable);
+ LOG.error("handle error: {} formatError:{} throwable:",
exchange.getLogPrefix(), formatError(throwable, exchange.getRequest()),
throwable);
HttpStatus httpStatus;
Object errorResult;
+ String errorMsg = "";
if (throwable instanceof IllegalArgumentException) {
httpStatus = HttpStatus.BAD_REQUEST;
errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(),
throwable.getMessage(), null);
+ errorMsg = throwable.getMessage();
} else if (throwable instanceof ResponseStatusException) {
httpStatus = ((ResponseStatusException) throwable).getStatus();
String errMsg = StringUtils.hasLength(((ResponseStatusException)
throwable).getReason()) ? ((ResponseStatusException) throwable).getReason() :
httpStatus.getReasonPhrase();
errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(),
errMsg, null);
+ errorMsg = errMsg;
} else {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
errorResult = ShenyuResultWrap.error(exchange, httpStatus.value(),
httpStatus.getReasonPhrase(), null);
+ errorMsg = httpStatus.getReasonPhrase();
}
exchange.getResponse().setStatusCode(httpStatus);
+ Map<String, String> labels = new HashMap<>(8);
+ labels.put("global", "error");
+ labels.put("component", "gateway");
+ AlarmSender.alarmMediumCritical("ShenYu-Gateway-Global-Error",
errorMsg, labels);
return WebFluxResultUtils.result(exchange, errorResult);
}
diff --git
a/shenyu-web/src/test/java/org/apache/shenyu/web/handler/GlobalErrorHandlerTest.java
b/shenyu-web/src/test/java/org/apache/shenyu/web/handler/GlobalErrorHandlerTest.java
index 31d5f9a7be..ad62f4fcad 100644
---
a/shenyu-web/src/test/java/org/apache/shenyu/web/handler/GlobalErrorHandlerTest.java
+++
b/shenyu-web/src/test/java/org/apache/shenyu/web/handler/GlobalErrorHandlerTest.java
@@ -17,9 +17,11 @@
package org.apache.shenyu.web.handler;
+import org.apache.shenyu.common.config.ShenyuConfig;
import org.apache.shenyu.plugin.api.result.DefaultShenyuResult;
import org.apache.shenyu.plugin.api.result.ShenyuResult;
import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
+import org.apache.shenyu.plugin.base.alert.AlarmService;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -76,6 +78,10 @@ public final class GlobalErrorHandlerTest {
SpringBeanUtils.getInstance().setApplicationContext(context);
when(context.getBean(ShenyuResult.class)).thenReturn(new
DefaultShenyuResult() {
});
+ when(context.getBean(AlarmService.class)).thenReturn(content -> {
+ });
+ when(context.getBean(ShenyuConfig.class)).thenReturn(new
ShenyuConfig() {
+ });
globalErrorHandler = new GlobalErrorHandler();
}