[Improvement][Alert] Add a test send feature when creating an alert instance (#15163)
* add alert test send feature * update doc * add alarm instance test send ui * update * fix mvn * fix test * update * update * change to rpc * fix ut * fix ut * update * update * change result * update * Update docs/docs/en/guide/alert/alert_plugin_user_guide.md Co-authored-by: Aaron Wang <wangweirao16@gmail.com> --------- Co-authored-by: Aaron Wang <wangweirao16@gmail.com>
This commit is contained in:
parent
2f2825784a
commit
6aa6e114a5
|
|
@ -13,6 +13,8 @@ Steps to be used are as follows:
|
|||
- Select the corresponding alarm plug-in and fill in the relevant alarm parameters.
|
||||
- Select `Alarm Group Management`, create an alarm group, and choose the corresponding alarm instance.
|
||||
|
||||
> You can click `Test Send` button to test whether the alarm instance is configured correctly.
|
||||
|
||||

|
||||
|
||||

|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
然后选择告警组管理,创建告警组,选择相应的告警实例即可。
|
||||
|
||||
> 可以使用`测试发送`功能来验证配置的告警实例是否正确。
|
||||
|
||||

|
||||

|
||||

|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 108 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 145 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 150 KiB |
|
|
@ -31,6 +31,8 @@ public final class AlertConstants {
|
|||
public static final String WARNING_TYPE = "warningType";
|
||||
|
||||
public static final String NAME_WARNING_TYPE = "WarningType";
|
||||
public static final String TEST_TITLE = "DolphinScheduler test alert";
|
||||
public static final String TEST_CONTENT = "[{\"message\":\" This is a test alert message form DolphinScheduler\"}]";
|
||||
|
||||
private AlertConstants() {
|
||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import org.apache.dolphinscheduler.alert.service.AlertBootstrapService;
|
|||
import org.apache.dolphinscheduler.extract.alert.IAlertOperator;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendRequest;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertTestSendRequest;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
|
@ -44,4 +45,14 @@ public class AlertOperatorImpl implements IAlertOperator {
|
|||
log.info("Handle AlertSendRequest finish: {}", alertSendResponse);
|
||||
return alertSendResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertSendResponse sendTestAlert(AlertTestSendRequest alertSendRequest) {
|
||||
log.info("Received AlertTestSendRequest : {}", alertSendRequest);
|
||||
AlertSendResponse alertSendResponse = alertBootstrapService.syncTestSend(
|
||||
alertSendRequest.getPluginDefineId(),
|
||||
alertSendRequest.getPluginInstanceParams());
|
||||
log.info("Handle AlertTestSendRequest finish: {}", alertSendResponse);
|
||||
return alertSendResponse;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import org.apache.dolphinscheduler.dao.entity.Alert;
|
|||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertSendStatus;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
|
|
@ -192,7 +193,7 @@ public final class AlertBootstrapService extends BaseDaemonThread implements Aut
|
|||
if (alertResult != null) {
|
||||
AlertSendResponse.AlertSendResponseResult alertSendResponseResult =
|
||||
new AlertSendResponse.AlertSendResponseResult(
|
||||
Boolean.parseBoolean(String.valueOf(alertResult.getStatus())),
|
||||
Boolean.parseBoolean(alertResult.getStatus()),
|
||||
alertResult.getMessage());
|
||||
sendResponseStatus = sendResponseStatus && alertSendResponseResult.isSuccess();
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
|
|
@ -302,6 +303,61 @@ public final class AlertBootstrapService extends BaseDaemonThread implements Aut
|
|||
}
|
||||
}
|
||||
|
||||
public AlertSendResponse syncTestSend(int pluginDefineId, String pluginInstanceParams) {
|
||||
|
||||
boolean sendResponseStatus = true;
|
||||
List<AlertSendResponse.AlertSendResponseResult> sendResponseResults = new ArrayList<>();
|
||||
|
||||
Optional<AlertChannel> alertChannelOptional = alertPluginManager.getAlertChannel(pluginDefineId);
|
||||
if (!alertChannelOptional.isPresent()) {
|
||||
String message = String.format("Test send alert error: the channel doesn't exist, pluginDefineId: %s",
|
||||
pluginDefineId);
|
||||
AlertSendResponse.AlertSendResponseResult alertSendResponseResult =
|
||||
new AlertSendResponse.AlertSendResponseResult();
|
||||
alertSendResponseResult.setSuccess(false);
|
||||
alertSendResponseResult.setMessage(message);
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
log.error("Test send alert error : not found plugin {}", pluginDefineId);
|
||||
return new AlertSendResponse(false, sendResponseResults);
|
||||
}
|
||||
AlertChannel alertChannel = alertChannelOptional.get();
|
||||
|
||||
Map<String, String> paramsMap = PluginParamsTransfer.getPluginParamsMap(pluginInstanceParams);
|
||||
|
||||
AlertData alertData = AlertData.builder()
|
||||
.title(AlertConstants.TEST_TITLE)
|
||||
.content(AlertConstants.TEST_CONTENT)
|
||||
.warnType(WarningType.ALL.getCode())
|
||||
.build();
|
||||
|
||||
AlertInfo alertInfo = AlertInfo.builder()
|
||||
.alertData(alertData)
|
||||
.alertParams(paramsMap)
|
||||
.build();
|
||||
|
||||
try {
|
||||
AlertResult alertResult = alertChannel.process(alertInfo);
|
||||
if (alertResult != null) {
|
||||
AlertSendResponse.AlertSendResponseResult alertSendResponseResult =
|
||||
new AlertSendResponse.AlertSendResponseResult(
|
||||
Boolean.parseBoolean(alertResult.getStatus()),
|
||||
alertResult.getMessage());
|
||||
sendResponseStatus = alertSendResponseResult.isSuccess();
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Test send alert error", e);
|
||||
AlertSendResponse.AlertSendResponseResult alertSendResponseResult =
|
||||
new AlertSendResponse.AlertSendResponseResult();
|
||||
alertSendResponseResult.setSuccess(false);
|
||||
alertSendResponseResult.setMessage(e.getMessage());
|
||||
sendResponseResults.add(alertSendResponseResult);
|
||||
return new AlertSendResponse(false, sendResponseResults);
|
||||
}
|
||||
|
||||
return new AlertSendResponse(sendResponseStatus, sendResponseResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
log.info("Closed AlertBootstrapService...");
|
||||
|
|
|
|||
|
|
@ -259,5 +259,4 @@ public final class ListenerEventPostService extends BaseDaemonThread implements
|
|||
public void close() {
|
||||
log.info("Closed ListenerEventPostService...");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,15 +26,19 @@ import org.apache.dolphinscheduler.alert.config.AlertConfig;
|
|||
import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager;
|
||||
import org.apache.dolphinscheduler.alert.service.AlertBootstrapService;
|
||||
import org.apache.dolphinscheduler.common.enums.WarningType;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.dao.AlertDao;
|
||||
import org.apache.dolphinscheduler.dao.PluginDao;
|
||||
import org.apache.dolphinscheduler.dao.entity.Alert;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.dao.entity.ListenerEvent;
|
||||
import org.apache.dolphinscheduler.dao.entity.PluginDefine;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
|
@ -42,6 +46,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -63,6 +68,18 @@ public class AlertBootstrapServiceTest {
|
|||
@InjectMocks
|
||||
private AlertBootstrapService alertBootstrapService;
|
||||
|
||||
private static final String PLUGIN_INSTANCE_PARAMS =
|
||||
"{\"User\":\"xx\",\"receivers\":\"xx\",\"sender\":\"xx\",\"smtpSslTrust\":\"*\",\"enableSmtpAuth\":\"true\",\"receiverCcs\":null,\"showType\":\"table\",\"starttlsEnable\":\"false\",\"serverPort\":\"25\",\"serverHost\":\"xx\",\"Password\":\"xx\",\"sslEnable\":\"false\"}";
|
||||
|
||||
private static final String PLUGIN_INSTANCE_NAME = "alert-instance-mail";
|
||||
private static final String TITLE = "alert mail test TITLE";
|
||||
private static final String CONTENT = "alert mail test CONTENT";
|
||||
private static final List<ListenerEvent> EVENTS = new ArrayList<>();
|
||||
|
||||
private static final int PLUGIN_DEFINE_ID = 1;
|
||||
|
||||
private static final int ALERT_GROUP_ID = 1;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
|
@ -70,17 +87,12 @@ public class AlertBootstrapServiceTest {
|
|||
|
||||
@Test
|
||||
public void testSyncHandler() {
|
||||
|
||||
int alertGroupId = 1;
|
||||
String title = "alert mail test title";
|
||||
String content = "alert mail test content";
|
||||
|
||||
// 1.alert instance does not exist
|
||||
when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(null);
|
||||
when(alertDao.listInstanceByAlertGroupId(ALERT_GROUP_ID)).thenReturn(null);
|
||||
when(alertConfig.getWaitTimeout()).thenReturn(0);
|
||||
|
||||
AlertSendResponse alertSendResponse =
|
||||
alertBootstrapService.syncHandler(alertGroupId, title, content, WarningType.ALL.getCode());
|
||||
alertBootstrapService.syncHandler(ALERT_GROUP_ID, TITLE, CONTENT, WarningType.ALL.getCode());
|
||||
Assertions.assertFalse(alertSendResponse.isSuccess());
|
||||
alertSendResponse.getResResults().forEach(result -> logger
|
||||
.info("alert send response result, status:{}, message:{}", result.isSuccess(), result.getMessage()));
|
||||
|
|
@ -101,7 +113,7 @@ public class AlertBootstrapServiceTest {
|
|||
when(pluginDao.getPluginDefineById(pluginDefineId)).thenReturn(pluginDefine);
|
||||
|
||||
alertSendResponse =
|
||||
alertBootstrapService.syncHandler(alertGroupId, title, content, WarningType.ALL.getCode());
|
||||
alertBootstrapService.syncHandler(ALERT_GROUP_ID, TITLE, CONTENT, WarningType.ALL.getCode());
|
||||
Assertions.assertFalse(alertSendResponse.isSuccess());
|
||||
alertSendResponse.getResResults().forEach(result -> logger
|
||||
.info("alert send response result, status:{}, message:{}", result.isSuccess(), result.getMessage()));
|
||||
|
|
@ -113,7 +125,7 @@ public class AlertBootstrapServiceTest {
|
|||
when(alertConfig.getWaitTimeout()).thenReturn(0);
|
||||
|
||||
alertSendResponse =
|
||||
alertBootstrapService.syncHandler(alertGroupId, title, content, WarningType.ALL.getCode());
|
||||
alertBootstrapService.syncHandler(ALERT_GROUP_ID, TITLE, CONTENT, WarningType.ALL.getCode());
|
||||
Assertions.assertFalse(alertSendResponse.isSuccess());
|
||||
alertSendResponse.getResResults().forEach(result -> logger
|
||||
.info("alert send response result, status:{}, message:{}", result.isSuccess(), result.getMessage()));
|
||||
|
|
@ -126,7 +138,7 @@ public class AlertBootstrapServiceTest {
|
|||
when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
|
||||
|
||||
alertSendResponse =
|
||||
alertBootstrapService.syncHandler(alertGroupId, title, content, WarningType.ALL.getCode());
|
||||
alertBootstrapService.syncHandler(ALERT_GROUP_ID, TITLE, CONTENT, WarningType.ALL.getCode());
|
||||
Assertions.assertFalse(alertSendResponse.isSuccess());
|
||||
alertSendResponse.getResResults().forEach(result -> logger
|
||||
.info("alert send response result, status:{}, message:{}", result.isSuccess(), result.getMessage()));
|
||||
|
|
@ -140,7 +152,7 @@ public class AlertBootstrapServiceTest {
|
|||
when(alertConfig.getWaitTimeout()).thenReturn(5000);
|
||||
|
||||
alertSendResponse =
|
||||
alertBootstrapService.syncHandler(alertGroupId, title, content, WarningType.ALL.getCode());
|
||||
alertBootstrapService.syncHandler(ALERT_GROUP_ID, TITLE, CONTENT, WarningType.ALL.getCode());
|
||||
Assertions.assertTrue(alertSendResponse.isSuccess());
|
||||
alertSendResponse.getResResults().forEach(result -> logger
|
||||
.info("alert send response result, status:{}, message:{}", result.isSuccess(), result.getMessage()));
|
||||
|
|
@ -149,15 +161,12 @@ public class AlertBootstrapServiceTest {
|
|||
|
||||
@Test
|
||||
public void testRun() {
|
||||
int alertGroupId = 1;
|
||||
String title = "alert mail test title";
|
||||
String content = "alert mail test content";
|
||||
List<Alert> alertList = new ArrayList<>();
|
||||
Alert alert = new Alert();
|
||||
alert.setId(1);
|
||||
alert.setAlertGroupId(alertGroupId);
|
||||
alert.setTitle(title);
|
||||
alert.setContent(content);
|
||||
alert.setAlertGroupId(ALERT_GROUP_ID);
|
||||
alert.setTitle(TITLE);
|
||||
alert.setContent(CONTENT);
|
||||
alert.setWarningType(WarningType.FAILURE);
|
||||
alertList.add(alert);
|
||||
|
||||
|
|
@ -170,7 +179,7 @@ public class AlertBootstrapServiceTest {
|
|||
AlertPluginInstance alertPluginInstance = new AlertPluginInstance(
|
||||
pluginDefineId, pluginInstanceParams, pluginInstanceName);
|
||||
alertInstanceList.add(alertPluginInstance);
|
||||
when(alertDao.listInstanceByAlertGroupId(alertGroupId)).thenReturn(alertInstanceList);
|
||||
when(alertDao.listInstanceByAlertGroupId(ALERT_GROUP_ID)).thenReturn(alertInstanceList);
|
||||
|
||||
String pluginName = "alert-plugin-mail";
|
||||
PluginDefine pluginDefine = new PluginDefine(pluginName, "1", null);
|
||||
|
|
@ -186,4 +195,20 @@ public class AlertBootstrapServiceTest {
|
|||
when(alertDao.listInstanceByAlertGroupId(1)).thenReturn(new ArrayList<>());
|
||||
alertBootstrapService.send(alertList);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAlert() {
|
||||
AlertResult sendResult = new AlertResult();
|
||||
sendResult.setStatus(String.valueOf(true));
|
||||
sendResult.setMessage(String.format("Alert Plugin %s send success", PLUGIN_INSTANCE_NAME));
|
||||
AlertChannel alertChannelMock = mock(AlertChannel.class);
|
||||
when(alertChannelMock.process(Mockito.any())).thenReturn(sendResult);
|
||||
when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock));
|
||||
Map<String, String> paramsMap = JSONUtils.toMap(PLUGIN_INSTANCE_PARAMS);
|
||||
MockedStatic<PluginParamsTransfer> pluginParamsTransferMockedStatic =
|
||||
Mockito.mockStatic(PluginParamsTransfer.class);
|
||||
pluginParamsTransferMockedStatic.when(() -> PluginParamsTransfer.getPluginParamsMap(PLUGIN_INSTANCE_PARAMS))
|
||||
.thenReturn(paramsMap);
|
||||
alertBootstrapService.syncTestSend(PLUGIN_DEFINE_ID, PLUGIN_INSTANCE_PARAMS);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -228,6 +228,10 @@
|
|||
<groupId>com.azure.resourcemanager</groupId>
|
||||
<artifactId>azure-resourcemanager-datafactory</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-extract-alert</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<testResources>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static org.apache.dolphinscheduler.api.enums.Status.DELETE_ALERT_PLUGIN_I
|
|||
import static org.apache.dolphinscheduler.api.enums.Status.GET_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.SEND_TEST_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
import static org.apache.dolphinscheduler.api.enums.Status.UPDATE_ALERT_PLUGIN_INSTANCE_ERROR;
|
||||
|
||||
import org.apache.dolphinscheduler.api.enums.Status;
|
||||
|
|
@ -99,6 +100,19 @@ public class AlertPluginInstanceController extends BaseController {
|
|||
return returnDataList(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "testSendAlertPluginInstance", description = "TEST_SEND_ALERT_PLUGIN_INSTANCE")
|
||||
@Parameters({
|
||||
@Parameter(name = "pluginDefineId", description = "ALERT_PLUGIN_DEFINE_ID", required = true, schema = @Schema(implementation = int.class, example = "100")),
|
||||
@Parameter(name = "pluginInstanceParams", description = "ALERT_PLUGIN_INSTANCE_PARAMS", required = true, schema = @Schema(implementation = String.class, example = "ALERT_PLUGIN_INSTANCE_PARAMS"))
|
||||
})
|
||||
@PostMapping(value = "/test-send")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@ApiException(SEND_TEST_ALERT_PLUGIN_INSTANCE_ERROR)
|
||||
public Result testSendAlertPluginInstance(@RequestParam(value = "pluginDefineId") int pluginDefineId,
|
||||
@RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) {
|
||||
return alertPluginInstanceService.testSend(pluginDefineId, pluginInstanceParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* updateAlertPluginInstance
|
||||
*
|
||||
|
|
|
|||
|
|
@ -472,7 +472,10 @@ public enum Status {
|
|||
"failed to delete the alert instance, there is an alarm group associated with this alert instance",
|
||||
"删除告警实例失败,存在与此告警实例关联的警报组"),
|
||||
PROCESS_DEFINITION_VERSION_IS_USED(110013, "this process definition version is used", "此工作流定义版本被使用"),
|
||||
|
||||
ALERT_TEST_SENDING_FAILED(110014, "Alert test sending failed, [{0}]", "alert测试发送失败,[{0}]"),
|
||||
ALERT_CHANNEL_NOT_EXIST(110015, "Alert channel not exist", "alert channel不存在"),
|
||||
SEND_TEST_ALERT_PLUGIN_INSTANCE_ERROR(110016, "send test alert plugin instance error", "发送测试告警错误"),
|
||||
ALERT_SERVER_NOT_EXIST(110017, "Alert server does not exist", "Alert server不存在"),
|
||||
CREATE_ENVIRONMENT_ERROR(120001, "create environment error", "创建环境失败"),
|
||||
ENVIRONMENT_NAME_EXISTS(120002, "this environment name [{0}] already exists", "环境名称[{0}]已经存在"),
|
||||
ENVIRONMENT_NAME_IS_NULL(120003, "this environment name shouldn't be empty.", "环境名称不能为空"),
|
||||
|
|
|
|||
|
|
@ -94,4 +94,6 @@ public interface AlertPluginInstanceService {
|
|||
* @return plugins
|
||||
*/
|
||||
Result listPaging(User loginUser, String searchVal, int pageNo, int pageSize);
|
||||
|
||||
Result<Void> testSend(int pluginDefineId, String pluginInstanceParams);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import org.apache.dolphinscheduler.common.constants.Constants;
|
|||
import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType;
|
||||
import org.apache.dolphinscheduler.common.enums.AuthorizationType;
|
||||
import org.apache.dolphinscheduler.common.enums.WarningType;
|
||||
import org.apache.dolphinscheduler.common.model.Server;
|
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertGroup;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
|
|
@ -39,6 +40,13 @@ import org.apache.dolphinscheduler.dao.entity.User;
|
|||
import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper;
|
||||
import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper;
|
||||
import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper;
|
||||
import org.apache.dolphinscheduler.extract.alert.IAlertOperator;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertTestSendRequest;
|
||||
import org.apache.dolphinscheduler.extract.base.client.SingletonJdkDynamicRpcClientProxyFactory;
|
||||
import org.apache.dolphinscheduler.extract.base.utils.Host;
|
||||
import org.apache.dolphinscheduler.registry.api.RegistryClient;
|
||||
import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType;
|
||||
import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
|
@ -82,6 +90,9 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A
|
|||
|
||||
private final Integer GLOBAL_ALERT_GROUP_ID = 2;
|
||||
|
||||
@Autowired
|
||||
private RegistryClient registryClient;
|
||||
|
||||
/**
|
||||
* creat alert plugin instance
|
||||
*
|
||||
|
|
@ -352,4 +363,49 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A
|
|||
return first.isPresent();
|
||||
}
|
||||
|
||||
public Optional<Host> getAlertServerAddress() {
|
||||
List<Server> serverList = registryClient.getServerList(RegistryNodeType.ALERT_SERVER);
|
||||
if (CollectionUtils.isEmpty(serverList)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
Server server = serverList.get(0);
|
||||
return Optional.of(new Host(server.getHost(), server.getPort()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Void> testSend(int pluginDefineId, String pluginInstanceParams) {
|
||||
Result<Void> result = new Result<>();
|
||||
Optional<Host> alertServerAddressOptional = getAlertServerAddress();
|
||||
if (!alertServerAddressOptional.isPresent()) {
|
||||
log.error("Cannot get alert server address, please check the alert server is running");
|
||||
putMsg(result, Status.ALERT_SERVER_NOT_EXIST);
|
||||
return result;
|
||||
}
|
||||
|
||||
Host alertServerAddress = alertServerAddressOptional.get();
|
||||
AlertTestSendRequest alertTestSendRequest = new AlertTestSendRequest(
|
||||
pluginDefineId,
|
||||
pluginInstanceParams);
|
||||
|
||||
AlertSendResponse alertSendResponse;
|
||||
|
||||
try {
|
||||
IAlertOperator alertOperator = SingletonJdkDynamicRpcClientProxyFactory
|
||||
.getProxyClient(alertServerAddress.getAddress(), IAlertOperator.class);
|
||||
alertSendResponse = alertOperator.sendTestAlert(alertTestSendRequest);
|
||||
log.info("Send alert to: {} successfully, response: {}", alertServerAddress, alertSendResponse);
|
||||
} catch (Exception e) {
|
||||
log.error("Send alert: {} to: {} failed", alertTestSendRequest, alertServerAddress, e);
|
||||
putMsg(result, Status.ALERT_TEST_SENDING_FAILED, e.getMessage());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (alertSendResponse.isSuccess()) {
|
||||
putMsg(result, Status.SUCCESS);
|
||||
} else {
|
||||
putMsg(result, Status.ALERT_TEST_SENDING_FAILED, alertSendResponse.getResResults().get(0).getMessage());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,34 @@ public class AlertPluginInstanceControllerTest extends AbstractControllerTest {
|
|||
assertThat(actualResponseContent.toString()).isEqualTo(expectResponseContent.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAlertPluginInstance() throws Exception {
|
||||
// Given
|
||||
Result result = JSONUtils.parseObject(
|
||||
"{\"code\":0,\"msg\":\"success\",\"data\":\"Test Data\",\"success\":true,\"failed\":false}",
|
||||
Result.class);
|
||||
|
||||
final MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
|
||||
paramsMap.add("pluginDefineId", String.valueOf(pluginDefineId));
|
||||
paramsMap.add("pluginInstanceParams", pluginInstanceParams);
|
||||
|
||||
when(alertPluginInstanceService.testSend(eq(pluginDefineId), eq(pluginInstanceParams)))
|
||||
.thenReturn(result);
|
||||
|
||||
// When
|
||||
final MvcResult mvcResult = mockMvc.perform(post("/alert-plugin-instances/test-send")
|
||||
.header(SESSION_ID, sessionId)
|
||||
.params(paramsMap))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
|
||||
// Then
|
||||
final Result actualResponseContent =
|
||||
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class);
|
||||
assertThat(actualResponseContent.toString()).isEqualTo(expectResponseContent.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAlertPluginInstance() throws Exception {
|
||||
// Given
|
||||
|
|
|
|||
|
|
@ -25,11 +25,13 @@ import org.apache.dolphinscheduler.api.enums.Status;
|
|||
import org.apache.dolphinscheduler.api.permission.ResourcePermissionCheckService;
|
||||
import org.apache.dolphinscheduler.api.service.impl.AlertPluginInstanceServiceImpl;
|
||||
import org.apache.dolphinscheduler.api.service.impl.BaseServiceImpl;
|
||||
import org.apache.dolphinscheduler.api.utils.Result;
|
||||
import org.apache.dolphinscheduler.common.constants.Constants;
|
||||
import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType;
|
||||
import org.apache.dolphinscheduler.common.enums.AuthorizationType;
|
||||
import org.apache.dolphinscheduler.common.enums.UserType;
|
||||
import org.apache.dolphinscheduler.common.enums.WarningType;
|
||||
import org.apache.dolphinscheduler.common.model.Server;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertGroup;
|
||||
import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance;
|
||||
import org.apache.dolphinscheduler.dao.entity.PluginDefine;
|
||||
|
|
@ -37,6 +39,10 @@ import org.apache.dolphinscheduler.dao.entity.User;
|
|||
import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper;
|
||||
import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper;
|
||||
import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertTestSendRequest;
|
||||
import org.apache.dolphinscheduler.registry.api.RegistryClient;
|
||||
import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -78,6 +84,9 @@ public class AlertPluginInstanceServiceTest {
|
|||
@Mock
|
||||
private AlertGroupMapper alertGroupMapper;
|
||||
|
||||
@Mock
|
||||
private RegistryClient registryClient;
|
||||
|
||||
private List<AlertPluginInstance> alertPluginInstances;
|
||||
|
||||
private User user;
|
||||
|
|
@ -190,6 +199,26 @@ public class AlertPluginInstanceServiceTest {
|
|||
Assertions.assertNotNull(result.get(Constants.DATA_LIST));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAlert() {
|
||||
Result<Void> result;
|
||||
Mockito.when(registryClient.getServerList(RegistryNodeType.ALERT_SERVER)).thenReturn(new ArrayList<>());
|
||||
result = alertPluginInstanceService.testSend(1, uiParams);
|
||||
Assertions.assertEquals(Status.ALERT_SERVER_NOT_EXIST.getCode(), result.getCode());
|
||||
AlertSendResponse.AlertSendResponseResult alertResult = new AlertSendResponse.AlertSendResponseResult();
|
||||
alertResult.setSuccess(true);
|
||||
AlertTestSendRequest alertTestSendRequest = new AlertTestSendRequest(
|
||||
1,
|
||||
uiParams);
|
||||
Server server = new Server();
|
||||
server.setPort(50052);
|
||||
server.setHost("127.0.0.1");
|
||||
Mockito.when(registryClient.getServerList(RegistryNodeType.ALERT_SERVER))
|
||||
.thenReturn(Collections.singletonList(server));
|
||||
result = alertPluginInstanceService.testSend(1, uiParams);
|
||||
Assertions.assertEquals(Status.ALERT_TEST_SENDING_FAILED.getCode(), result.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() {
|
||||
List<String> ids = Arrays.asList("11,2,3", "5,96", null, "98,1");
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dolphinscheduler.extract.alert;
|
|||
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendRequest;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertSendResponse;
|
||||
import org.apache.dolphinscheduler.extract.alert.request.AlertTestSendRequest;
|
||||
import org.apache.dolphinscheduler.extract.base.RpcMethod;
|
||||
import org.apache.dolphinscheduler.extract.base.RpcService;
|
||||
|
||||
|
|
@ -28,4 +29,7 @@ public interface IAlertOperator {
|
|||
@RpcMethod
|
||||
AlertSendResponse sendAlert(AlertSendRequest alertSendRequest);
|
||||
|
||||
@RpcMethod
|
||||
AlertSendResponse sendTestAlert(AlertTestSendRequest alertSendRequest);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dolphinscheduler.extract.alert.request;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AlertTestSendRequest {
|
||||
|
||||
private int pluginDefineId;
|
||||
|
||||
private String pluginInstanceParams;
|
||||
}
|
||||
|
|
@ -33,5 +33,9 @@
|
|||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dolphinscheduler</groupId>
|
||||
<artifactId>dolphinscheduler-extract-base</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -238,5 +238,4 @@ public class RegistryClient {
|
|||
private Collection<String> getServerNodes(RegistryNodeType nodeType) {
|
||||
return getChildrenKeys(nodeType.getRegistryPath());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,8 @@ export default {
|
|||
user_password: 'Password',
|
||||
user_password_tips:
|
||||
'Please enter a password containing letters and numbers with a length between 6 and 20',
|
||||
confirm_password_tips: 'The both of password and confirm password are not same.',
|
||||
confirm_password_tips:
|
||||
'The both of password and confirm password are not same.',
|
||||
user_type: 'User Type',
|
||||
ordinary_user: 'Ordinary users',
|
||||
administrator: 'Administrator',
|
||||
|
|
@ -216,6 +217,7 @@ export default {
|
|||
confirm: 'Confirm',
|
||||
cancel: 'Cancel',
|
||||
submit: 'Submit',
|
||||
test_send: 'Test Send',
|
||||
create_alarm_instance: 'Create Alarm Instance',
|
||||
select_plugin: 'Select plugin',
|
||||
select_plugin_tips: 'Select Alarm plugin',
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ export default {
|
|||
confirm: '确定',
|
||||
cancel: '取消',
|
||||
submit: '提交',
|
||||
test_send: '测试发送',
|
||||
create_alarm_instance: '创建告警实例',
|
||||
select_plugin: '选择插件',
|
||||
select_plugin_tips: '请选择告警插件',
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import {
|
|||
PluginInstanceReq,
|
||||
InstanceNameReq,
|
||||
IdReq,
|
||||
UpdatePluginInstanceReq
|
||||
UpdatePluginInstanceReq,
|
||||
TestPluginInstanceReq
|
||||
} from './types'
|
||||
|
||||
export function queryAlertPluginInstanceListPaging(params: ListReq): any {
|
||||
|
|
@ -40,6 +41,14 @@ export function createAlertPluginInstance(data: PluginInstanceReq): any {
|
|||
})
|
||||
}
|
||||
|
||||
export function testAlertPluginInstance(data: TestPluginInstanceReq): any {
|
||||
return axios({
|
||||
url: '/alert-plugin-instances/test-send',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function verifyAlertInstanceName(params: InstanceNameReq): any {
|
||||
return axios({
|
||||
url: '/alert-plugin-instances/verify-name',
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ interface PluginInstanceReq {
|
|||
pluginInstanceParams: string
|
||||
}
|
||||
|
||||
interface TestPluginInstanceReq {
|
||||
pluginDefineId: number
|
||||
pluginInstanceParams: string
|
||||
}
|
||||
|
||||
interface InstanceNameReq {
|
||||
alertInstanceName: string
|
||||
}
|
||||
|
|
@ -58,5 +63,6 @@ export {
|
|||
InstanceNameReq,
|
||||
IdReq,
|
||||
UpdatePluginInstanceReq,
|
||||
AlertPluginItem
|
||||
AlertPluginItem,
|
||||
TestPluginInstanceReq
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,15 @@ import {
|
|||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import { NSelect, NInput, NSwitch, NRadioGroup, NSpace, NRadio } from 'naive-ui'
|
||||
import {
|
||||
NSelect,
|
||||
NInput,
|
||||
NSwitch,
|
||||
NRadioGroup,
|
||||
NSpace,
|
||||
NRadio,
|
||||
NButton
|
||||
} from 'naive-ui'
|
||||
import { isFunction } from 'lodash'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useForm } from './use-form'
|
||||
|
|
@ -69,7 +77,7 @@ const DetailModal = defineComponent({
|
|||
changePlugin
|
||||
} = useForm()
|
||||
|
||||
const { status, createOrUpdate } = useDetail(getFormValues)
|
||||
const { status, createOrUpdate, testSend } = useDetail(getFormValues)
|
||||
|
||||
const onCancel = () => {
|
||||
resetForm()
|
||||
|
|
@ -86,6 +94,11 @@ const DetailModal = defineComponent({
|
|||
ctx.emit('update')
|
||||
}
|
||||
}
|
||||
const onTest = async () => {
|
||||
await state.detailFormRef.validate()
|
||||
testSend(state.json)
|
||||
}
|
||||
|
||||
const onChangePlugin = changePlugin
|
||||
|
||||
const trim = getCurrentInstance()?.appContext.config.globalProperties.trim
|
||||
|
|
@ -98,7 +111,9 @@ const DetailModal = defineComponent({
|
|||
)
|
||||
watch(
|
||||
() => state.detailForm.instanceType,
|
||||
() => warningTypeSpan.value = state.detailForm.instanceType === 'GLOBAL' ? 0 : 24
|
||||
() =>
|
||||
(warningTypeSpan.value =
|
||||
state.detailForm.instanceType === 'GLOBAL' ? 0 : 24)
|
||||
)
|
||||
watch(
|
||||
() => state.json,
|
||||
|
|
@ -131,6 +146,7 @@ const DetailModal = defineComponent({
|
|||
elements,
|
||||
onChangePlugin,
|
||||
onSubmit,
|
||||
onTest,
|
||||
onCancel,
|
||||
trim
|
||||
}
|
||||
|
|
@ -150,7 +166,9 @@ const DetailModal = defineComponent({
|
|||
saving,
|
||||
onChangePlugin,
|
||||
onCancel,
|
||||
onSubmit
|
||||
onSubmit,
|
||||
onTest,
|
||||
testing
|
||||
} = this
|
||||
const { currentRecord } = props
|
||||
return (
|
||||
|
|
@ -195,11 +213,11 @@ const DetailModal = defineComponent({
|
|||
label: t('security.alarm_instance.is_global_instance'),
|
||||
widget: (
|
||||
<NSwitch
|
||||
checkedValue={'GLOBAL'}
|
||||
uncheckedValue={'NORMAL'}
|
||||
disabled={!!currentRecord?.id}
|
||||
v-model:value={detailForm.instanceType}
|
||||
/>
|
||||
checkedValue={'GLOBAL'}
|
||||
uncheckedValue={'NORMAL'}
|
||||
disabled={!!currentRecord?.id}
|
||||
v-model:value={detailForm.instanceType}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
|
|
@ -208,18 +226,12 @@ const DetailModal = defineComponent({
|
|||
span: warningTypeSpan,
|
||||
widget: (
|
||||
<NRadioGroup v-model:value={detailForm.warningType}>
|
||||
<NSpace>
|
||||
<NRadio value={'SUCCESS'}>
|
||||
{"success"}
|
||||
</NRadio>
|
||||
<NRadio value={'FAILURE'} >
|
||||
{"failure"}
|
||||
</NRadio>
|
||||
<NRadio value={'ALL'} >
|
||||
{"all"}
|
||||
</NRadio>
|
||||
</NSpace>
|
||||
</NRadioGroup>
|
||||
<NSpace>
|
||||
<NRadio value={'SUCCESS'}>{'success'}</NRadio>
|
||||
<NRadio value={'FAILURE'}>{'failure'}</NRadio>
|
||||
<NRadio value={'ALL'}>{'all'}</NRadio>
|
||||
</NSpace>
|
||||
</NRadioGroup>
|
||||
)
|
||||
},
|
||||
{
|
||||
|
|
@ -244,6 +256,18 @@ const DetailModal = defineComponent({
|
|||
cols: 24
|
||||
}}
|
||||
/>
|
||||
),
|
||||
|
||||
'btn-middle': () => (
|
||||
<NButton
|
||||
class='btn-test-send'
|
||||
type='primary'
|
||||
size='small'
|
||||
onClick={onTest}
|
||||
loading={testing || loading}
|
||||
>
|
||||
{t('security.alarm_instance.test_send')}
|
||||
</NButton>
|
||||
)
|
||||
}}
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -19,14 +19,19 @@ import { reactive } from 'vue'
|
|||
import { isFunction } from 'lodash'
|
||||
import {
|
||||
createAlertPluginInstance,
|
||||
testAlertPluginInstance,
|
||||
updateAlertPluginInstance,
|
||||
verifyAlertInstanceName
|
||||
} from '@/service/modules/alert-plugin'
|
||||
import type { IJsonItem, IRecord } from './types'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
export function useDetail(getFormValues: Function) {
|
||||
const { t } = useI18n()
|
||||
|
||||
const status = reactive({
|
||||
saving: false,
|
||||
testing: false,
|
||||
loading: false
|
||||
})
|
||||
|
||||
|
|
@ -41,6 +46,26 @@ export function useDetail(getFormValues: Function) {
|
|||
return JSON.stringify(json)
|
||||
}
|
||||
|
||||
const testSend = async (json?: IJsonItem[]) => {
|
||||
const values = getFormValues()
|
||||
|
||||
if (status.testing) return
|
||||
status.testing = true
|
||||
try {
|
||||
const res = await testAlertPluginInstance({
|
||||
pluginDefineId: values.pluginDefineId,
|
||||
pluginInstanceParams: formatParams(json, values)
|
||||
})
|
||||
window.$message.success(
|
||||
res
|
||||
? res.msg
|
||||
: `${t('security.alarm_instance.test_send')} ${t('home.success')}`
|
||||
)
|
||||
} finally {
|
||||
status.testing = false
|
||||
}
|
||||
}
|
||||
|
||||
const createOrUpdate = async (currentRecord: IRecord, json?: IJsonItem[]) => {
|
||||
const values = getFormValues()
|
||||
if (status.saving) return false
|
||||
|
|
@ -79,5 +104,5 @@ export function useDetail(getFormValues: Function) {
|
|||
}
|
||||
}
|
||||
|
||||
return { status, createOrUpdate }
|
||||
return { status, createOrUpdate, testSend }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue