From c0ed68121d771dd126d279c2bcb9b00709f1a7a1 Mon Sep 17 00:00:00 2001 From: Wei Xiaonan <33857431+weixiaonan1@users.noreply.github.com> Date: Sun, 29 Oct 2023 20:28:05 +0800 Subject: [PATCH] [Feature-14832][Listener]Implementation of Listener Mechanism (#14981) * first commit * 1. sql: sync ddl 2. front-end: change to ternary expression 3. back-end: correct license header in ListenerEvent.java * test case * frontend: remove unnecessary console * fix unit test * remove log depends on user-provided value * fix dolphinscheduler_postgresql.sql * sync database schema * fix unit test * fix unit test * fix some NIT. * extract GLOBAL_ALERT_GROUP_ID into variable * fix ddl bug * add column task_type in t_ds_fav_task in upgrade/3.2.0_schema * add unit test --- .../dolphinscheduler/alert/AlertServer.java | 5 + .../alert/plugin/AlertPluginManager.java | 19 -- .../service/ListenerEventPostService.java | 263 +++++++++++++++++ .../src/main/resources/application.yaml | 1 + .../runner/ListenerEventPostServiceTest.java | 154 ++++++++++ .../api/controller/AlertGroupController.java | 16 + .../AlertPluginInstanceController.java | 10 +- .../dolphinscheduler/api/enums/Status.java | 1 + .../api/service/AlertGroupService.java | 8 + .../service/AlertPluginInstanceService.java | 8 +- .../service/impl/AlertGroupServiceImpl.java | 30 +- .../impl/AlertPluginInstanceServiceImpl.java | 58 +++- .../impl/ProcessDefinitionServiceImpl.java | 21 +- .../api/vo/AlertPluginInstanceVO.java | 10 + .../controller/AlertGroupControllerTest.java | 46 +++ .../AlertPluginInstanceControllerTest.java | 11 +- .../api/service/AlertGroupServiceTest.java | 76 +++-- .../AlertPluginInstanceServiceTest.java | 62 ++-- .../service/ProcessDefinitionServiceTest.java | 4 + .../common/enums/AlertPluginInstanceType.java | 43 +++ .../common/enums/ListenerEventType.java | 66 +++++ .../common/enums/WarningType.java | 4 +- .../common/enums/ListenerEventTypeTest.java | 43 +++ .../apache/dolphinscheduler/dao/AlertDao.java | 3 +- .../dao/entity/AlertPluginInstance.java | 19 +- .../dao/entity/ListenerEvent.java | 88 ++++++ .../entity/event/AbstractListenerEvent.java | 27 ++ ...ProcessDefinitionCreatedListenerEvent.java | 195 ++++++++++++ ...ProcessDefinitionDeletedListenerEvent.java | 52 ++++ ...ProcessDefinitionUpdatedListenerEvent.java | 195 ++++++++++++ .../entity/event/ProcessEndListenerEvent.java | 59 ++++ .../event/ProcessFailListenerEvent.java | 59 ++++ .../event/ProcessStartListenerEvent.java | 58 ++++ .../entity/event/ServerDownListenerEvent.java | 45 +++ .../entity/event/TaskEndListenerEvent.java | 59 ++++ .../entity/event/TaskFailListenerEvent.java | 59 ++++ .../entity/event/TaskStartListenerEvent.java | 59 ++++ .../dao/mapper/AlertPluginInstanceMapper.java | 7 + .../dao/mapper/ListenerEventMapper.java | 42 +++ .../dao/mapper/AlertPluginInstanceMapper.xml | 10 +- .../dao/mapper/ListenerEventMapper.xml | 66 +++++ .../resources/sql/dolphinscheduler_h2.sql | 25 ++ .../resources/sql/dolphinscheduler_mysql.sql | 22 ++ .../sql/dolphinscheduler_postgresql.sql | 26 +- .../mysql/dolphinscheduler_ddl.sql | 7 + .../mysql/dolphinscheduler_ddl.sql | 20 ++ .../mysql/dolphinscheduler_dml.sql | 2 + .../postgresql/dolphinscheduler_ddl.sql | 10 + .../postgresql/dolphinscheduler_dml.sql | 2 + ...essDefinitionCreatedListenerEventTest.java | 48 +++ ...essDefinitionUpdatedListenerEventTest.java | 48 +++ .../mapper/AlertPluginInstanceMapperTest.java | 55 +++- .../dao/mapper/ListenerEventMapperTest.java | 134 +++++++++ .../master/event/TaskStateEventHandler.java | 4 + .../master/registry/ServerNodeManager.java | 6 + .../runner/WorkflowExecuteRunnable.java | 28 +- .../WorkflowExecuteRunnableFactory.java | 7 +- .../runner/WorkflowExecuteRunnableTest.java | 7 +- .../alert/ListenerEventAlertManager.java | 278 ++++++++++++++++++ .../alert/ListenerEventAlertManagerTest.java | 148 ++++++++++ .../src/main/resources/application.yaml | 1 + .../src/locales/en_US/security.ts | 2 + .../src/locales/zh_CN/security.ts | 2 + .../src/service/modules/alert-group/index.ts | 7 + .../src/service/modules/alert-plugin/types.ts | 3 + .../preference/components/use-alert-group.ts | 4 +- .../components/node/fields/use-sql-type.ts | 4 +- .../task/definition/components/use-start.tsx | 4 +- .../components/dag/dag-startup-param.tsx | 4 +- .../definition/components/use-modal.ts | 4 +- .../security/alarm-instance-manage/detail.tsx | 41 ++- .../security/alarm-instance-manage/types.ts | 2 + .../alarm-instance-manage/use-columns.ts | 4 + .../alarm-instance-manage/use-detail.ts | 3 + .../alarm-instance-manage/use-form.ts | 8 +- 75 files changed, 2929 insertions(+), 102 deletions(-) create mode 100644 dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/service/ListenerEventPostService.java create mode 100644 dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/ListenerEventPostServiceTest.java create mode 100644 dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AlertPluginInstanceType.java create mode 100644 dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ListenerEventType.java create mode 100644 dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/enums/ListenerEventTypeTest.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/AbstractListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionCreatedListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionDeletedListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionUpdatedListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessEndListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessFailListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessStartListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ServerDownListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskEndListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskFailListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskStartListenerEvent.java create mode 100644 dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapper.java create mode 100644 dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapper.xml create mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionCreatedListenerEventTest.java create mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionUpdatedListenerEventTest.java create mode 100644 dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapperTest.java create mode 100644 dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManager.java create mode 100644 dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManagerTest.java diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java index f95e71a10c..aeb2baf7a2 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/AlertServer.java @@ -21,6 +21,7 @@ import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; import org.apache.dolphinscheduler.alert.registry.AlertRegistryClient; import org.apache.dolphinscheduler.alert.rpc.AlertRpcServer; import org.apache.dolphinscheduler.alert.service.AlertBootstrapService; +import org.apache.dolphinscheduler.alert.service.ListenerEventPostService; import org.apache.dolphinscheduler.common.constants.Constants; import org.apache.dolphinscheduler.common.lifecycle.ServerLifeCycleManager; import org.apache.dolphinscheduler.common.thread.ThreadUtils; @@ -44,6 +45,8 @@ public class AlertServer { @Autowired private AlertBootstrapService alertBootstrapService; @Autowired + private ListenerEventPostService listenerEventPostService; + @Autowired private AlertRpcServer alertRpcServer; @Autowired private AlertPluginManager alertPluginManager; @@ -61,6 +64,7 @@ public class AlertServer { alertPluginManager.start(); alertRegistryClient.start(); alertBootstrapService.start(); + listenerEventPostService.start(); alertRpcServer.start(); log.info("Alert server is started ..."); } @@ -88,6 +92,7 @@ public class AlertServer { try ( AlertRpcServer closedAlertRpcServer = alertRpcServer; AlertBootstrapService closedAlertBootstrapService = alertBootstrapService; + ListenerEventPostService closedListenerEventPostService = listenerEventPostService; AlertRegistryClient closedAlertRegistryClient = alertRegistryClient) { // close resource } diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java index 81ebbe0ac4..b52804643d 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java +++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/plugin/AlertPluginManager.java @@ -19,16 +19,11 @@ package org.apache.dolphinscheduler.alert.plugin; import org.apache.dolphinscheduler.alert.api.AlertChannel; import org.apache.dolphinscheduler.alert.api.AlertChannelFactory; -import org.apache.dolphinscheduler.alert.api.AlertConstants; import org.apache.dolphinscheduler.common.enums.PluginType; -import org.apache.dolphinscheduler.common.enums.WarningType; import org.apache.dolphinscheduler.dao.PluginDao; import org.apache.dolphinscheduler.dao.entity.PluginDefine; import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; -import org.apache.dolphinscheduler.spi.params.base.ParamsOptions; import org.apache.dolphinscheduler.spi.params.base.PluginParams; -import org.apache.dolphinscheduler.spi.params.base.Validate; -import org.apache.dolphinscheduler.spi.params.radio.RadioParam; import org.apache.dolphinscheduler.spi.plugin.PrioritySPIFactory; import java.util.ArrayList; @@ -76,8 +71,6 @@ public final class AlertPluginManager { } private void installAlertPlugin() { - final PluginParams warningTypeParams = getWarningTypeParams(); - PrioritySPIFactory prioritySPIFactory = new PrioritySPIFactory<>(AlertChannelFactory.class); for (Map.Entry entry : prioritySPIFactory.getSPIMap().entrySet()) { @@ -91,7 +84,6 @@ public final class AlertPluginManager { log.info("Registered alert plugin: {} - {}", name, factory.getClass()); final List params = new ArrayList<>(factory.params()); - params.add(0, warningTypeParams); final String paramsJson = PluginParamsTransfer.transferParamsToJson(params); @@ -102,15 +94,4 @@ public final class AlertPluginManager { } } - private PluginParams getWarningTypeParams() { - return RadioParam.newBuilder(AlertConstants.NAME_WARNING_TYPE, AlertConstants.WARNING_TYPE) - .addParamsOptions( - new ParamsOptions(WarningType.SUCCESS.getDescp(), WarningType.SUCCESS.getDescp(), false)) - .addParamsOptions( - new ParamsOptions(WarningType.FAILURE.getDescp(), WarningType.FAILURE.getDescp(), false)) - .addParamsOptions(new ParamsOptions(WarningType.ALL.getDescp(), WarningType.ALL.getDescp(), false)) - .setValue(WarningType.ALL.getDescp()) - .addValidate(Validate.newBuilder().setRequired(true).build()) - .build(); - } } diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/service/ListenerEventPostService.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/service/ListenerEventPostService.java new file mode 100644 index 0000000000..e3a1bdefee --- /dev/null +++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/java/org/apache/dolphinscheduler/alert/service/ListenerEventPostService.java @@ -0,0 +1,263 @@ +/* + * 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.alert.service; + +import org.apache.dolphinscheduler.alert.api.AlertChannel; +import org.apache.dolphinscheduler.alert.api.AlertData; +import org.apache.dolphinscheduler.alert.api.AlertInfo; +import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.config.AlertConfig; +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.common.constants.Constants; +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.enums.AlertType; +import org.apache.dolphinscheduler.common.enums.WarningType; +import org.apache.dolphinscheduler.common.lifecycle.ServerLifeCycleManager; +import org.apache.dolphinscheduler.common.thread.BaseDaemonThread; +import org.apache.dolphinscheduler.common.thread.ThreadUtils; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.AlertSendStatus; +import org.apache.dolphinscheduler.dao.entity.ListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.AbstractListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionCreatedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionDeletedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionUpdatedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessEndListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessFailListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessStartListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ServerDownListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskEndListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskFailListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskStartListenerEvent; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; +import org.apache.dolphinscheduler.dao.mapper.ListenerEventMapper; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.curator.shaded.com.google.common.collect.Lists; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nullable; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public final class ListenerEventPostService extends BaseDaemonThread implements AutoCloseable { + + @Value("${alert.query_alert_threshold:100}") + private Integer QUERY_ALERT_THRESHOLD; + @Autowired + private ListenerEventMapper listenerEventMapper; + @Autowired + private AlertPluginInstanceMapper alertPluginInstanceMapper; + @Autowired + private AlertPluginManager alertPluginManager; + @Autowired + private AlertConfig alertConfig; + + public ListenerEventPostService() { + super("ListenerEventPostService"); + } + + @Override + public void run() { + log.info("listener event post thread started"); + while (!ServerLifeCycleManager.isStopped()) { + try { + List listenerEvents = listenerEventMapper + .listingListenerEventByStatus(AlertStatus.WAIT_EXECUTION, QUERY_ALERT_THRESHOLD); + if (CollectionUtils.isEmpty(listenerEvents)) { + log.debug("There is no waiting listener events"); + continue; + } + this.send(listenerEvents); + } catch (Exception e) { + log.error("listener event post thread meet an exception", e); + } finally { + ThreadUtils.sleep(Constants.SLEEP_TIME_MILLIS * 5L); + } + } + log.info("listener event post thread stopped"); + } + + public void send(List listenerEvents) { + for (ListenerEvent listenerEvent : listenerEvents) { + int eventId = listenerEvent.getId(); + List globalAlertInstanceList = + alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + if (CollectionUtils.isEmpty(globalAlertInstanceList)) { + log.error("post listener event fail,no bind global plugin instance."); + listenerEventMapper.updateListenerEvent(eventId, AlertStatus.EXECUTION_FAILURE, + "no bind plugin instance", new Date()); + continue; + } + AbstractListenerEvent event = generateEventFromContent(listenerEvent); + if (event == null) { + log.error("parse listener event to abstract listener event fail.ed {}", listenerEvent.getContent()); + listenerEventMapper.updateListenerEvent(eventId, AlertStatus.EXECUTION_FAILURE, + "parse listener event to abstract listener event failed", new Date()); + continue; + } + List events = Lists.newArrayList(event); + AlertData alertData = AlertData.builder() + .id(eventId) + .content(JSONUtils.toJsonString(events)) + .log(listenerEvent.getLog()) + .title(event.getTitle()) + .warnType(WarningType.GLOBAL.getCode()) + .alertType(event.getEventType().getCode()) + .build(); + + int sendSuccessCount = 0; + List failedPostResults = new ArrayList<>(); + for (AlertPluginInstance instance : globalAlertInstanceList) { + AlertResult alertResult = this.alertResultHandler(instance, alertData); + if (alertResult != null) { + AlertStatus sendStatus = Boolean.parseBoolean(alertResult.getStatus()) + ? AlertStatus.EXECUTION_SUCCESS + : AlertStatus.EXECUTION_FAILURE; + if (AlertStatus.EXECUTION_SUCCESS.equals(sendStatus)) { + sendSuccessCount++; + } else { + AlertSendStatus alertSendStatus = AlertSendStatus.builder() + .alertId(eventId) + .alertPluginInstanceId(instance.getId()) + .sendStatus(sendStatus) + .log(JSONUtils.toJsonString(alertResult)) + .createTime(new Date()) + .build(); + failedPostResults.add(alertSendStatus); + } + } + } + if (sendSuccessCount == globalAlertInstanceList.size()) { + listenerEventMapper.deleteById(eventId); + } else { + AlertStatus alertStatus = + sendSuccessCount == 0 ? AlertStatus.EXECUTION_FAILURE : AlertStatus.EXECUTION_PARTIAL_SUCCESS; + listenerEventMapper.updateListenerEvent(eventId, alertStatus, JSONUtils.toJsonString(failedPostResults), + new Date()); + } + } + } + + /** + * alert result handler + * + * @param instance instance + * @param alertData alertData + * @return AlertResult + */ + private @Nullable AlertResult alertResultHandler(AlertPluginInstance instance, AlertData alertData) { + String pluginInstanceName = instance.getInstanceName(); + int pluginDefineId = instance.getPluginDefineId(); + Optional alertChannelOptional = alertPluginManager.getAlertChannel(instance.getPluginDefineId()); + if (!alertChannelOptional.isPresent()) { + String message = + String.format("Global Alert Plugin %s send error: the channel doesn't exist, pluginDefineId: %s", + pluginInstanceName, + pluginDefineId); + log.error("Global Alert Plugin {} send error : not found plugin {}", pluginInstanceName, pluginDefineId); + return new AlertResult("false", message); + } + AlertChannel alertChannel = alertChannelOptional.get(); + + Map paramsMap = JSONUtils.toMap(instance.getPluginInstanceParams()); + + AlertInfo alertInfo = AlertInfo.builder() + .alertData(alertData) + .alertParams(paramsMap) + .alertPluginInstanceId(instance.getId()) + .build(); + int waitTimeout = alertConfig.getWaitTimeout(); + try { + AlertResult alertResult; + if (waitTimeout <= 0) { + if (alertData.getAlertType() == AlertType.CLOSE_ALERT.getCode()) { + alertResult = alertChannel.closeAlert(alertInfo); + } else { + alertResult = alertChannel.process(alertInfo); + } + } else { + CompletableFuture future; + if (alertData.getAlertType() == AlertType.CLOSE_ALERT.getCode()) { + future = CompletableFuture.supplyAsync(() -> alertChannel.closeAlert(alertInfo)); + } else { + future = CompletableFuture.supplyAsync(() -> alertChannel.process(alertInfo)); + } + alertResult = future.get(waitTimeout, TimeUnit.MILLISECONDS); + } + if (alertResult == null) { + throw new RuntimeException("Alert result cannot be null"); + } + return alertResult; + } catch (InterruptedException e) { + log.error("post listener event error alert data id :{},", alertData.getId(), e); + Thread.currentThread().interrupt(); + return new AlertResult("false", e.getMessage()); + } catch (Exception e) { + log.error("post listener event error alert data id :{},", alertData.getId(), e); + return new AlertResult("false", e.getMessage()); + } + } + + private AbstractListenerEvent generateEventFromContent(ListenerEvent listenerEvent) { + String content = listenerEvent.getContent(); + switch (listenerEvent.getEventType()) { + case SERVER_DOWN: + return JSONUtils.parseObject(content, ServerDownListenerEvent.class); + case PROCESS_DEFINITION_CREATED: + return JSONUtils.parseObject(content, ProcessDefinitionCreatedListenerEvent.class); + case PROCESS_DEFINITION_UPDATED: + return JSONUtils.parseObject(content, ProcessDefinitionUpdatedListenerEvent.class); + case PROCESS_DEFINITION_DELETED: + return JSONUtils.parseObject(content, ProcessDefinitionDeletedListenerEvent.class); + case PROCESS_START: + return JSONUtils.parseObject(content, ProcessStartListenerEvent.class); + case PROCESS_END: + return JSONUtils.parseObject(content, ProcessEndListenerEvent.class); + case PROCESS_FAIL: + return JSONUtils.parseObject(content, ProcessFailListenerEvent.class); + case TASK_START: + return JSONUtils.parseObject(content, TaskStartListenerEvent.class); + case TASK_END: + return JSONUtils.parseObject(content, TaskEndListenerEvent.class); + case TASK_FAIL: + return JSONUtils.parseObject(content, TaskFailListenerEvent.class); + default: + return null; + } + } + @Override + public void close() { + log.info("Closed ListenerEventPostService..."); + } + +} diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/application.yaml b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/application.yaml index e9d2554832..2d95552737 100644 --- a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/application.yaml +++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/main/resources/application.yaml @@ -81,6 +81,7 @@ alert: # Define value is (0 = infinite), and alert server would be waiting alert result. wait-timeout: 0 heartbeat-interval: 60s + query_alert_threshold: 100 registry: type: zookeeper diff --git a/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/ListenerEventPostServiceTest.java b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/ListenerEventPostServiceTest.java new file mode 100644 index 0000000000..33917267f0 --- /dev/null +++ b/dolphinscheduler-alert/dolphinscheduler-alert-server/src/test/java/org/apache/dolphinscheduler/alert/runner/ListenerEventPostServiceTest.java @@ -0,0 +1,154 @@ +/* + * 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.alert.runner; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.dolphinscheduler.alert.api.AlertChannel; +import org.apache.dolphinscheduler.alert.api.AlertResult; +import org.apache.dolphinscheduler.alert.config.AlertConfig; +import org.apache.dolphinscheduler.alert.plugin.AlertPluginManager; +import org.apache.dolphinscheduler.alert.service.ListenerEventPostService; +import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType; +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.ListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ServerDownListenerEvent; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; +import org.apache.dolphinscheduler.dao.mapper.ListenerEventMapper; + +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ListenerEventPostServiceTest { + + private static final Logger logger = LoggerFactory.getLogger(ListenerEventPostServiceTest.class); + + @Mock + private ListenerEventMapper listenerEventMapper; + @Mock + private AlertPluginInstanceMapper alertPluginInstanceMapper; + @Mock + private AlertPluginManager alertPluginManager; + @Mock + private AlertConfig alertConfig; + + @InjectMocks + private ListenerEventPostService listenerEventPostService; + + @BeforeEach + public void before() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testSendServerDownEventSuccess() { + List events = new ArrayList<>(); + ServerDownListenerEvent serverDownListenerEvent = new ServerDownListenerEvent(); + serverDownListenerEvent.setEventTime(new Date()); + serverDownListenerEvent.setType("WORKER"); + serverDownListenerEvent.setHost("192.168.*.*"); + ListenerEvent successEvent = new ListenerEvent(); + successEvent.setId(1); + successEvent.setPostStatus(AlertStatus.WAIT_EXECUTION); + successEvent.setContent(JSONUtils.toJsonString(serverDownListenerEvent)); + successEvent.setSign(DigestUtils.sha256Hex(successEvent.getContent())); + successEvent.setEventType(ListenerEventType.SERVER_DOWN); + successEvent.setCreateTime(new Date()); + successEvent.setUpdateTime(new Date()); + events.add(successEvent); + + int pluginDefineId = 1; + String pluginInstanceParams = + "{\"User\":\"xx\",\"receivers\":\"xx\",\"sender\":\"xx\",\"smtpSslTrust\":\"*\",\"enableSmtpAuth\":\"true\",\"receiverCcs\":null,\"showType\":\"table\",\"starttlsEnable\":\"false\",\"serverPort\":\"25\",\"serverHost\":\"xx\",\"Password\":\"xx\",\"sslEnable\":\"false\"}"; + String pluginInstanceName = "alert-instance-mail"; + List alertInstanceList = new ArrayList<>(); + AlertPluginInstance alertPluginInstance = new AlertPluginInstance( + pluginDefineId, pluginInstanceParams, pluginInstanceName); + alertPluginInstance.setInstanceType(AlertPluginInstanceType.GLOBAL); + alertPluginInstance.setId(1); + alertInstanceList.add(alertPluginInstance); + when(alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList()).thenReturn(alertInstanceList); + + AlertResult sendResult = new AlertResult(); + sendResult.setStatus(String.valueOf(true)); + sendResult.setMessage(String.format("Alert Plugin %s send success", pluginInstanceName)); + AlertChannel alertChannelMock = mock(AlertChannel.class); + when(alertChannelMock.process(Mockito.any())).thenReturn(sendResult); + when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock)); + Assertions.assertTrue(Boolean.parseBoolean(sendResult.getStatus())); + when(listenerEventMapper.deleteById(1)).thenReturn(1); + listenerEventPostService.send(events); + } + + @Test + public void testSendServerDownEventFailed() { + List events = new ArrayList<>(); + ServerDownListenerEvent serverDownListenerEvent = new ServerDownListenerEvent(); + serverDownListenerEvent.setEventTime(new Date()); + serverDownListenerEvent.setType("WORKER"); + serverDownListenerEvent.setHost("192.168.*.*"); + ListenerEvent successEvent = new ListenerEvent(); + successEvent.setId(1); + successEvent.setPostStatus(AlertStatus.WAIT_EXECUTION); + successEvent.setContent(JSONUtils.toJsonString(serverDownListenerEvent)); + successEvent.setSign(DigestUtils.sha1Hex(successEvent.getContent())); + successEvent.setEventType(ListenerEventType.SERVER_DOWN); + successEvent.setCreateTime(new Date()); + successEvent.setUpdateTime(new Date()); + events.add(successEvent); + + int pluginDefineId = 1; + String pluginInstanceParams = + "{\"User\":\"xx\",\"receivers\":\"xx\",\"sender\":\"xx\",\"smtpSslTrust\":\"*\",\"enableSmtpAuth\":\"true\",\"receiverCcs\":null,\"showType\":\"table\",\"starttlsEnable\":\"false\",\"serverPort\":\"25\",\"serverHost\":\"xx\",\"Password\":\"xx\",\"sslEnable\":\"false\"}"; + String pluginInstanceName = "alert-instance-mail"; + List alertInstanceList = new ArrayList<>(); + AlertPluginInstance alertPluginInstance = new AlertPluginInstance( + pluginDefineId, pluginInstanceParams, pluginInstanceName); + alertPluginInstance.setInstanceType(AlertPluginInstanceType.GLOBAL); + alertPluginInstance.setId(1); + alertInstanceList.add(alertPluginInstance); + when(alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList()).thenReturn(alertInstanceList); + + AlertResult sendResult = new AlertResult(); + sendResult.setStatus(String.valueOf(false)); + sendResult.setMessage(String.format("Alert Plugin %s send failed", pluginInstanceName)); + AlertChannel alertChannelMock = mock(AlertChannel.class); + when(alertChannelMock.process(Mockito.any())).thenReturn(sendResult); + when(alertPluginManager.getAlertChannel(1)).thenReturn(Optional.of(alertChannelMock)); + Assertions.assertFalse(Boolean.parseBoolean(sendResult.getStatus())); + listenerEventPostService.send(events); + } +} diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java index 86bfb6a4a1..9ac7a82db0 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertGroupController.java @@ -109,6 +109,22 @@ public class AlertGroupController extends BaseController { return returnDataList(result); } + /** + * normal alert group list + * + * @param loginUser login user + * @return normal alert group list + */ + @Operation(summary = "listNormalAlertgroupById", description = "QUERY_ALERT_GROUP_LIST_NOTES") + @GetMapping(value = "/normal-list") + @ResponseStatus(HttpStatus.OK) + @ApiException(QUERY_ALL_ALERTGROUP_ERROR) + public Result normalAlertGroupList(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser) { + + Map result = alertGroupService.queryNormalAlertgroup(loginUser); + return returnDataList(result); + } + /** * paging query alarm group list * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java index 3ccba174a2..688f2c594c 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceController.java @@ -29,6 +29,8 @@ import org.apache.dolphinscheduler.api.exceptions.ApiException; import org.apache.dolphinscheduler.api.service.AlertPluginInstanceService; 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.WarningType; import org.apache.dolphinscheduler.dao.entity.User; import org.apache.dolphinscheduler.plugin.task.api.utils.ParameterUtils; @@ -88,9 +90,12 @@ public class AlertPluginInstanceController extends BaseController { public Result createAlertPluginInstance(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @RequestParam(value = "pluginDefineId") int pluginDefineId, @RequestParam(value = "instanceName") String instanceName, + @RequestParam(value = "instanceType") AlertPluginInstanceType instanceType, + @RequestParam(value = "warningType") WarningType warningType, @RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) { Map result = - alertPluginInstanceService.create(loginUser, pluginDefineId, instanceName, pluginInstanceParams); + alertPluginInstanceService.create(loginUser, pluginDefineId, instanceName, instanceType, warningType, + pluginInstanceParams); return returnDataList(result); } @@ -115,9 +120,10 @@ public class AlertPluginInstanceController extends BaseController { public Result updateAlertPluginInstance(@Parameter(hidden = true) @RequestAttribute(value = Constants.SESSION_USER) User loginUser, @PathVariable(value = "id") int id, @RequestParam(value = "instanceName") String instanceName, + @RequestParam(value = "warningType") WarningType warningType, @RequestParam(value = "pluginInstanceParams") String pluginInstanceParams) { Map result = - alertPluginInstanceService.update(loginUser, id, instanceName, pluginInstanceParams); + alertPluginInstanceService.update(loginUser, id, instanceName, warningType, pluginInstanceParams); return returnDataList(result); } diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java index 49058ad2e6..e37eca0f3f 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java @@ -539,6 +539,7 @@ public enum Status { NOT_ALLOW_TO_DISABLE_OWN_ACCOUNT(130020, "Not allow to disable your own account", "不能停用自己的账号"), NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP(130030, "Not allow to delete the default alarm group ", "不能删除默认告警组"), TIME_ZONE_ILLEGAL(130031, "time zone [{0}] is illegal", "时区参数 [{0}] 不合法"), + NOT_ALLOW_TO_UPDATE_GLOBAL_ALARM_GROUP(130032, "Not allow to update the global alert group ", "不能更新全局告警组"), QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR(1300001, "login user query k8s namespace list paging error", "分页查询k8s名称空间列表错误"), diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java index 538518b5ff..096d5c3b7b 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertGroupService.java @@ -35,6 +35,14 @@ public interface AlertGroupService { */ Map queryAlertgroup(User loginUser); + /** + * query normal alert group list + * + * @param loginUser + * @return alert group list + */ + Map queryNormalAlertgroup(User loginUser); + /** * query alert group by id * diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java index 24c7ce5100..156531f160 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceService.java @@ -18,6 +18,8 @@ package org.apache.dolphinscheduler.api.service; import org.apache.dolphinscheduler.api.utils.Result; +import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType; +import org.apache.dolphinscheduler.common.enums.WarningType; import org.apache.dolphinscheduler.dao.entity.User; import java.util.Map; @@ -36,7 +38,9 @@ public interface AlertPluginInstanceService { * @param pluginInstanceParams plugin instance params * @return result */ - Map create(User loginUser, int pluginDefineId, String instanceName, String pluginInstanceParams); + Map create(User loginUser, int pluginDefineId, String instanceName, + AlertPluginInstanceType instanceType, WarningType warningType, + String pluginInstanceParams); /** * update @@ -47,7 +51,7 @@ public interface AlertPluginInstanceService { * @return result */ Map update(User loginUser, int alertPluginInstanceId, String instanceName, - String pluginInstanceParams); + WarningType warningType, String pluginInstanceParams); /** * delete alert plugin instance diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertGroupServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertGroupServiceImpl.java index 82c5cd1e69..5f04caaaac 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertGroupServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertGroupServiceImpl.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -90,6 +91,28 @@ public class AlertGroupServiceImpl extends BaseServiceImpl implements AlertGroup return result; } + @Override + public Map queryNormalAlertgroup(User loginUser) { + HashMap result = new HashMap<>(); + List alertGroups; + if (loginUser.getUserType().equals(UserType.ADMIN_USER)) { + alertGroups = alertGroupMapper.queryAllGroupList(); + } else { + Set ids = resourcePermissionCheckService + .userOwnedResourceIdsAcquisition(AuthorizationType.ALERT_GROUP, loginUser.getId(), log); + if (ids.isEmpty()) { + result.put(Constants.DATA_LIST, Collections.emptyList()); + putMsg(result, Status.SUCCESS); + return result; + } + alertGroups = alertGroupMapper.selectBatchIds(ids); + } + alertGroups = alertGroups.stream().filter(alertGroup -> alertGroup.getId() != 2).collect(Collectors.toList()); + result.put(Constants.DATA_LIST, alertGroups); + putMsg(result, Status.SUCCESS); + return result; + } + /** * query alert group by id * @@ -223,6 +246,11 @@ public class AlertGroupServiceImpl extends BaseServiceImpl implements AlertGroup public Map updateAlertgroup(User loginUser, int id, String groupName, String desc, String alertInstanceIds) { Map result = new HashMap<>(); + // don't allow to update global alert group + if (id == 2) { + putMsg(result, Status.NOT_ALLOW_TO_UPDATE_GLOBAL_ALARM_GROUP); + return result; + } if (!canOperatorPermissions(loginUser, new Object[]{id}, AuthorizationType.ALERT_GROUP, ALERT_GROUP_UPDATE)) { putMsg(result, Status.USER_NO_OPERATION_PERM); @@ -282,7 +310,7 @@ public class AlertGroupServiceImpl extends BaseServiceImpl implements AlertGroup } // Not allow to delete the default alarm group ,because the module of service need to use it. - if (id == 1) { + if (id == 1 || id == 2) { log.warn("Not allow to delete the default alarm group."); putMsg(result, Status.NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP); return result; diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java index 8a77821453..fffb95fbcf 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/AlertPluginInstanceServiceImpl.java @@ -28,8 +28,11 @@ import org.apache.dolphinscheduler.api.utils.PageInfo; import org.apache.dolphinscheduler.api.utils.Result; import org.apache.dolphinscheduler.api.vo.AlertPluginInstanceVO; 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.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.entity.AlertGroup; import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; import org.apache.dolphinscheduler.dao.entity.PluginDefine; import org.apache.dolphinscheduler.dao.entity.User; @@ -39,6 +42,7 @@ import org.apache.dolphinscheduler.dao.mapper.PluginDefineMapper; import org.apache.dolphinscheduler.spi.params.PluginParamsTransfer; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Arrays; @@ -76,6 +80,8 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A @Autowired private AlertGroupMapper alertGroupMapper; + private final Integer GLOBAL_ALERT_GROUP_ID = 2; + /** * creat alert plugin instance * @@ -86,12 +92,15 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A */ @Override public Map create(User loginUser, int pluginDefineId, String instanceName, + AlertPluginInstanceType instanceType, WarningType warningType, String pluginInstanceParams) { AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); String paramsMapJson = parsePluginParamsMap(pluginInstanceParams); alertPluginInstance.setPluginInstanceParams(paramsMapJson); alertPluginInstance.setInstanceName(instanceName); alertPluginInstance.setPluginDefineId(pluginDefineId); + alertPluginInstance.setInstanceType(instanceType); + alertPluginInstance.setWarningType(warningType); Map result = new HashMap<>(); if (!canOperatorPermissions(loginUser, null, AuthorizationType.ALERT_PLUGIN_INSTANCE, ALART_INSTANCE_CREATE)) { @@ -108,6 +117,20 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A int i = alertPluginInstanceMapper.insert(alertPluginInstance); if (i > 0) { log.info("Create alert plugin instance complete, name:{}", alertPluginInstance.getInstanceName()); + // global instance will be added into global alert group automatically + if (instanceType == AlertPluginInstanceType.GLOBAL) { + AlertGroup globalAlertGroup = alertGroupMapper.selectById(GLOBAL_ALERT_GROUP_ID); + if (StringUtils.isEmpty(globalAlertGroup.getAlertInstanceIds())) { + globalAlertGroup.setAlertInstanceIds(String.valueOf(alertPluginInstance.getId())); + } else { + List ids = Arrays.stream(globalAlertGroup.getAlertInstanceIds().split(",")) + .map(s -> Integer.parseInt(s.trim())) + .collect(Collectors.toList()); + ids.add(alertPluginInstance.getId()); + globalAlertGroup.setAlertInstanceIds(StringUtils.join(ids, ",")); + } + alertGroupMapper.updateById(globalAlertGroup); + } result.put(Constants.DATA_LIST, alertPluginInstance); putMsg(result, Status.SUCCESS); return result; @@ -127,11 +150,11 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A */ @Override public Map update(User loginUser, int pluginInstanceId, String instanceName, - String pluginInstanceParams) { + WarningType warningType, String pluginInstanceParams) { String paramsMapJson = parsePluginParamsMap(pluginInstanceParams); AlertPluginInstance alertPluginInstance = - new AlertPluginInstance(pluginInstanceId, paramsMapJson, instanceName, new Date()); + new AlertPluginInstance(pluginInstanceId, paramsMapJson, instanceName, warningType, new Date()); Map result = new HashMap<>(); @@ -163,12 +186,26 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A @Override public Map delete(User loginUser, int id) { Map result = new HashMap<>(); - // check if there is an associated alert group - boolean hasAssociatedAlertGroup = checkHasAssociatedAlertGroup(String.valueOf(id)); - if (hasAssociatedAlertGroup) { - log.warn("Delete alert plugin failed because alert group is using it, pluginId:{}.", id); - putMsg(result, Status.DELETE_ALERT_PLUGIN_INSTANCE_ERROR_HAS_ALERT_GROUP_ASSOCIATED); - return result; + AlertPluginInstance alertPluginInstance = alertPluginInstanceMapper.selectById(id); + if (alertPluginInstance.getInstanceType() == AlertPluginInstanceType.GLOBAL) { + // global instance will be removed from global alert group automatically + AlertGroup globalAlertGroup = alertGroupMapper.selectById(GLOBAL_ALERT_GROUP_ID); + List ids = Arrays.stream(globalAlertGroup.getAlertInstanceIds().split(",")) + .map(s -> Integer.parseInt(s.trim())) + .collect(Collectors.toList()); + ids = ids.stream().filter(x -> x != id).collect(Collectors.toList()); + globalAlertGroup.setAlertInstanceIds(StringUtils.join(ids, ",")); + alertGroupMapper.updateById(globalAlertGroup); + log.info("Remove global alert plugin instance from global alert group automatically, name:{}", + alertPluginInstance.getInstanceName()); + } else { + // check if there is an associated alert group + boolean hasAssociatedAlertGroup = checkHasAssociatedAlertGroup(String.valueOf(id)); + if (hasAssociatedAlertGroup) { + log.warn("Delete alert plugin failed because alert group is using it, pluginId:{}.", id); + putMsg(result, Status.DELETE_ALERT_PLUGIN_INSTANCE_ERROR_HAS_ALERT_GROUP_ASSOCIATED); + return result; + } } if (!canOperatorPermissions(loginUser, null, AuthorizationType.ALERT_PLUGIN_INSTANCE, ALERT_PLUGIN_DELETE)) { putMsg(result, Status.USER_NO_OPERATION_PERM); @@ -255,12 +292,15 @@ public class AlertPluginInstanceServiceImpl extends BaseServiceImpl implements A pluginDefineList.stream().collect(Collectors.toMap(PluginDefine::getId, Function.identity())); alertPluginInstances.forEach(alertPluginInstance -> { AlertPluginInstanceVO alertPluginInstanceVO = new AlertPluginInstanceVO(); - alertPluginInstanceVO.setCreateTime(alertPluginInstance.getCreateTime()); alertPluginInstanceVO.setUpdateTime(alertPluginInstance.getUpdateTime()); alertPluginInstanceVO.setPluginDefineId(alertPluginInstance.getPluginDefineId()); alertPluginInstanceVO.setInstanceName(alertPluginInstance.getInstanceName()); alertPluginInstanceVO.setId(alertPluginInstance.getId()); + alertPluginInstanceVO.setInstanceType(alertPluginInstance.getInstanceType().getDescp()); + if (alertPluginInstance.getWarningType() != null) { + alertPluginInstanceVO.setWarningType(alertPluginInstance.getWarningType().getDescp().toUpperCase()); + } PluginDefine pluginDefine = pluginDefineMap.get(alertPluginInstance.getPluginDefineId()); // FIXME When the user removes the plug-in, this will happen. At this time, maybe we should add a new field // to indicate that the plug-in has expired? diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java index d98d7b75fc..49fcf01086 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/ProcessDefinitionServiceImpl.java @@ -118,6 +118,7 @@ import org.apache.dolphinscheduler.plugin.task.api.enums.TaskTimeoutStrategy; import org.apache.dolphinscheduler.plugin.task.api.model.Property; import org.apache.dolphinscheduler.plugin.task.api.parameters.ParametersNode; import org.apache.dolphinscheduler.plugin.task.api.parameters.SqlParameters; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.dolphinscheduler.service.cron.CronUtils; import org.apache.dolphinscheduler.service.model.TaskNode; import org.apache.dolphinscheduler.service.process.ProcessService; @@ -251,6 +252,9 @@ public class ProcessDefinitionServiceImpl extends BaseServiceImpl implements Pro @Autowired private MetricsCleanUpService metricsCleanUpService; + @Autowired + private ListenerEventAlertManager listenerEventAlertManager; + /** * create process definition * @@ -306,7 +310,13 @@ public class ProcessDefinitionServiceImpl extends BaseServiceImpl implements Pro globalParams, locations, timeout, loginUser.getId()); processDefinition.setExecutionType(executionType); - return createDagDefine(loginUser, taskRelationList, processDefinition, taskDefinitionLogs, otherParamsJson); + result = createDagDefine(loginUser, taskRelationList, processDefinition, taskDefinitionLogs, otherParamsJson); + if (result.get(Constants.STATUS) == Status.SUCCESS) { + listenerEventAlertManager.publishProcessDefinitionCreatedListenerEvent(loginUser, processDefinition, + taskDefinitionLogs, + taskRelationList); + } + return result; } private void createWorkflowValid(User user, ProcessDefinition processDefinition) { @@ -805,8 +815,14 @@ public class ProcessDefinitionServiceImpl extends BaseServiceImpl implements Pro JSONUtils.parseObject(JSONUtils.toJsonString(processDefinition), ProcessDefinition.class); processDefinition.set(projectCode, name, description, globalParams, locations, timeout); processDefinition.setExecutionType(executionType); - return updateDagDefine(loginUser, taskRelationList, processDefinition, processDefinitionDeepCopy, + result = updateDagDefine(loginUser, taskRelationList, processDefinition, processDefinitionDeepCopy, taskDefinitionLogs, otherParamsJson); + if (result.get(Constants.STATUS) == Status.SUCCESS) { + listenerEventAlertManager.publishProcessDefinitionUpdatedListenerEvent(loginUser, processDefinition, + taskDefinitionLogs, + taskRelationList); + } + return result; } /** @@ -1071,6 +1087,7 @@ public class ProcessDefinitionServiceImpl extends BaseServiceImpl implements Pro processDefinitionDao.deleteByWorkflowDefinitionCode(processDefinition.getCode()); metricsCleanUpService.cleanUpWorkflowMetricsByDefinitionCode(code); log.info("Success delete workflow definition workflowDefinitionCode: {}", code); + listenerEventAlertManager.publishProcessDefinitionDeletedListenerEvent(loginUser, project, processDefinition); } /** diff --git a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java index 581ad78250..1b533350ab 100644 --- a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java +++ b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/vo/AlertPluginInstanceVO.java @@ -39,6 +39,16 @@ public class AlertPluginInstanceVO { */ private String instanceName; + /** + * alert plugin instance type + */ + private String instanceType; + + /** + * alert plugin instance warning type + */ + private String warningType; + /** * plugin_instance_params */ diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertGroupControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertGroupControllerTest.java index f0bbd09cb6..b28af9d11a 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertGroupControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertGroupControllerTest.java @@ -217,4 +217,50 @@ public class AlertGroupControllerTest extends AbstractControllerTest { Assertions.assertEquals(Status.NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP.getCode(), result.getCode().intValue()); logger.info(mvcResult.getResponse().getContentAsString()); } + + @Test + public void test100DelAlertGroupById() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + MvcResult mvcResult = mockMvc.perform(delete("/alert-groups/2") + .header("sessionId", sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assertions.assertEquals(Status.NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + + @Test + public void test110UpdateAlertGroupById() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + paramsMap.add("groupName", defaultTestAlertGroupName); + paramsMap.add("groupType", "email"); + paramsMap.add("description", "update alter group"); + paramsMap.add("alertInstanceIds", ""); + MvcResult mvcResult = mockMvc.perform(put("/alert-groups/2") + .header("sessionId", sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assertions.assertEquals(Status.NOT_ALLOW_TO_UPDATE_GLOBAL_ALARM_GROUP.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } + + @Test + public void test120QueryNormalAlertGroupList() throws Exception { + MultiValueMap paramsMap = new LinkedMultiValueMap<>(); + MvcResult mvcResult = mockMvc.perform(get("/alert-groups/normal-list") + .header("sessionId", sessionId) + .params(paramsMap)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + Result result = JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), Result.class); + Assertions.assertEquals(Status.SUCCESS.getCode(), result.getCode().intValue()); + logger.info(mvcResult.getResponse().getContentAsString()); + } } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceControllerTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceControllerTest.java index df77f558a6..870fb1f82b 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceControllerTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/AlertPluginInstanceControllerTest.java @@ -32,6 +32,8 @@ import org.apache.dolphinscheduler.api.enums.Status; import org.apache.dolphinscheduler.api.service.AlertPluginInstanceService; 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.WarningType; import org.apache.dolphinscheduler.common.utils.JSONUtils; import org.apache.dolphinscheduler.dao.entity.User; @@ -52,6 +54,8 @@ public class AlertPluginInstanceControllerTest extends AbstractControllerTest { private static final int pluginDefineId = 1; private static final String instanceName = "instanceName"; private static final String pluginInstanceParams = "pluginInstanceParams"; + private static final AlertPluginInstanceType pluginInstanceType = AlertPluginInstanceType.NORMAL; + private static final WarningType warningType = WarningType.ALL; private static final Result expectResponseContent = JSONUtils.parseObject( "{\"code\":0,\"msg\":\"success\",\"data\":\"Test Data\",\"success\":true,\"failed\":false}", Result.class); private static final ImmutableMap alertPluginInstanceServiceResult = @@ -66,10 +70,12 @@ public class AlertPluginInstanceControllerTest extends AbstractControllerTest { final MultiValueMap paramsMap = new LinkedMultiValueMap<>(); paramsMap.add("pluginDefineId", String.valueOf(pluginDefineId)); paramsMap.add("instanceName", instanceName); + paramsMap.add("instanceType", pluginInstanceType.getDescp()); + paramsMap.add("warningType", warningType.name()); paramsMap.add("pluginInstanceParams", pluginInstanceParams); when(alertPluginInstanceService.create(any(User.class), eq(pluginDefineId), eq(instanceName), - eq(pluginInstanceParams))) + eq(pluginInstanceType), eq(warningType), eq(pluginInstanceParams))) .thenReturn(alertPluginInstanceServiceResult); // When @@ -92,10 +98,11 @@ public class AlertPluginInstanceControllerTest extends AbstractControllerTest { final MultiValueMap paramsMap = new LinkedMultiValueMap<>(); paramsMap.add("pluginDefineId", String.valueOf(pluginDefineId)); paramsMap.add("instanceName", instanceName); + paramsMap.add("warningType", warningType.name()); paramsMap.add("pluginInstanceParams", pluginInstanceParams); when(alertPluginInstanceService.update(any(User.class), eq(pluginDefineId), eq(instanceName), - eq(pluginInstanceParams))) + eq(warningType), eq(pluginInstanceParams))) .thenReturn(alertPluginInstanceServiceResult); // When diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java index 4b58847280..695ee3b5a4 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertGroupServiceTest.java @@ -39,10 +39,8 @@ import org.apache.dolphinscheduler.dao.mapper.AlertGroupMapper; import org.apache.commons.collections4.CollectionUtils; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -87,13 +85,23 @@ public class AlertGroupServiceTest { Map result = alertGroupService.queryAlertgroup(getLoginUser()); logger.info(result.toString()); List alertGroups = (List) result.get(Constants.DATA_LIST); - Assertions.assertTrue(CollectionUtils.isNotEmpty(alertGroups)); + Assertions.assertEquals(alertGroups.size(), 2); + } + + @Test + public void testQueryNormalAlertGroup() { + + Mockito.when(alertGroupMapper.queryAllGroupList()).thenReturn(getList()); + Map result = alertGroupService.queryNormalAlertgroup(getLoginUser()); + logger.info(result.toString()); + List alertGroups = (List) result.get(Constants.DATA_LIST); + Assertions.assertEquals(alertGroups.size(), 1); } @Test public void testListPaging() { IPage page = new Page<>(1, 10); - page.setTotal(1L); + page.setTotal(2L); page.setRecords(getList()); Mockito.when(alertGroupMapper.queryAlertGroupPage(any(Page.class), eq(groupName))).thenReturn(page); User user = new User(); @@ -101,8 +109,6 @@ public class AlertGroupServiceTest { user.setUserType(UserType.GENERAL_USER); user.setId(88); - Set ids = new HashSet<>(); - ids.add(1); Result result = alertGroupService.listPaging(user, groupName, 1, 10); logger.info(result.toString()); Assertions.assertEquals(Status.SUCCESS.getCode(), (int) result.getCode()); @@ -119,7 +125,7 @@ public class AlertGroupServiceTest { @Test public void testCreateAlertgroup() { - Mockito.when(alertGroupMapper.insert(any(AlertGroup.class))).thenReturn(2); + Mockito.when(alertGroupMapper.insert(any(AlertGroup.class))).thenReturn(3); User user = new User(); user.setId(0); // no operate @@ -179,9 +185,9 @@ public class AlertGroupServiceTest { Assertions.assertEquals(Status.ALERT_GROUP_NOT_EXIST, result.get(Constants.STATUS)); // success Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, - new Object[]{2}, user.getId(), baseServiceLogger)).thenReturn(true); - Mockito.when(alertGroupMapper.selectById(2)).thenReturn(getEntity()); - result = alertGroupService.updateAlertgroup(user, 2, groupName, groupName, null); + new Object[]{3}, user.getId(), baseServiceLogger)).thenReturn(true); + Mockito.when(alertGroupMapper.selectById(3)).thenReturn(getEntity()); + result = alertGroupService.updateAlertgroup(user, 3, groupName, groupName, null); logger.info(result.toString()); Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); @@ -195,17 +201,28 @@ public class AlertGroupServiceTest { Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.ALERT_GROUP, user.getId(), ALERT_GROUP_UPDATE, baseServiceLogger)).thenReturn(true); Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, - new Object[]{2}, user.getId(), baseServiceLogger)).thenReturn(true); - Mockito.when(alertGroupMapper.selectById(2)).thenReturn(getEntity()); + new Object[]{3}, user.getId(), baseServiceLogger)).thenReturn(true); + Mockito.when(alertGroupMapper.selectById(3)).thenReturn(getEntity()); Mockito.when(alertGroupMapper.updateById(Mockito.any())) .thenThrow(new DuplicateKeyException("group name exist")); - Map result = alertGroupService.updateAlertgroup(user, 2, groupName, groupName, null); + Map result = alertGroupService.updateAlertgroup(user, 3, groupName, groupName, null); Assertions.assertEquals(Status.ALERT_GROUP_EXIST, result.get(Constants.STATUS)); } @Test - public void testDelAlertgroupById() { + public void testUpdateGlobalAlertgroup() { + User user = new User(); + user.setId(0); + user.setUserType(UserType.ADMIN_USER); + AlertGroup globalAlertGroup = new AlertGroup(); + globalAlertGroup.setId(2); + globalAlertGroup.setGroupName("global alert group"); + Map result = alertGroupService.updateAlertgroup(user, 2, groupName, groupName, null); + Assertions.assertEquals(Status.NOT_ALLOW_TO_UPDATE_GLOBAL_ALARM_GROUP, result.get(Constants.STATUS)); + } + @Test + public void testDelAlertgroupById() { User user = new User(); user.setId(0); // no operate @@ -222,18 +239,30 @@ public class AlertGroupServiceTest { Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.ALERT_GROUP, user.getId(), ALERT_GROUP_DELETE, baseServiceLogger)).thenReturn(true); Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, - new Object[]{2}, 0, baseServiceLogger)).thenReturn(true); - result = alertGroupService.delAlertgroupById(user, 2); + new Object[]{3}, 0, baseServiceLogger)).thenReturn(true); + result = alertGroupService.delAlertgroupById(user, 3); logger.info(result.toString()); Assertions.assertEquals(Status.ALERT_GROUP_NOT_EXIST, result.get(Constants.STATUS)); - // success + + // not allowed1 + Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, + new Object[]{1}, 0, baseServiceLogger)).thenReturn(true); + result = alertGroupService.delAlertgroupById(user, 1); + logger.info(result.toString()); + Assertions.assertEquals(Status.NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP, result.get(Constants.STATUS)); + // not allowed2 Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, new Object[]{2}, 0, baseServiceLogger)).thenReturn(true); - Mockito.when(alertGroupMapper.selectById(2)).thenReturn(getEntity()); result = alertGroupService.delAlertgroupById(user, 2); logger.info(result.toString()); + Assertions.assertEquals(Status.NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP, result.get(Constants.STATUS)); + // success + Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_GROUP, + new Object[]{4}, 0, baseServiceLogger)).thenReturn(true); + Mockito.when(alertGroupMapper.selectById(4)).thenReturn(getEntity()); + result = alertGroupService.delAlertgroupById(user, 4); + logger.info(result.toString()); Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - } @Test @@ -264,7 +293,14 @@ public class AlertGroupServiceTest { */ private List getList() { List alertGroups = new ArrayList<>(); - alertGroups.add(getEntity()); + AlertGroup defaultAdminWarningGroup = new AlertGroup(); + defaultAdminWarningGroup.setId(1); + defaultAdminWarningGroup.setGroupName("default admin warning group"); + alertGroups.add(defaultAdminWarningGroup); + AlertGroup globalAlertGroup = new AlertGroup(); + globalAlertGroup.setId(2); + globalAlertGroup.setGroupName("global alert group"); + alertGroups.add(globalAlertGroup); return alertGroups; } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceServiceTest.java index 3f767c6ce4..a91d2da37f 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/AlertPluginInstanceServiceTest.java @@ -26,8 +26,11 @@ 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.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.dao.entity.AlertGroup; import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; import org.apache.dolphinscheduler.dao.entity.PluginDefine; import org.apache.dolphinscheduler.dao.entity.User; @@ -79,6 +82,12 @@ public class AlertPluginInstanceServiceTest { private User user; + private final AlertPluginInstanceType normalInstanceType = AlertPluginInstanceType.NORMAL; + + private final AlertPluginInstanceType globalInstanceType = AlertPluginInstanceType.GLOBAL; + + private final WarningType warningType = WarningType.ALL; + private String uiParams = "[\n" + " {\n" + " \"field\":\"userParams\",\n" @@ -160,11 +169,7 @@ public class AlertPluginInstanceServiceTest { user = new User(); user.setUserType(UserType.ADMIN_USER); user.setId(1); - AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); - alertPluginInstance.setPluginInstanceParams("test1"); - alertPluginInstance.setPluginDefineId(1); - alertPluginInstance.setId(1); - alertPluginInstance.setPluginInstanceParams("test"); + AlertPluginInstance alertPluginInstance = getAlertPluginInstance(1, normalInstanceType, "test"); alertPluginInstances = new ArrayList<>(); alertPluginInstances.add(alertPluginInstance); } @@ -176,29 +181,44 @@ public class AlertPluginInstanceServiceTest { 1, ALART_INSTANCE_CREATE, baseServiceLogger)).thenReturn(true); Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_PLUGIN_INSTANCE, null, 0, baseServiceLogger)).thenReturn(true); - Map result = alertPluginInstanceService.create(user, 1, "test", uiParams); + Map result = + alertPluginInstanceService.create(user, 1, "test", normalInstanceType, warningType, uiParams); Assertions.assertEquals(Status.PLUGIN_INSTANCE_ALREADY_EXISTS, result.get(Constants.STATUS)); Mockito.when(alertPluginInstanceMapper.insert(Mockito.any())).thenReturn(1); - result = alertPluginInstanceService.create(user, 1, "test1", uiParams); + result = alertPluginInstanceService.create(user, 1, "test1", normalInstanceType, warningType, uiParams); Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); Assertions.assertNotNull(result.get(Constants.DATA_LIST)); } @Test public void testDelete() { - List ids = Arrays.asList("11,2,3", null, "98,1"); + List ids = Arrays.asList("11,2,3", "5,96", null, "98,1"); Mockito.when(alertGroupMapper.queryInstanceIdsList()).thenReturn(ids); Mockito.when(resourcePermissionCheckService.operationPermissionCheck(AuthorizationType.ALERT_PLUGIN_INSTANCE, 1, ALERT_PLUGIN_DELETE, baseServiceLogger)).thenReturn(true); Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_PLUGIN_INSTANCE, null, 0, baseServiceLogger)).thenReturn(true); - Map result = alertPluginInstanceService.delete(user, 1); + AlertPluginInstance normalInstanceWithId1 = getAlertPluginInstance(1, normalInstanceType, "test1"); + AlertPluginInstance normalInstanceWithId9 = getAlertPluginInstance(9, normalInstanceType, "test9"); + AlertPluginInstance globalInstanceWithId5 = getAlertPluginInstance(5, globalInstanceType, "test5"); + Mockito.when(alertPluginInstanceMapper.selectById(1)).thenReturn(normalInstanceWithId1); + Mockito.when(alertPluginInstanceMapper.selectById(9)).thenReturn(normalInstanceWithId9); + Mockito.when(alertPluginInstanceMapper.selectById(5)).thenReturn(globalInstanceWithId5); + AlertGroup globalAlertGroup = new AlertGroup(); + globalAlertGroup.setId(2); + globalAlertGroup.setAlertInstanceIds("5,96"); + Mockito.when(alertGroupMapper.selectById(2)).thenReturn(globalAlertGroup); + Mockito.when(alertGroupMapper.updateById(Mockito.any())).thenReturn(1); + Map result; + result = alertPluginInstanceService.delete(user, 1); Assertions.assertEquals(Status.DELETE_ALERT_PLUGIN_INSTANCE_ERROR_HAS_ALERT_GROUP_ASSOCIATED, result.get(Constants.STATUS)); Mockito.when(alertPluginInstanceMapper.deleteById(9)).thenReturn(1); result = alertPluginInstanceService.delete(user, 9); Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); - + Mockito.when(alertPluginInstanceMapper.deleteById(5)).thenReturn(1); + result = alertPluginInstanceService.delete(user, 5); + Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } @Test @@ -208,20 +228,16 @@ public class AlertPluginInstanceServiceTest { 1, ALERT_PLUGIN_UPDATE, baseServiceLogger)).thenReturn(true); Mockito.when(resourcePermissionCheckService.resourcePermissionCheck(AuthorizationType.ALERT_PLUGIN_INSTANCE, null, 0, baseServiceLogger)).thenReturn(true); - Map result = alertPluginInstanceService.update(user, 1, "testUpdate", uiParams); + Map result = alertPluginInstanceService.update(user, 1, "testUpdate", warningType, uiParams); Assertions.assertEquals(Status.SAVE_ERROR, result.get(Constants.STATUS)); Mockito.when(alertPluginInstanceMapper.updateById(Mockito.any())).thenReturn(1); - result = alertPluginInstanceService.update(user, 1, "testUpdate", uiParams); + result = alertPluginInstanceService.update(user, 1, "testUpdate", warningType, uiParams); Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } @Test public void testQueryAll() { - AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); - alertPluginInstance.setId(1); - alertPluginInstance.setPluginDefineId(1); - alertPluginInstance.setPluginInstanceParams(paramsMap); - alertPluginInstance.setInstanceName("test"); + AlertPluginInstance alertPluginInstance = getAlertPluginInstance(1, normalInstanceType, "test"); PluginDefine pluginDefine = new PluginDefine("script", "script", uiParams); pluginDefine.setId(1); List pluginDefines = Collections.singletonList(pluginDefine); @@ -232,4 +248,16 @@ public class AlertPluginInstanceServiceTest { Assertions.assertEquals(Status.SUCCESS, result.get(Constants.STATUS)); } + private AlertPluginInstance getAlertPluginInstance(int id, AlertPluginInstanceType instanceType, + String instanceName) { + AlertPluginInstance alertPluginInstance = new AlertPluginInstance(); + alertPluginInstance.setId(id); + alertPluginInstance.setPluginDefineId(1); + alertPluginInstance.setInstanceType(instanceType); + alertPluginInstance.setWarningType(warningType); + alertPluginInstance.setPluginInstanceParams(paramsMap); + alertPluginInstance.setInstanceName(instanceName); + return alertPluginInstance; + } + } diff --git a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java index 705642a88d..dd0801977a 100644 --- a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java +++ b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionServiceTest.java @@ -70,6 +70,7 @@ import org.apache.dolphinscheduler.dao.model.PageListingResult; import org.apache.dolphinscheduler.dao.repository.ProcessDefinitionDao; import org.apache.dolphinscheduler.dao.repository.ProcessDefinitionLogDao; import org.apache.dolphinscheduler.dao.repository.TaskDefinitionLogDao; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.dolphinscheduler.service.process.ProcessService; import org.apache.dolphinscheduler.spi.enums.DbType; @@ -184,6 +185,9 @@ public class ProcessDefinitionServiceTest extends BaseServiceTestTool { @Mock private UserMapper userMapper; + @Mock + private ListenerEventAlertManager listenerEventAlertManager; + protected User user; protected Exception exception; protected final static long projectCode = 1L; diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AlertPluginInstanceType.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AlertPluginInstanceType.java new file mode 100644 index 0000000000..2fa7950dde --- /dev/null +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/AlertPluginInstanceType.java @@ -0,0 +1,43 @@ +/* + * 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.common.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +public enum AlertPluginInstanceType { + + NORMAL(0, "NORMAL"), + GLOBAL(1, "GLOBAL"); + AlertPluginInstanceType(int code, String descp) { + this.code = code; + this.descp = descp; + } + + @EnumValue + private final int code; + private final String descp; + + public int getCode() { + return code; + } + + public String getDescp() { + return descp; + } + +} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ListenerEventType.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ListenerEventType.java new file mode 100644 index 0000000000..4678526daa --- /dev/null +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/ListenerEventType.java @@ -0,0 +1,66 @@ +/* + * 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.common.enums; + +import java.util.HashMap; +import java.util.Map; + +import lombok.Getter; + +import com.baomidou.mybatisplus.annotation.EnumValue; + +@Getter +public enum ListenerEventType { + + SERVER_DOWN(0, "SERVER_DOWN"), + PROCESS_DEFINITION_CREATED(1, "PROCESS_DEFINITION_CREATED"), + PROCESS_DEFINITION_UPDATED(2, "PROCESS_DEFINITION_UPDATED"), + PROCESS_DEFINITION_DELETED(3, "PROCESS_DEFINITION_DELETED"), + PROCESS_START(4, "PROCESS_START"), + PROCESS_END(5, "PROCESS_INSTANCE_END"), + PROCESS_FAIL(6, "PROCESS_FAIL"), + TASK_START(10, "TASK_START"), + TASK_END(11, "TASK_END"), + TASK_FAIL(12, "TASK_FAIL"); + + private static final Map CODE_MAP = new HashMap<>(); + + static { + for (ListenerEventType listenerEventType : ListenerEventType.values()) { + CODE_MAP.put(listenerEventType.getCode(), listenerEventType); + } + } + + @EnumValue + private final int code; + private final String descp; + + ListenerEventType(int code, String descp) { + this.code = code; + this.descp = descp; + } + + public static ListenerEventType of(int code) { + ListenerEventType listenerEventType = CODE_MAP.get(code); + if (listenerEventType == null) { + throw new IllegalArgumentException(String.format("The task execution status code: %s is invalid", + code)); + } + return listenerEventType; + } +} diff --git a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WarningType.java b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WarningType.java index 2ba69e944e..8ac5541159 100644 --- a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WarningType.java +++ b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/enums/WarningType.java @@ -35,11 +35,13 @@ public enum WarningType { * 1 send if process success; * 2 send if process failed; * 3 send if process ends, whatever the result; + * 4 send global events; */ NONE(0, "none"), SUCCESS(1, "success"), FAILURE(2, "failure"), - ALL(3, "all"); + ALL(3, "all"), + GLOBAL(4, "global"); WarningType(int code, String descp) { this.code = code; diff --git a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/enums/ListenerEventTypeTest.java b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/enums/ListenerEventTypeTest.java new file mode 100644 index 0000000000..5e34776661 --- /dev/null +++ b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/enums/ListenerEventTypeTest.java @@ -0,0 +1,43 @@ +/* + * 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.common.enums; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ListenerEventTypeTest { + + @Test + public void testGetCode() { + Assertions.assertEquals(0, ListenerEventType.SERVER_DOWN.getCode()); + Assertions.assertEquals(1, ListenerEventType.PROCESS_DEFINITION_CREATED.getCode()); + } + + @Test + public void testGetDesp() { + Assertions.assertEquals("PROCESS_DEFINITION_UPDATED", ListenerEventType.PROCESS_DEFINITION_UPDATED.getDescp()); + Assertions.assertEquals("PROCESS_DEFINITION_DELETED", ListenerEventType.PROCESS_DEFINITION_DELETED.getDescp()); + } + + @Test + public void testGetListenerEventTypeByCode() { + Assertions.assertEquals(ListenerEventType.PROCESS_START, ListenerEventType.of(4)); + Assertions.assertNotEquals(ListenerEventType.PROCESS_END, ListenerEventType.of(6)); + Assertions.assertThrows(IllegalArgumentException.class, () -> ListenerEventType.of(-1)); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java index c2a25d758e..3b71312d0f 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java @@ -63,7 +63,8 @@ import com.google.common.collect.Lists; @Slf4j public class AlertDao { - private static final int QUERY_ALERT_THRESHOLD = 100; + @Value("${alert.query_alert_threshold:100}") + private Integer QUERY_ALERT_THRESHOLD; @Value("${alert.alarm-suppression.crash:60}") private Integer crashAlarmSuppression; diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java index d1f3400c6d..ae02f081a8 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/AlertPluginInstance.java @@ -17,6 +17,9 @@ package org.apache.dolphinscheduler.dao.entity; +import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType; +import org.apache.dolphinscheduler.common.enums.WarningType; + import java.util.Date; import lombok.Data; @@ -55,6 +58,18 @@ public class AlertPluginInstance { @TableField("plugin_instance_params") private String pluginInstanceParams; + /** + * instance_type. 0 normal, 1 global + */ + @TableField("instance_type") + private AlertPluginInstanceType instanceType; + + /** + * warning_type + */ + @TableField("warning_type") + private WarningType warningType; + /** * create_time */ @@ -80,9 +95,11 @@ public class AlertPluginInstance { this.instanceName = instanceName; } - public AlertPluginInstance(int id, String pluginInstanceParams, String instanceName, Date updateDate) { + public AlertPluginInstance(int id, String pluginInstanceParams, String instanceName, WarningType warningType, + Date updateDate) { this.id = id; this.pluginInstanceParams = pluginInstanceParams; + this.warningType = warningType; this.updateTime = updateDate; this.instanceName = instanceName; } diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java new file mode 100644 index 0000000000..36fe939ce8 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ListenerEvent.java @@ -0,0 +1,88 @@ +/* + * 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.dao.entity; + +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("t_ds_listener_event") +public class ListenerEvent { + + /** + * primary key + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * content + */ + @TableField(value = "content") + private String content; + + /** + * sign + */ + @TableField(value = "sign") + private String sign; + + /** + * alert_status + */ + @TableField(value = "event_type") + private ListenerEventType eventType; + + /** + * post_status + */ + @TableField("post_status") + private AlertStatus postStatus; + + /** + * log + */ + @TableField("log") + private String log; + /** + * create_time + */ + @TableField("create_time") + private Date createTime; + + /** + * update_time + */ + @TableField("update_time") + private Date updateTime; +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/AbstractListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/AbstractListenerEvent.java new file mode 100644 index 0000000000..c2e9501bd3 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/AbstractListenerEvent.java @@ -0,0 +1,27 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; + +public interface AbstractListenerEvent { + + ListenerEventType getEventType(); + + String getTitle(); +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionCreatedListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionCreatedListenerEvent.java new file mode 100644 index 0000000000..c3b14d4c4b --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionCreatedListenerEvent.java @@ -0,0 +1,195 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.Flag; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.ProcessExecutionTypeEnum; +import org.apache.dolphinscheduler.common.enums.ReleaseState; +import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; +import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; +import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; +import org.apache.dolphinscheduler.plugin.task.api.model.Property; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessDefinitionCreatedListenerEvent implements AbstractListenerEvent { + + /** + * id + */ + private Integer id; + + /** + * code + */ + private long code; + + /** + * name + */ + private String name; + + /** + * version + */ + private int version; + + /** + * release state : online/offline + */ + private ReleaseState releaseState; + + /** + * project code + */ + private long projectCode; + + /** + * description + */ + private String description; + + /** + * user defined parameters + */ + private String globalParams; + + /** + * user defined parameter list + */ + private List globalParamList; + + /** + * user define parameter map + */ + private Map globalParamMap; + + /** + * create time + */ + private Date createTime; + + /** + * update time + */ + private Date updateTime; + + /** + * process is valid: yes/no + */ + private Flag flag; + + /** + * process user id + */ + private int userId; + + /** + * create user name + */ + private String userName; + + /** + * project name + */ + private String projectName; + + /** + * locations array for web + */ + private String locations; + + /** + * schedule release state : online/offline + */ + private ReleaseState scheduleReleaseState; + + /** + * process warning time out. unit: minute + */ + private int timeout; + + /** + * modify user name + */ + private String modifyBy; + + /** + * warningGroupId + */ + private Integer warningGroupId; + + /** + * execution type + */ + private ProcessExecutionTypeEnum executionType; + + /** + * task definitions + */ + List taskDefinitionLogs; + + /** + * + */ + List taskRelationList; + + public ProcessDefinitionCreatedListenerEvent(ProcessDefinition processDefinition) { + this.setId(processDefinition.getId()); + this.setCode(processDefinition.getCode()); + this.setName(processDefinition.getName()); + this.setVersion(processDefinition.getVersion()); + this.setReleaseState(processDefinition.getReleaseState()); + this.setProjectCode(processDefinition.getProjectCode()); + this.setDescription(processDefinition.getDescription()); + this.setGlobalParams(processDefinition.getGlobalParams()); + this.setGlobalParamList(processDefinition.getGlobalParamList()); + this.setGlobalParamMap(processDefinition.getGlobalParamMap()); + this.setCreateTime(processDefinition.getCreateTime()); + this.setUpdateTime(processDefinition.getUpdateTime()); + this.setFlag(processDefinition.getFlag()); + this.setUserId(processDefinition.getUserId()); + this.setUserName(processDefinition.getUserName()); + this.setProjectName(processDefinition.getProjectName()); + this.setLocations(processDefinition.getLocations()); + this.setScheduleReleaseState(processDefinition.getScheduleReleaseState()); + this.setTimeout(processDefinition.getTimeout()); + this.setModifyBy(processDefinition.getModifyBy()); + this.setWarningGroupId(processDefinition.getWarningGroupId()); + this.setExecutionType(processDefinition.getExecutionType()); + } + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_DEFINITION_CREATED; + } + + @Override + public String getTitle() { + return String.format("process definition created:%s", this.name); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionDeletedListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionDeletedListenerEvent.java new file mode 100644 index 0000000000..a42e81de68 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionDeletedListenerEvent.java @@ -0,0 +1,52 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessDefinitionDeletedListenerEvent implements AbstractListenerEvent { + + private Integer projectId; + private Long projectCode; + private String projectName; + private String owner; + private Integer id; + private Long code; + private String name; + private Integer userId; + private String modifiedBy; + private Date eventTime; + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_DEFINITION_DELETED; + } + + @Override + public String getTitle() { + return String.format("process definition deleted:%s", this.name); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionUpdatedListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionUpdatedListenerEvent.java new file mode 100644 index 0000000000..dc9b5de7cc --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessDefinitionUpdatedListenerEvent.java @@ -0,0 +1,195 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.Flag; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.ProcessExecutionTypeEnum; +import org.apache.dolphinscheduler.common.enums.ReleaseState; +import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; +import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; +import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; +import org.apache.dolphinscheduler.plugin.task.api.model.Property; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessDefinitionUpdatedListenerEvent implements AbstractListenerEvent { + + /** + * id + */ + private Integer id; + + /** + * code + */ + private long code; + + /** + * name + */ + private String name; + + /** + * version + */ + private int version; + + /** + * release state : online/offline + */ + private ReleaseState releaseState; + + /** + * project code + */ + private long projectCode; + + /** + * description + */ + private String description; + + /** + * user defined parameters + */ + private String globalParams; + + /** + * user defined parameter list + */ + private List globalParamList; + + /** + * user define parameter map + */ + private Map globalParamMap; + + /** + * create time + */ + private Date createTime; + + /** + * update time + */ + private Date updateTime; + + /** + * process is valid: yes/no + */ + private Flag flag; + + /** + * process user id + */ + private int userId; + + /** + * create user name + */ + private String userName; + + /** + * project name + */ + private String projectName; + + /** + * locations array for web + */ + private String locations; + + /** + * schedule release state : online/offline + */ + private ReleaseState scheduleReleaseState; + + /** + * process warning time out. unit: minute + */ + private int timeout; + + /** + * modify user name + */ + private String modifyBy; + + /** + * warningGroupId + */ + private Integer warningGroupId; + + /** + * execution type + */ + private ProcessExecutionTypeEnum executionType; + + /** + * task definitions + */ + List taskDefinitionLogs; + + /** + * + */ + List taskRelationList; + + public ProcessDefinitionUpdatedListenerEvent(ProcessDefinition processDefinition) { + this.setId(processDefinition.getId()); + this.setCode(processDefinition.getCode()); + this.setName(processDefinition.getName()); + this.setVersion(processDefinition.getVersion()); + this.setReleaseState(processDefinition.getReleaseState()); + this.setProjectCode(processDefinition.getProjectCode()); + this.setDescription(processDefinition.getDescription()); + this.setGlobalParams(processDefinition.getGlobalParams()); + this.setGlobalParamList(processDefinition.getGlobalParamList()); + this.setGlobalParamMap(processDefinition.getGlobalParamMap()); + this.setCreateTime(processDefinition.getCreateTime()); + this.setUpdateTime(processDefinition.getUpdateTime()); + this.setFlag(processDefinition.getFlag()); + this.setUserId(processDefinition.getUserId()); + this.setUserName(processDefinition.getUserName()); + this.setProjectName(processDefinition.getProjectName()); + this.setLocations(processDefinition.getLocations()); + this.setScheduleReleaseState(processDefinition.getScheduleReleaseState()); + this.setTimeout(processDefinition.getTimeout()); + this.setModifyBy(processDefinition.getModifyBy()); + this.setWarningGroupId(processDefinition.getWarningGroupId()); + this.setExecutionType(processDefinition.getExecutionType()); + } + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_DEFINITION_UPDATED; + } + + @Override + public String getTitle() { + return String.format("process definition updated:%s", this.name); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessEndListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessEndListenerEvent.java new file mode 100644 index 0000000000..19ac3d824f --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessEndListenerEvent.java @@ -0,0 +1,59 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.Flag; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessEndListenerEvent implements AbstractListenerEvent { + + private Long projectCode; + private String projectName; + private String owner; + private Integer processId; + private Long processDefinitionCode; + private String processName; + private CommandType processType; + private WorkflowExecutionStatus processState; + private Flag recovery; + private Integer runTimes; + private Date processStartTime; + private Date processEndTime; + private String processHost; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_END; + } + + @Override + public String getTitle() { + return String.format("process end: %s", processName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessFailListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessFailListenerEvent.java new file mode 100644 index 0000000000..6910347410 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessFailListenerEvent.java @@ -0,0 +1,59 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.Flag; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessFailListenerEvent implements AbstractListenerEvent { + + private Long projectCode; + private String projectName; + private String owner; + private Integer processId; + private Long processDefinitionCode; + private String processName; + private CommandType processType; + private WorkflowExecutionStatus processState; + private Flag recovery; + private Integer runTimes; + private Date processStartTime; + private Date processEndTime; + private String processHost; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_FAIL; + } + + @Override + public String getTitle() { + return String.format("process fail: %s", processName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessStartListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessStartListenerEvent.java new file mode 100644 index 0000000000..3fc96ba32d --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ProcessStartListenerEvent.java @@ -0,0 +1,58 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.CommandType; +import org.apache.dolphinscheduler.common.enums.Flag; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.WorkflowExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProcessStartListenerEvent implements AbstractListenerEvent { + + private Long projectCode; + private String projectName; + private String owner; + private Long processDefinitionCode; + private String processDefinitionName; + private Integer processId; + private String processName; + private CommandType processType; + private WorkflowExecutionStatus processState; + private Integer runTimes; + private Flag recovery; + private Date processStartTime; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.PROCESS_START; + } + + @Override + public String getTitle() { + return String.format("process start: %s", processName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ServerDownListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ServerDownListenerEvent.java new file mode 100644 index 0000000000..5fdf475c54 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/ServerDownListenerEvent.java @@ -0,0 +1,45 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ServerDownListenerEvent implements AbstractListenerEvent { + + private String type; + private String host; + private Date eventTime; + @Override + public ListenerEventType getEventType() { + return ListenerEventType.SERVER_DOWN; + } + + @Override + public String getTitle() { + return String.format("%s server down: %s", type, host); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskEndListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskEndListenerEvent.java new file mode 100644 index 0000000000..2718d7ef0e --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskEndListenerEvent.java @@ -0,0 +1,59 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TaskEndListenerEvent implements AbstractListenerEvent { + + private long projectCode; + private String projectName; + private String owner; + private long processId; + private long processDefinitionCode; + private String processName; + private int taskInstanceId; + private long taskCode; + private String taskName; + private String taskType; + private TaskExecutionStatus taskState; + private Date taskStartTime; + private Date taskEndTime; + private String taskHost; + private String logPath; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.TASK_END; + } + + @Override + public String getTitle() { + return String.format("task end: %s", taskName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskFailListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskFailListenerEvent.java new file mode 100644 index 0000000000..a7c4117a70 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskFailListenerEvent.java @@ -0,0 +1,59 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TaskFailListenerEvent implements AbstractListenerEvent { + + private long projectCode; + private String projectName; + private String owner; + private long processId; + private long processDefinitionCode; + private String processName; + private int taskInstanceId; + private long taskCode; + private String taskName; + private String taskType; + private TaskExecutionStatus taskState; + private Date taskStartTime; + private Date taskEndTime; + private String taskHost; + private String logPath; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.TASK_FAIL; + } + + @Override + public String getTitle() { + return String.format("task fail: %s", taskName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskStartListenerEvent.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskStartListenerEvent.java new file mode 100644 index 0000000000..afd5cbff7e --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/event/TaskStartListenerEvent.java @@ -0,0 +1,59 @@ +/* + * 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.dao.entity.event; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.plugin.task.api.enums.TaskExecutionStatus; + +import java.util.Date; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class TaskStartListenerEvent implements AbstractListenerEvent { + + private long projectCode; + private String projectName; + private String owner; + private long processId; + private long processDefinitionCode; + private String processName; + private int taskInstanceId; + private long taskCode; + private String taskName; + private String taskType; + private TaskExecutionStatus taskState; + private Date taskStartTime; + private Date taskEndTime; + private String taskHost; + private String logPath; + + @Override + public ListenerEventType getEventType() { + return ListenerEventType.TASK_START; + } + + @Override + public String getTitle() { + return String.format("task start: %s", taskName); + } +} diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java index d857ac6845..27d18a90bb 100644 --- a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.java @@ -36,6 +36,13 @@ public interface AlertPluginInstanceMapper extends BaseMapper queryAllAlertPluginInstanceList(); + /** + * query all global alert plugin instance + * + * @return global AlertPluginInstance list + */ + List queryAllGlobalAlertPluginInstanceList(); + /** * query by alert group id * diff --git a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapper.java b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapper.java new file mode 100644 index 0000000000..820ac3b3a6 --- /dev/null +++ b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapper.java @@ -0,0 +1,42 @@ +/* + * 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.dao.mapper; + +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.dao.entity.ListenerEvent; + +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface ListenerEventMapper extends BaseMapper { + + int batchInsert(@Param("events") List events); + + void insertServerDownEvent(@Param("event") ListenerEvent event, + @Param("crashAlarmSuppressionStartTime") Date crashAlarmSuppressionStartTime); + + List listingListenerEventByStatus(@Param("postStatus") AlertStatus postStatus, + @Param("limit") int limit); + + void updateListenerEvent(@Param("eventId") int eventId, @Param("postStatus") AlertStatus postStatus, + @Param("log") String log, @Param("updateTime") Date updateTime); +} diff --git a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.xml b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.xml index f05e7d0f8c..95a4f32cbf 100644 --- a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.xml +++ b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapper.xml @@ -20,7 +20,7 @@ - id, plugin_define_id, plugin_instance_params, create_time, update_time, instance_name + id, plugin_define_id, plugin_instance_params, instance_type, warning_type, create_time, update_time, instance_name @@ -32,6 +32,14 @@ where 1 = 1 order by update_time desc + + + select + + from t_ds_listener_event + where post_status = #{postStatus.code} + limit #{limit} + + diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql index 2604aa0e0a..abfc5274de 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql @@ -1062,6 +1062,10 @@ INSERT INTO t_ds_alertgroup(alert_instance_ids, create_user_id, group_name, desc VALUES (NULL, 1, 'default admin warning group', 'default admin warning group', '2018-11-29 10:20:39', '2018-11-29 10:20:39'); +INSERT INTO t_ds_alertgroup(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) +VALUES (NULL, 1, 'global alert group', 'global alert group', '2018-11-29 10:20:39', + '2018-11-29 10:20:39'); + -- ---------------------------- -- Records of t_ds_user -- ---------------------------- @@ -1097,6 +1101,8 @@ CREATE TABLE t_ds_alert_plugin_instance create_time timestamp NULL DEFAULT CURRENT_TIMESTAMP, update_time timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, instance_name varchar(200) DEFAULT NULL, + instance_type int NOT NULL default '0', + warning_type int NOT NULL default '3', PRIMARY KEY (id) ); @@ -2141,3 +2147,22 @@ CREATE TABLE t_ds_relation_sub_workflow ( INDEX idx_parent_task_code (parent_task_code), INDEX idx_sub_workflow_instance_id (sub_workflow_instance_id) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Table structure for t_ds_listener_event +-- ---------------------------- +DROP TABLE IF EXISTS t_ds_listener_event; +CREATE TABLE t_ds_listener_event +( + id int NOT NULL AUTO_INCREMENT, + content text, + sign char(64) NOT NULL DEFAULT '', + post_status tinyint(4) NOT NULL DEFAULT '0', + event_type int(11), + log text, + create_time datetime DEFAULT NULL, + update_time datetime DEFAULT NULL, + PRIMARY KEY (id), + KEY idx_status (post_status), + KEY idx_event_sign (sign) +); diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql index d6bfc3b2da..73e9da51b3 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql @@ -1051,6 +1051,8 @@ INSERT IGNORE INTO `t_ds_version` VALUES ('1', '3.3.0'); -- ---------------------------- INSERT IGNORE INTO `t_ds_alertgroup`(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) VALUES (NULL, 1, 'default admin warning group', 'default admin warning group', current_timestamp, current_timestamp); +INSERT IGNORE INTO `t_ds_alertgroup`(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) +VALUES (NULL, 1, 'global alert group', 'global alert group', current_timestamp, current_timestamp); -- ---------------------------- -- Records of t_ds_user @@ -1086,6 +1088,8 @@ CREATE TABLE `t_ds_alert_plugin_instance` ( `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `instance_name` varchar(255) DEFAULT NULL COMMENT 'alert instance name', + `instance_type` int NOT NULL default '0', + `warning_type` int NOT NULL default '3', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE = utf8_bin; @@ -2114,3 +2118,21 @@ CREATE TABLE `t_ds_relation_sub_workflow` ( KEY `idx_parent_task_code` (`parent_task_code`), KEY `idx_sub_workflow_instance_id` (`sub_workflow_instance_id`) ); + +-- ---------------------------- +-- Table structure for t_ds_listener_event +-- ---------------------------- +DROP TABLE IF EXISTS `t_ds_listener_event`; +CREATE TABLE `t_ds_listener_event` ( + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'key', + `content` text COMMENT 'listener event json content', + `sign` char(64) NOT NULL DEFAULT '' COMMENT 'sign=sha1(content)', + `post_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:wait running,1:success,2:failed,3:partial success', + `event_type` int(11) NOT NULL COMMENT 'listener event type', + `log` text COMMENT 'log', + `create_time` datetime DEFAULT NULL COMMENT 'create time', + `update_time` datetime DEFAULT NULL COMMENT 'update time', + PRIMARY KEY (`id`), + KEY `idx_status` (`post_status`) USING BTREE, + KEY `idx_sign` (`sign`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE = utf8_bin; diff --git a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql index bc006cfba3..2d4a2162a0 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql @@ -1035,6 +1035,8 @@ VALUES (-1, 'default', 'default tenant', '1', '2018-03-27 15:48:50', '2018-10-24 -- Records of t_ds_alertgroup, default admin warning group INSERT INTO t_ds_alertgroup(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) VALUES (NULL, 1, 'default admin warning group', 'default admin warning group', '2018-11-29 10:20:39', '2018-11-29 10:20:39'); +INSERT INTO t_ds_alertgroup(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) +VALUES (NULL, 1, 'global alert group', 'global alert group', '2018-11-29 10:20:39', '2018-11-29 10:20:39'); -- Records of t_ds_queue,default queue name : default INSERT INTO t_ds_queue(queue_name, queue, create_time, update_time) @@ -1066,11 +1068,13 @@ CREATE TABLE t_ds_plugin_define ( DROP TABLE IF EXISTS t_ds_alert_plugin_instance; CREATE TABLE t_ds_alert_plugin_instance ( id serial NOT NULL, - plugin_define_id int4 NOT NULL, + plugin_define_id int NOT NULL, plugin_instance_params text NULL, create_time timestamp NULL, update_time timestamp NULL, instance_name varchar(255) NULL, + instance_type int NOT NULL default '0', + warning_type int NOT NULL default '3', CONSTRAINT t_ds_alert_plugin_instance_pk PRIMARY KEY (id) ); @@ -2103,3 +2107,23 @@ CREATE INDEX idx_parent_workflow_instance_id ON t_ds_relation_sub_workflow (pare CREATE INDEX idx_parent_task_code ON t_ds_relation_sub_workflow (parent_task_code); CREATE INDEX idx_sub_workflow_instance_id ON t_ds_relation_sub_workflow (sub_workflow_instance_id); +-- +-- Table structure for table t_ds_alert +-- + +DROP TABLE IF EXISTS t_ds_listener_event; +CREATE TABLE t_ds_listener_event( + id int NOT NULL, + content text, + sign varchar(64) NOT NULL DEFAULT '', + post_status int NOT NULL DEFAULT '0', + event_type int NOT NULL, + log text, + create_time timestamp DEFAULT NULL, + update_time timestamp DEFAULT NULL, + PRIMARY KEY (id) +); +comment on column t_ds_listener_event.sign is 'sign=sha1(content)'; + +create index idx_listener_event_post_status on t_ds_listener_event (post_status); +create index idx_listener_event_sign on t_ds_listener_event (sign); diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.2.0_schema/mysql/dolphinscheduler_ddl.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.2.0_schema/mysql/dolphinscheduler_ddl.sql index fe841e23e0..3015f83e76 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.2.0_schema/mysql/dolphinscheduler_ddl.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.2.0_schema/mysql/dolphinscheduler_ddl.sql @@ -447,6 +447,13 @@ BEGIN THEN ALTER TABLE `t_ds_fav_task` DROP COLUMN `task_name`; END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS + WHERE TABLE_NAME='t_ds_fav_task' + AND TABLE_SCHEMA=(SELECT DATABASE()) + AND COLUMN_NAME ='task_type') + THEN + ALTER TABLE `t_ds_fav_task` ADD `task_type` varchar(64) NOT NULL COMMENT 'favorite task type name'; + END IF; END; d// delimiter ; diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_ddl.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_ddl.sql index 4a14f326b9..0bbc6fbad2 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_ddl.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_ddl.sql @@ -14,3 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +-- Modify "t_ds_alertgroup" table +ALTER TABLE `t_ds_alertgroup` AUTO_INCREMENT 3; +-- Modify "t_ds_alert_plugin_instance" table +ALTER TABLE `t_ds_alert_plugin_instance` + ADD COLUMN `instance_type` int NOT NULL DEFAULT 0, ADD COLUMN `warning_type` int NOT NULL DEFAULT 3; +-- Create "t_ds_listener_event" table +CREATE TABLE `t_ds_listener_event` +( + `id` int NOT NULL AUTO_INCREMENT COMMENT "key", + `content` text NULL COMMENT "listener event json content", + `sign` char(64) NOT NULL DEFAULT "" COMMENT "sign=sha1(content)", + `post_status` tinyint NOT NULL DEFAULT 0 COMMENT "0:wait running,1:success,2:failed,3:partial success", + `event_type` int NOT NULL COMMENT "listener event type", + `log` text NULL COMMENT "log", + `create_time` datetime NULL COMMENT "create time", + `update_time` datetime NULL COMMENT "update time", + PRIMARY KEY (`id`), + INDEX `idx_sign` (`sign`), + INDEX `idx_status` (`post_status`) +) CHARSET utf8 COLLATE utf8_bin; diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql index 4a14f326b9..f1a1229680 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/mysql/dolphinscheduler_dml.sql @@ -14,3 +14,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +INSERT IGNORE INTO `t_ds_alertgroup`(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) +VALUES (NULL, 1, 'global alert group', 'global alert group', current_timestamp, current_timestamp); diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_ddl.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_ddl.sql index 4a14f326b9..7a2cef722f 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_ddl.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_ddl.sql @@ -14,3 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +-- Modify "t_ds_alert_plugin_instance" table +ALTER TABLE "t_ds_alert_plugin_instance" ADD COLUMN "instance_type" integer NOT NULL DEFAULT 0, ADD COLUMN "warning_type" integer NOT NULL DEFAULT 3; +-- Create "t_ds_listener_event" table +CREATE TABLE "t_ds_listener_event" ("id" integer NOT NULL, "content" text NULL, "sign" character varying(64) NOT NULL DEFAULT '', "post_status" integer NOT NULL DEFAULT 0, "event_type" integer NOT NULL, "log" text NULL, "create_time" timestamp NULL, "update_time" timestamp NULL, PRIMARY KEY ("id")); +-- Create index "idx_listener_event_post_status" to table: "t_ds_listener_event" +CREATE INDEX "idx_listener_event_post_status" ON "t_ds_listener_event" ("post_status"); +-- Create index "idx_listener_event_sign" to table: "t_ds_listener_event" +CREATE INDEX "idx_listener_event_sign" ON "t_ds_listener_event" ("sign"); +-- Set comment to column: "sign" on table: "t_ds_listener_event" +COMMENT ON COLUMN "t_ds_listener_event" ."sign" IS 'sign=sha1(content)'; diff --git a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql index 4a14f326b9..43640a93b9 100644 --- a/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql +++ b/dolphinscheduler-dao/src/main/resources/sql/upgrade/3.3.0_schema/postgresql/dolphinscheduler_dml.sql @@ -14,3 +14,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +INSERT INTO t_ds_alertgroup(alert_instance_ids, create_user_id, group_name, description, create_time, update_time) +VALUES (NULL, 1, 'global alert group', 'global alert group', '2018-11-29 10:20:39', '2018-11-29 10:20:39'); diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionCreatedListenerEventTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionCreatedListenerEventTest.java new file mode 100644 index 0000000000..b5cd3e5319 --- /dev/null +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionCreatedListenerEventTest.java @@ -0,0 +1,48 @@ +/* + * 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.dao.entity; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.ReleaseState; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionCreatedListenerEvent; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ProcessDefinitionCreatedListenerEventTest { + + @Test + public void testBuildProcessDefinitionUpdatedListenerEvent() { + int id = 1; + long code = 1L; + String name = "testName"; + ReleaseState releaseState = ReleaseState.OFFLINE; + ProcessDefinition processDefinition = new ProcessDefinition(); + processDefinition.setId(id); + processDefinition.setCode(code); + processDefinition.setName(name); + processDefinition.setReleaseState(releaseState); + ProcessDefinitionCreatedListenerEvent event = new ProcessDefinitionCreatedListenerEvent(processDefinition); + Assertions.assertEquals(event.getEventType(), ListenerEventType.PROCESS_DEFINITION_CREATED); + Assertions.assertEquals(event.getId(), id); + Assertions.assertEquals(event.getCode(), code); + Assertions.assertEquals(event.getName(), name); + Assertions.assertEquals(event.getReleaseState(), releaseState); + Assertions.assertEquals(String.format("process definition created:%s", name), event.getTitle()); + } +} diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionUpdatedListenerEventTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionUpdatedListenerEventTest.java new file mode 100644 index 0000000000..71c73d2c61 --- /dev/null +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/entity/ProcessDefinitionUpdatedListenerEventTest.java @@ -0,0 +1,48 @@ +/* + * 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.dao.entity; + +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.enums.ReleaseState; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionUpdatedListenerEvent; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ProcessDefinitionUpdatedListenerEventTest { + + @Test + public void testBuildProcessDefinitionUpdatedListenerEvent() { + int id = 1; + long code = 1L; + String name = "testName"; + ReleaseState releaseState = ReleaseState.OFFLINE; + ProcessDefinition processDefinition = new ProcessDefinition(); + processDefinition.setId(id); + processDefinition.setCode(code); + processDefinition.setName(name); + processDefinition.setReleaseState(releaseState); + ProcessDefinitionUpdatedListenerEvent event = new ProcessDefinitionUpdatedListenerEvent(processDefinition); + Assertions.assertEquals(event.getEventType(), ListenerEventType.PROCESS_DEFINITION_UPDATED); + Assertions.assertEquals(event.getId(), id); + Assertions.assertEquals(event.getCode(), code); + Assertions.assertEquals(event.getName(), name); + Assertions.assertEquals(event.getReleaseState(), releaseState); + Assertions.assertEquals(String.format("process definition updated:%s", name), event.getTitle()); + } +} diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapperTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapperTest.java index 93d8f04c93..d6e45a98fc 100644 --- a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapperTest.java +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/AlertPluginInstanceMapperTest.java @@ -17,6 +17,7 @@ package org.apache.dolphinscheduler.dao.mapper; +import org.apache.dolphinscheduler.common.enums.AlertPluginInstanceType; import org.apache.dolphinscheduler.dao.BaseDaoTest; import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; import org.apache.dolphinscheduler.dao.entity.PluginDefine; @@ -41,6 +42,9 @@ public class AlertPluginInstanceMapperTest extends BaseDaoTest { @Autowired private PluginDefineMapper pluginDefineMapper; + @Autowired + private AlertGroupMapper alertGroupMapper; + /** * Test function queryAllAlertPluginInstanceList behavior with different size. */ @@ -49,13 +53,17 @@ public class AlertPluginInstanceMapperTest extends BaseDaoTest { List withoutSingleOne = alertPluginInstanceMapper.queryAllAlertPluginInstanceList(); Assertions.assertEquals(0, withoutSingleOne.size()); - createAlertPluginInstance("test_instance_1"); + createNormalAlertPluginInstance("test_instance_1"); List withExactlyOne = alertPluginInstanceMapper.queryAllAlertPluginInstanceList(); Assertions.assertEquals(1, withExactlyOne.size()); - createAlertPluginInstance("test_instance_2"); + createNormalAlertPluginInstance("test_instance_2"); List withExactlyTwo = alertPluginInstanceMapper.queryAllAlertPluginInstanceList(); Assertions.assertEquals(2, withExactlyTwo.size()); + + createGlobalAlertPluginInstance("test_global_instance_1"); + List withExactlyThree = alertPluginInstanceMapper.queryAllAlertPluginInstanceList(); + Assertions.assertEquals(3, withExactlyThree.size()); } /** @@ -65,7 +73,9 @@ public class AlertPluginInstanceMapperTest extends BaseDaoTest { public void testExistInstanceName() { String instanceName = "test_instance"; Assertions.assertNull(alertPluginInstanceMapper.existInstanceName(instanceName)); - createAlertPluginInstance(instanceName); + createNormalAlertPluginInstance(instanceName); + Assertions.assertTrue(alertPluginInstanceMapper.existInstanceName(instanceName)); + createGlobalAlertPluginInstance(instanceName); Assertions.assertTrue(alertPluginInstanceMapper.existInstanceName(instanceName)); } @@ -74,8 +84,8 @@ public class AlertPluginInstanceMapperTest extends BaseDaoTest { */ @Test public void testQueryByInstanceNamePage() { - createAlertPluginInstance("test_with_pattern_instance"); - createAlertPluginInstance("test_no_instance"); + createNormalAlertPluginInstance("test_with_pattern_instance"); + createNormalAlertPluginInstance("test_no_instance"); Page page = new Page<>(1, 10); IPage matchTwoRecord = alertPluginInstanceMapper.queryByInstanceNamePage(page, "test"); @@ -86,11 +96,42 @@ public class AlertPluginInstanceMapperTest extends BaseDaoTest { } /** - * Create alert plugin instance according to given alter plugin name. + * Test function queryAllGlobalAlertPluginInstanceList returning with different search variables. + */ + @Test + public void testQueryAllGlobalAlertPluginInstanceList() { + List withoutSingleOne = alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + Assertions.assertEquals(0, withoutSingleOne.size()); + + createNormalAlertPluginInstance("test_normal_instance"); + List withExactlyOne = alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + Assertions.assertEquals(0, withExactlyOne.size()); + + createGlobalAlertPluginInstance("test_global_instance_1"); + List withExactlyTwo = alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + Assertions.assertEquals(1, withExactlyTwo.size()); + + createGlobalAlertPluginInstance("test_global_instance_2"); + List withExactlyThree = alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + Assertions.assertEquals(2, withExactlyThree.size()); + } + + /** + * Create normal alert plugin instance according to given alter plugin name. + */ + private void createNormalAlertPluginInstance(String alterPluginInsName) { + PluginDefine pluginDefine = makeSurePluginDefineExists(); + AlertPluginInstance alertPluginInstance = new AlertPluginInstance(pluginDefine.getId(), "", alterPluginInsName); + alertPluginInstanceMapper.insert(alertPluginInstance); + } + + /** + * Create global alert plugin instance according to given alter plugin name. */ - private void createAlertPluginInstance(String alterPluginInsName) { + private void createGlobalAlertPluginInstance(String alterPluginInsName) { PluginDefine pluginDefine = makeSurePluginDefineExists(); AlertPluginInstance alertPluginInstance = new AlertPluginInstance(pluginDefine.getId(), "", alterPluginInsName); + alertPluginInstance.setInstanceType(AlertPluginInstanceType.GLOBAL); alertPluginInstanceMapper.insert(alertPluginInstance); } diff --git a/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapperTest.java b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapperTest.java new file mode 100644 index 0000000000..f3e877aaa3 --- /dev/null +++ b/dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/ListenerEventMapperTest.java @@ -0,0 +1,134 @@ +/* + * 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.dao.mapper; + +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.utils.DateUtils; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.BaseDaoTest; +import org.apache.dolphinscheduler.dao.entity.ListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ServerDownListenerEvent; + +import org.apache.commons.codec.digest.DigestUtils; + +import java.util.Date; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Lists; + +/** + * AlertPluginInstanceMapper mapper test + */ +public class ListenerEventMapperTest extends BaseDaoTest { + + @Autowired + private ListenerEventMapper listenerEventMapper; + + /** + * test insert + * + * @return + */ + @Test + public void testInsert() { + ListenerEvent serverDownListenerEvent = generateServerDownListenerEvent("192.168.x.x"); + listenerEventMapper.insert(serverDownListenerEvent); + Assertions.assertTrue(serverDownListenerEvent.getId() > 0); + } + + /** + * test batch insert + * + * @return + */ + @Test + public void testBatchInsert() { + ListenerEvent event1 = generateServerDownListenerEvent("192.168.x.1"); + ListenerEvent event2 = generateServerDownListenerEvent("192.168.x.2"); + listenerEventMapper.batchInsert(Lists.newArrayList(event1, event2)); + Assertions.assertEquals(listenerEventMapper.selectCount(new QueryWrapper<>()), 2L); + } + + /** + * test list listener event by status + * + * @return + */ + @Test + public void testListingListenerEventByStatus() { + ListenerEvent event1 = generateServerDownListenerEvent("192.168.x.1"); + ListenerEvent event2 = generateServerDownListenerEvent("192.168.x.2"); + listenerEventMapper.batchInsert(Lists.newArrayList(event1, event2)); + List listenerEvents = + listenerEventMapper.listingListenerEventByStatus(AlertStatus.WAIT_EXECUTION, 50); + Assertions.assertEquals(listenerEvents.size(), 2); + } + + /** + * test update server down event + * + * @return + */ + @Test + public void testUpdateListenerEvent() { + ListenerEvent event = generateServerDownListenerEvent("192.168.x.1"); + listenerEventMapper.insert(event); + listenerEventMapper.updateListenerEvent(event.getId(), AlertStatus.EXECUTION_FAILURE, "fail", new Date()); + ListenerEvent updatedEvent = listenerEventMapper.selectById(event.getId()); + Assertions.assertEquals(updatedEvent.getPostStatus(), AlertStatus.EXECUTION_FAILURE); + Assertions.assertEquals(updatedEvent.getLog(), "fail"); + } + + /** + * test delete listener event + */ + @Test + public void testDeleteListenerEvent() { + ListenerEvent event = generateServerDownListenerEvent("192.168.x.1"); + listenerEventMapper.insert(event); + listenerEventMapper.deleteById(event); + ListenerEvent actualAlert = listenerEventMapper.selectById(event.getId()); + Assertions.assertNull(actualAlert); + } + /** + * create server down event + * @param host worker host + * @return listener event + */ + private ListenerEvent generateServerDownListenerEvent(String host) { + ServerDownListenerEvent event = new ServerDownListenerEvent(); + event.setEventTime(new Date()); + event.setHost(host); + event.setType("WORKER"); + ListenerEvent listenerEvent = new ListenerEvent(); + listenerEvent.setEventType(ListenerEventType.SERVER_DOWN); + listenerEvent.setContent(JSONUtils.toJsonString(event)); + listenerEvent.setSign(DigestUtils.sha1Hex(listenerEvent.getContent())); + listenerEvent.setLog("success"); + listenerEvent.setCreateTime(DateUtils.getCurrentDate()); + listenerEvent.setUpdateTime(DateUtils.getCurrentDate()); + listenerEvent.setPostStatus(AlertStatus.WAIT_EXECUTION); + return listenerEvent; + } +} diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/event/TaskStateEventHandler.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/event/TaskStateEventHandler.java index 731a16b619..f790131a70 100644 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/event/TaskStateEventHandler.java +++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/event/TaskStateEventHandler.java @@ -54,6 +54,10 @@ public class TaskStateEventHandler implements StateEventHandler { "Handle task instance state event, the current task instance state {} will be changed to {}", task.getState().name(), taskStateEvent.getStatus().name()); + if (taskStateEvent.getStatus().isRunning()) { + workflowExecuteRunnable.taskStart(task); + } + Set completeTaskSet = workflowExecuteRunnable.getCompleteTaskCodes(); if (task.getState().isFinished() && (taskStateEvent.getStatus() != null && taskStateEvent.getStatus().isRunning())) { diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/registry/ServerNodeManager.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/registry/ServerNodeManager.java index feee60a171..5fc0a1990f 100644 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/registry/ServerNodeManager.java +++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/registry/ServerNodeManager.java @@ -32,6 +32,7 @@ import org.apache.dolphinscheduler.registry.api.SubscribeListener; import org.apache.dolphinscheduler.registry.api.enums.RegistryNodeType; import org.apache.dolphinscheduler.server.master.config.MasterConfig; import org.apache.dolphinscheduler.server.master.dispatch.exceptions.WorkerGroupNotFoundException; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ArrayUtils; @@ -101,6 +102,9 @@ public class ServerNodeManager implements InitializingBean { @Autowired private MasterConfig masterConfig; + @Autowired + private ListenerEventAlertManager listenerEventAlertManager; + private final List workerInfoChangeListeners = new ArrayList<>(); private final List masterInfoChangeListeners = new ArrayList<>(); @@ -171,6 +175,7 @@ public class ServerNodeManager implements InitializingBean { } else if (type == Type.REMOVE) { log.info("Worker node : {} down.", path); alertDao.sendServerStoppedAlert(1, path, "WORKER"); + listenerEventAlertManager.publishServerDownListenerEvent(path, "WORKER"); } else if (type == Type.UPDATE) { syncSingleWorkerNodeInfo(workerAddress, JSONUtils.parseObject(data, WorkerHeartBeat.class)); } @@ -203,6 +208,7 @@ public class ServerNodeManager implements InitializingBean { } else if (type.equals(Type.REMOVE)) { log.info("master node : {} down.", path); alertDao.sendServerStoppedAlert(1, path, "MASTER"); + listenerEventAlertManager.publishServerDownListenerEvent(path, "MASTER"); } } catch (Exception ex) { log.error("MasterNodeListener capture data change and get data failed.", ex); diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnable.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnable.java index 7bf2f30e8c..00c1515648 100644 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnable.java +++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnable.java @@ -85,6 +85,7 @@ import org.apache.dolphinscheduler.server.master.runner.execute.DefaultTaskExecu import org.apache.dolphinscheduler.server.master.runner.execute.TaskExecuteRunnable; import org.apache.dolphinscheduler.server.master.utils.TaskUtils; import org.apache.dolphinscheduler.server.master.utils.WorkflowInstanceUtils; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.dolphinscheduler.service.alert.ProcessAlertManager; import org.apache.dolphinscheduler.service.command.CommandService; import org.apache.dolphinscheduler.service.cron.CronUtils; @@ -225,6 +226,8 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { private final MasterConfig masterConfig; + private final ListenerEventAlertManager listenerEventAlertManager; + public WorkflowExecuteRunnable( @NonNull IWorkflowExecuteContext workflowExecuteContext, @NonNull CommandService commandService, @@ -235,7 +238,8 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { @NonNull StateWheelExecuteThread stateWheelExecuteThread, @NonNull CuringParamsService curingParamsService, @NonNull TaskInstanceDao taskInstanceDao, - @NonNull DefaultTaskExecuteRunnableFactory defaultTaskExecuteRunnableFactory) { + @NonNull DefaultTaskExecuteRunnableFactory defaultTaskExecuteRunnableFactory, + @NonNull ListenerEventAlertManager listenerEventAlertManager) { this.processService = processService; this.commandService = commandService; this.processInstanceDao = processInstanceDao; @@ -246,6 +250,7 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { this.curingParamsService = curingParamsService; this.taskInstanceDao = taskInstanceDao; this.defaultTaskExecuteRunnableFactory = defaultTaskExecuteRunnableFactory; + this.listenerEventAlertManager = listenerEventAlertManager; TaskMetrics.registerTaskPrepared(readyToSubmitTaskQueue::size); } @@ -372,6 +377,17 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { return true; } } + public void processStart() { + ProcessInstance workflowInstance = workflowExecuteContext.getWorkflowInstance(); + ProjectUser projectUser = processService.queryProjectWithUserByProcessInstanceId(workflowInstance.getId()); + this.listenerEventAlertManager.publishProcessStartListenerEvent(workflowInstance, projectUser); + } + + public void taskStart(TaskInstance taskInstance) { + ProcessInstance workflowInstance = workflowExecuteContext.getWorkflowInstance(); + ProjectUser projectUser = processService.queryProjectWithUserByProcessInstanceId(workflowInstance.getId()); + this.listenerEventAlertManager.publishTaskStartListenerEvent(workflowInstance, taskInstance, projectUser); + } public void processTimeout() { ProcessInstance workflowInstance = workflowExecuteContext.getWorkflowInstance(); @@ -398,6 +414,9 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { completeTaskSet.add(taskInstance.getTaskCode()); mergeTaskInstanceVarPool(taskInstance); processInstanceDao.upsertProcessInstance(workflowInstance); + ProjectUser projectUser = + processService.queryProjectWithUserByProcessInstanceId(workflowInstance.getId()); + listenerEventAlertManager.publishTaskEndListenerEvent(workflowInstance, taskInstance, projectUser); // save the cacheKey only if the task is defined as cache task and the task is success if (taskInstance.getIsCache().equals(Flag.YES)) { saveCacheTaskInstance(taskInstance); @@ -411,6 +430,9 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { retryTaskInstance(taskInstance); } else if (taskInstance.getState().isFailure()) { completeTaskSet.add(taskInstance.getTaskCode()); + ProjectUser projectUser = + processService.queryProjectWithUserByProcessInstanceId(workflowInstance.getId()); + listenerEventAlertManager.publishTaskFailListenerEvent(workflowInstance, taskInstance, projectUser); // There are child nodes and the failure policy is: CONTINUE if (workflowInstance.getFailureStrategy() == FailureStrategy.CONTINUE && DagHelper.haveAllNodeAfterNode( taskInstance.getTaskCode(), @@ -725,6 +747,7 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { log.info("workflowStatue changed to :{}", workflowRunnableStatus); } if (workflowRunnableStatus == WorkflowRunnableStatus.INITIALIZE_QUEUE) { + processStart(); submitPostNode(null); workflowRunnableStatus = WorkflowRunnableStatus.STARTED; log.info("workflowStatue changed to :{}", workflowRunnableStatus); @@ -753,6 +776,9 @@ public class WorkflowExecuteRunnable implements IWorkflowExecuteRunnable { processAlertManager.sendAlertProcessInstance(workflowInstance, getValidTaskList(), projectUser); if (workflowInstance.getState().isSuccess()) { processAlertManager.closeAlert(workflowInstance); + listenerEventAlertManager.publishProcessEndListenerEvent(workflowInstance, projectUser); + } else { + listenerEventAlertManager.publishProcessFailListenerEvent(workflowInstance, projectUser); } if (checkTaskQueue()) { // release task group diff --git a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableFactory.java b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableFactory.java index ed4fb8855b..fcd2a5f721 100644 --- a/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableFactory.java +++ b/dolphinscheduler-master/src/main/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableFactory.java @@ -23,6 +23,7 @@ import org.apache.dolphinscheduler.dao.repository.TaskInstanceDao; import org.apache.dolphinscheduler.server.master.config.MasterConfig; import org.apache.dolphinscheduler.server.master.exception.WorkflowCreateException; import org.apache.dolphinscheduler.server.master.runner.execute.DefaultTaskExecuteRunnableFactory; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.dolphinscheduler.service.alert.ProcessAlertManager; import org.apache.dolphinscheduler.service.command.CommandService; import org.apache.dolphinscheduler.service.expand.CuringParamsService; @@ -69,6 +70,9 @@ public class WorkflowExecuteRunnableFactory { @Autowired private WorkflowExecuteContextFactory workflowExecuteContextFactory; + @Autowired + private ListenerEventAlertManager listenerEventAlertManager; + public Optional createWorkflowExecuteRunnable(Command command) throws WorkflowCreateException { try { Optional workflowExecuteRunnableContextOptional = @@ -83,7 +87,8 @@ public class WorkflowExecuteRunnableFactory { stateWheelExecuteThread, curingGlobalParamsService, taskInstanceDao, - defaultTaskExecuteRunnableFactory)); + defaultTaskExecuteRunnableFactory, + listenerEventAlertManager)); } catch (Exception ex) { throw new WorkflowCreateException("Create workflow execute runnable failed", ex); } diff --git a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableTest.java b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableTest.java index 9599478f4a..d121d7e198 100644 --- a/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableTest.java +++ b/dolphinscheduler-master/src/test/java/org/apache/dolphinscheduler/server/master/runner/WorkflowExecuteRunnableTest.java @@ -40,6 +40,7 @@ import org.apache.dolphinscheduler.server.master.config.MasterConfig; import org.apache.dolphinscheduler.server.master.graph.IWorkflowGraph; import org.apache.dolphinscheduler.server.master.runner.execute.DefaultTaskExecuteRunnableFactory; import org.apache.dolphinscheduler.server.master.runner.execute.TaskExecuteRunnable; +import org.apache.dolphinscheduler.service.alert.ListenerEventAlertManager; import org.apache.dolphinscheduler.service.alert.ProcessAlertManager; import org.apache.dolphinscheduler.service.bean.SpringApplicationContext; import org.apache.dolphinscheduler.service.command.CommandService; @@ -102,6 +103,8 @@ public class WorkflowExecuteRunnableTest { private WorkflowExecuteContextFactory workflowExecuteContextFactory; + private ListenerEventAlertManager listenerEventAlertManager; + @BeforeEach public void init() throws Exception { applicationContext = Mockito.mock(ApplicationContext.class); @@ -117,6 +120,7 @@ public class WorkflowExecuteRunnableTest { taskDefinitionLogDao = Mockito.mock(TaskDefinitionLogDao.class); defaultTaskExecuteRunnableFactory = Mockito.mock(DefaultTaskExecuteRunnableFactory.class); workflowExecuteContextFactory = Mockito.mock(WorkflowExecuteContextFactory.class); + listenerEventAlertManager = Mockito.mock(ListenerEventAlertManager.class); Map cmdParam = new HashMap<>(); cmdParam.put(CMD_PARAM_COMPLEMENT_DATA_START_DATE, "2020-01-01 00:00:00"); @@ -146,7 +150,8 @@ public class WorkflowExecuteRunnableTest { stateWheelExecuteThread, curingGlobalParamsService, taskInstanceDao, - defaultTaskExecuteRunnableFactory)); + defaultTaskExecuteRunnableFactory, + listenerEventAlertManager)); } @Test diff --git a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManager.java b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManager.java new file mode 100644 index 0000000000..182ed678a0 --- /dev/null +++ b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManager.java @@ -0,0 +1,278 @@ +/* + * 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.service.alert; + +import org.apache.dolphinscheduler.common.enums.AlertStatus; +import org.apache.dolphinscheduler.common.enums.ListenerEventType; +import org.apache.dolphinscheduler.common.utils.JSONUtils; +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.ListenerEvent; +import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; +import org.apache.dolphinscheduler.dao.entity.ProcessInstance; +import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; +import org.apache.dolphinscheduler.dao.entity.Project; +import org.apache.dolphinscheduler.dao.entity.ProjectUser; +import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; +import org.apache.dolphinscheduler.dao.entity.TaskInstance; +import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.entity.event.AbstractListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionCreatedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionDeletedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessDefinitionUpdatedListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessEndListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessFailListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ProcessStartListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.ServerDownListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskEndListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskFailListenerEvent; +import org.apache.dolphinscheduler.dao.entity.event.TaskStartListenerEvent; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; +import org.apache.dolphinscheduler.dao.mapper.ListenerEventMapper; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.collections4.CollectionUtils; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class ListenerEventAlertManager { + + @Value("${alert.alarm-suppression.crash:60}") + private int crashAlarmSuppression; + + @Autowired + private ListenerEventMapper listenerEventMapper; + + @Autowired + private AlertPluginInstanceMapper alertPluginInstanceMapper; + + public void publishServerDownListenerEvent(String host, String type) { + ServerDownListenerEvent event = new ServerDownListenerEvent(); + event.setEventTime(new Date()); + event.setHost(host); + event.setType(type); + this.saveEvent(event); + } + + public void publishProcessDefinitionCreatedListenerEvent(User user, + ProcessDefinition processDefinition, + List taskDefinitionLogs, + List processTaskRelationLogs) { + ProcessDefinitionCreatedListenerEvent event = new ProcessDefinitionCreatedListenerEvent(processDefinition); + event.setUserName(user.getUserName()); + event.setModifyBy(user.getUserName()); + event.setTaskDefinitionLogs(taskDefinitionLogs); + event.setTaskRelationList(processTaskRelationLogs); + this.saveEvent(event); + } + + public void publishProcessDefinitionUpdatedListenerEvent(User user, ProcessDefinition processDefinition, + List taskDefinitionLogs, + List processTaskRelationLogs) { + ProcessDefinitionUpdatedListenerEvent event = new ProcessDefinitionUpdatedListenerEvent(processDefinition); + event.setTaskDefinitionLogs(taskDefinitionLogs); + event.setTaskRelationList(processTaskRelationLogs); + event.setUserName(user.getUserName()); + event.setModifyBy(user.getUserName()); + this.saveEvent(event); + } + + public void publishProcessDefinitionDeletedListenerEvent(User user, Project project, + ProcessDefinition processDefinition) { + ProcessDefinitionDeletedListenerEvent event = new ProcessDefinitionDeletedListenerEvent(); + event.setProjectId(project.getId()); + event.setProjectCode(project.getCode()); + event.setProjectName(project.getName()); + event.setOwner(processDefinition.getUserName()); + event.setId(processDefinition.getId()); + event.setCode(processDefinition.getCode()); + event.setName(processDefinition.getName()); + event.setEventTime(new Date()); + event.setUserId(user.getId()); + event.setModifiedBy(user.getUserName()); + this.saveEvent(event); + } + + public void publishProcessStartListenerEvent(ProcessInstance processInstance, ProjectUser projectUser) { + ProcessStartListenerEvent event = new ProcessStartListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setProcessType(processInstance.getCommandType()); + event.setProcessState(processInstance.getState()); + event.setRunTimes(processInstance.getRunTimes()); + event.setRecovery(processInstance.getRecovery()); + event.setProcessStartTime(processInstance.getStartTime()); + this.saveEvent(event); + } + + public void publishProcessEndListenerEvent(ProcessInstance processInstance, ProjectUser projectUser) { + ProcessEndListenerEvent event = new ProcessEndListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setProcessType(processInstance.getCommandType()); + event.setProcessState(processInstance.getState()); + event.setRecovery(processInstance.getRecovery()); + event.setRunTimes(processInstance.getRunTimes()); + event.setProcessStartTime(processInstance.getStartTime()); + event.setProcessEndTime(processInstance.getEndTime()); + event.setProcessHost(processInstance.getHost()); + this.saveEvent(event); + } + + public void publishProcessFailListenerEvent(ProcessInstance processInstance, + ProjectUser projectUser) { + ProcessFailListenerEvent event = new ProcessFailListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setProcessType(processInstance.getCommandType()); + event.setProcessState(processInstance.getState()); + event.setRecovery(processInstance.getRecovery()); + event.setRunTimes(processInstance.getRunTimes()); + event.setProcessStartTime(processInstance.getStartTime()); + event.setProcessEndTime(processInstance.getEndTime()); + event.setProcessHost(processInstance.getHost()); + this.saveEvent(event); + } + + public void publishTaskStartListenerEvent(ProcessInstance processInstance, + TaskInstance taskInstance, + ProjectUser projectUser) { + TaskStartListenerEvent event = new TaskStartListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setTaskCode(taskInstance.getTaskCode()); + event.setTaskName(taskInstance.getName()); + event.setTaskType(taskInstance.getTaskType()); + event.setTaskState(taskInstance.getState()); + event.setTaskStartTime(taskInstance.getStartTime()); + event.setTaskEndTime(taskInstance.getEndTime()); + event.setTaskHost(taskInstance.getHost()); + event.setLogPath(taskInstance.getLogPath()); + this.saveEvent(event); + } + + public void publishTaskEndListenerEvent(ProcessInstance processInstance, + TaskInstance taskInstance, + ProjectUser projectUser) { + TaskEndListenerEvent event = new TaskEndListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setTaskCode(taskInstance.getTaskCode()); + event.setTaskName(taskInstance.getName()); + event.setTaskType(taskInstance.getTaskType()); + event.setTaskState(taskInstance.getState()); + event.setTaskStartTime(taskInstance.getStartTime()); + event.setTaskEndTime(taskInstance.getEndTime()); + event.setTaskHost(taskInstance.getHost()); + event.setLogPath(taskInstance.getLogPath()); + this.saveEvent(event); + } + + public void publishTaskFailListenerEvent(ProcessInstance processInstance, + TaskInstance taskInstance, + ProjectUser projectUser) { + TaskFailListenerEvent event = new TaskFailListenerEvent(); + event.setProjectCode(projectUser.getProjectCode()); + event.setProjectName(projectUser.getProjectName()); + event.setOwner(projectUser.getUserName()); + event.setProcessId(processInstance.getId()); + event.setProcessDefinitionCode(processInstance.getProcessDefinitionCode()); + event.setProcessName(processInstance.getName()); + event.setTaskCode(taskInstance.getTaskCode()); + event.setTaskName(taskInstance.getName()); + event.setTaskType(taskInstance.getTaskType()); + event.setTaskState(taskInstance.getState()); + event.setTaskStartTime(taskInstance.getStartTime()); + event.setTaskEndTime(taskInstance.getEndTime()); + event.setTaskHost(taskInstance.getHost()); + event.setLogPath(taskInstance.getLogPath()); + this.saveEvent(event); + } + + private void saveEvent(AbstractListenerEvent event) { + if (!needSendGlobalListenerEvent()) { + return; + } + ListenerEvent listenerEvent = new ListenerEvent(); + String content = JSONUtils.toJsonString(event); + listenerEvent.setContent(content); + listenerEvent.setPostStatus(AlertStatus.WAIT_EXECUTION); + listenerEvent.setSign(generateSign(content)); + listenerEvent.setCreateTime(new Date()); + listenerEvent.setUpdateTime(new Date()); + listenerEvent.setEventType(event.getEventType()); + if (event.getEventType() == ListenerEventType.SERVER_DOWN) { + saveServerDownEvent(listenerEvent); + } else { + saveNormalEvent(listenerEvent); + } + } + + private void saveNormalEvent(ListenerEvent listenerEvent) { + int insert = listenerEventMapper.insert(listenerEvent); + if (insert < 1) { + log.error("insert listener event failed: {}", listenerEvent); + } + } + + private void saveServerDownEvent(ListenerEvent listenerEvent) { + Date crashAlarmSuppressionStartTime = Date.from( + LocalDateTime.now().plusMinutes(-crashAlarmSuppression).atZone(ZoneId.systemDefault()).toInstant()); + listenerEventMapper.insertServerDownEvent(listenerEvent, crashAlarmSuppressionStartTime); + } + + private String generateSign(String content) { + return DigestUtils.sha256Hex(content).toLowerCase(); + } + + private boolean needSendGlobalListenerEvent() { + List globalPluginInstanceList = + alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList(); + return CollectionUtils.isNotEmpty(globalPluginInstanceList); + } +} diff --git a/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManagerTest.java b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManagerTest.java new file mode 100644 index 0000000000..981b0a8050 --- /dev/null +++ b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/alert/ListenerEventAlertManagerTest.java @@ -0,0 +1,148 @@ +/* + * 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.service.alert; + +import static org.mockito.ArgumentMatchers.any; + +import org.apache.dolphinscheduler.dao.entity.AlertPluginInstance; +import org.apache.dolphinscheduler.dao.entity.ProcessDefinition; +import org.apache.dolphinscheduler.dao.entity.ProcessInstance; +import org.apache.dolphinscheduler.dao.entity.ProcessTaskRelationLog; +import org.apache.dolphinscheduler.dao.entity.Project; +import org.apache.dolphinscheduler.dao.entity.ProjectUser; +import org.apache.dolphinscheduler.dao.entity.TaskDefinitionLog; +import org.apache.dolphinscheduler.dao.entity.TaskInstance; +import org.apache.dolphinscheduler.dao.entity.User; +import org.apache.dolphinscheduler.dao.mapper.AlertPluginInstanceMapper; +import org.apache.dolphinscheduler.dao.mapper.ListenerEventMapper; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ProcessAlertManager Test + */ +@ExtendWith(MockitoExtension.class) +public class ListenerEventAlertManagerTest { + + private static final Logger logger = LoggerFactory.getLogger(ListenerEventAlertManagerTest.class); + + @InjectMocks + ListenerEventAlertManager listenerEventAlertManager; + + @Mock + AlertPluginInstanceMapper alertPluginInstanceMapper; + + @Mock + ListenerEventMapper listenerEventMapper; + + @Test + public void sendServerDownListenerEventTest() { + String host = "127.0.0.1"; + String type = "WORKER"; + List globalPluginInstanceList = new ArrayList<>(); + AlertPluginInstance instance = new AlertPluginInstance(1, "instanceParams", "instanceName"); + globalPluginInstanceList.add(instance); + Mockito.when(alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList()) + .thenReturn(globalPluginInstanceList); + Mockito.doNothing().when(listenerEventMapper).insertServerDownEvent(any(), any()); + listenerEventAlertManager.publishServerDownListenerEvent(host, type); + } + + @Test + public void sendProcessDefinitionCreatedListenerEvent() { + User user = Mockito.mock(User.class); + ProcessDefinition processDefinition = Mockito.mock(ProcessDefinition.class); + List taskDefinitionLogs = new ArrayList<>(); + List processTaskRelationLogs = new ArrayList<>(); + AlertPluginInstance instance = new AlertPluginInstance(1, "instanceParams", "instanceName"); + List globalPluginInstanceList = new ArrayList<>(); + globalPluginInstanceList.add(instance); + Mockito.when(alertPluginInstanceMapper.queryAllGlobalAlertPluginInstanceList()) + .thenReturn(globalPluginInstanceList); + Mockito.when(listenerEventMapper.insert(any())).thenReturn(1); + listenerEventAlertManager.publishProcessDefinitionCreatedListenerEvent(user, processDefinition, + taskDefinitionLogs, processTaskRelationLogs); + } + @Test + public void sendProcessDefinitionUpdatedListenerEvent() { + User user = new User(); + ProcessDefinition processDefinition = new ProcessDefinition(); + List taskDefinitionLogs = new ArrayList<>(); + List processTaskRelationLogs = new ArrayList<>(); + listenerEventAlertManager.publishProcessDefinitionUpdatedListenerEvent(user, processDefinition, + taskDefinitionLogs, processTaskRelationLogs); + } + + @Test + public void sendProcessDefinitionDeletedListenerEvent() { + User user = new User(); + Project project = new Project(); + ProcessDefinition processDefinition = new ProcessDefinition(); + listenerEventAlertManager.publishProcessDefinitionDeletedListenerEvent(user, project, processDefinition); + } + + @Test + public void sendProcessStartListenerEvent() { + ProcessInstance processInstance = new ProcessInstance(); + ProjectUser projectUser = new ProjectUser(); + listenerEventAlertManager.publishProcessStartListenerEvent(processInstance, projectUser); + } + @Test + public void sendProcessEndListenerEvent() { + ProcessInstance processInstance = new ProcessInstance(); + ProjectUser projectUser = new ProjectUser(); + listenerEventAlertManager.publishProcessEndListenerEvent(processInstance, projectUser); + } + @Test + public void sendProcessFailListenerEvent() { + ProcessInstance processInstance = new ProcessInstance(); + ProjectUser projectUser = new ProjectUser(); + listenerEventAlertManager.publishProcessFailListenerEvent(processInstance, projectUser); + } + @Test + public void sendTaskStartListenerEvent() { + ProcessInstance processInstance = Mockito.mock(ProcessInstance.class); + TaskInstance taskInstance = Mockito.mock(TaskInstance.class); + ProjectUser projectUser = Mockito.mock(ProjectUser.class); + listenerEventAlertManager.publishTaskStartListenerEvent(processInstance, taskInstance, projectUser); + } + @Test + public void sendTaskEndListenerEvent() { + ProcessInstance processInstance = Mockito.mock(ProcessInstance.class); + TaskInstance taskInstance = Mockito.mock(TaskInstance.class); + ProjectUser projectUser = Mockito.mock(ProjectUser.class); + listenerEventAlertManager.publishTaskEndListenerEvent(processInstance, taskInstance, projectUser); + } + @Test + public void sendTaskFailListenerEvent() { + ProcessInstance processInstance = Mockito.mock(ProcessInstance.class); + TaskInstance taskInstance = Mockito.mock(TaskInstance.class); + ProjectUser projectUser = Mockito.mock(ProjectUser.class); + listenerEventAlertManager.publishTaskFailListenerEvent(processInstance, taskInstance, projectUser); + } +} diff --git a/dolphinscheduler-standalone-server/src/main/resources/application.yaml b/dolphinscheduler-standalone-server/src/main/resources/application.yaml index dda509733e..23aaf313ba 100644 --- a/dolphinscheduler-standalone-server/src/main/resources/application.yaml +++ b/dolphinscheduler-standalone-server/src/main/resources/application.yaml @@ -223,6 +223,7 @@ alert: # Define value is (0 = infinite), and alert server would be waiting alert result. wait-timeout: 0 heartbeat-interval: 60s + query_alert_threshold: 100 api: audit-enable: false diff --git a/dolphinscheduler-ui/src/locales/en_US/security.ts b/dolphinscheduler-ui/src/locales/en_US/security.ts index 3b8e47586d..d8fe8ec79b 100644 --- a/dolphinscheduler-ui/src/locales/en_US/security.ts +++ b/dolphinscheduler-ui/src/locales/en_US/security.ts @@ -204,6 +204,8 @@ export default { alarm_instance_name: 'Alarm instance name', alarm_instance_name_tips: 'Please enter alarm plugin instance name', alarm_plugin_name: 'Alarm plugin name', + alarm_instance_type: 'Alarm instance type', + is_global_instance: 'Is Global Instance', create_time: 'Create Time', update_time: 'Update Time', operation: 'Operation', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/security.ts b/dolphinscheduler-ui/src/locales/zh_CN/security.ts index d015730d8c..279ef0eb42 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/security.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/security.ts @@ -201,6 +201,8 @@ export default { alarm_instance_name: '告警实例名称', alarm_instance_name_tips: '请输入告警实例名称', alarm_plugin_name: '告警插件名称', + alarm_instance_type: '告警实例类型', + is_global_instance: '是否全局告警实例', create_time: '创建时间', update_time: '更新时间', operation: '操作', diff --git a/dolphinscheduler-ui/src/service/modules/alert-group/index.ts b/dolphinscheduler-ui/src/service/modules/alert-group/index.ts index b9da6292de..705d306132 100644 --- a/dolphinscheduler-ui/src/service/modules/alert-group/index.ts +++ b/dolphinscheduler-ui/src/service/modules/alert-group/index.ts @@ -41,6 +41,13 @@ export function listAlertGroupById(): any { }) } +export function listNormalAlertGroupById(): any { + return axios({ + url: '/alert-groups/normal-list', + method: 'get' + }) +} + export function queryAlertGroupById(data: IdReq): any { return axios({ url: '/alert-groups/query', diff --git a/dolphinscheduler-ui/src/service/modules/alert-plugin/types.ts b/dolphinscheduler-ui/src/service/modules/alert-plugin/types.ts index dca86a4501..ff977af5ab 100644 --- a/dolphinscheduler-ui/src/service/modules/alert-plugin/types.ts +++ b/dolphinscheduler-ui/src/service/modules/alert-plugin/types.ts @@ -24,6 +24,8 @@ interface ListReq { interface PluginInstanceReq { instanceName: string pluginDefineId: number + instanceType: string + warningType: string pluginInstanceParams: string } @@ -34,6 +36,7 @@ interface InstanceNameReq { interface UpdatePluginInstanceReq { alertPluginInstanceId: number instanceName: string + warningType: string pluginInstanceParams: string } diff --git a/dolphinscheduler-ui/src/views/projects/preference/components/use-alert-group.ts b/dolphinscheduler-ui/src/views/projects/preference/components/use-alert-group.ts index 323c3374f4..6b486ca764 100644 --- a/dolphinscheduler-ui/src/views/projects/preference/components/use-alert-group.ts +++ b/dolphinscheduler-ui/src/views/projects/preference/components/use-alert-group.ts @@ -18,7 +18,7 @@ import { ref, onMounted } from 'vue' import { useI18n } from 'vue-i18n' import type { IJsonItem } from '../../task/components/node/types' -import { listAlertGroupById } from '@/service/modules/alert-group' +import { listNormalAlertGroupById } from '@/service/modules/alert-group' export function useAlertGroup(): IJsonItem { const { t } = useI18n() @@ -26,7 +26,7 @@ export function useAlertGroup(): IJsonItem { const options = ref([] as { label: string; value: string }[]) const getAlertGroups = async () => { - const res = await listAlertGroupById() + const res = await listNormalAlertGroupById() options.value = res.map((item: any) => ({ label: item.groupName, value: item.id diff --git a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts index 1e93c9e208..f54b922b00 100644 --- a/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts +++ b/dolphinscheduler-ui/src/views/projects/task/components/node/fields/use-sql-type.ts @@ -17,7 +17,7 @@ import { ref, onMounted, computed, h } from 'vue' import { useI18n } from 'vue-i18n' -import { listAlertGroupById } from '@/service/modules/alert-group' +import { listNormalAlertGroupById } from '@/service/modules/alert-group' import styles from '../index.module.scss' import type { IJsonItem } from '../types' @@ -43,7 +43,7 @@ export function useSqlType(model: { [field: string]: any }): IJsonItem[] { const getGroups = async () => { if (groupsLoading.value) return groupsLoading.value = true - const res = await listAlertGroupById() + const res = await listNormalAlertGroupById() groups.value = res.map((item: { id: number; groupName: string }) => ({ label: item.groupName, value: item.id diff --git a/dolphinscheduler-ui/src/views/projects/task/definition/components/use-start.tsx b/dolphinscheduler-ui/src/views/projects/task/definition/components/use-start.tsx index e7b4340e4a..f824a4dba8 100644 --- a/dolphinscheduler-ui/src/views/projects/task/definition/components/use-start.tsx +++ b/dolphinscheduler-ui/src/views/projects/task/definition/components/use-start.tsx @@ -24,7 +24,7 @@ import { queryProcessDefinitionByCode } from '@/service/modules/process-definiti import { queryAllWorkerGroups } from '@/service/modules/worker-groups' import { queryTenantList } from '@/service/modules/tenants' import { queryAllEnvironmentList } from '@/service/modules/environment' -import { listAlertGroupById } from '@/service/modules/alert-group' +import { listNormalAlertGroupById } from '@/service/modules/alert-group' import type { EnvironmentItem } from '@/service/modules/environment/types' import type { IStartState } from '../types' @@ -90,7 +90,7 @@ export const useStart = ( } const getAlertGroups = () => { - listAlertGroupById().then((res: any) => { + listNormalAlertGroupById().then((res: any) => { variables.startState.alertGroups = res.map((item: any) => ({ label: item.groupName, value: item.id diff --git a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-startup-param.tsx b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-startup-param.tsx index 0887f2324f..65b2cb297f 100644 --- a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-startup-param.tsx +++ b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/dag-startup-param.tsx @@ -18,7 +18,7 @@ import _ from 'lodash' import { defineComponent, onMounted, PropType, ref, computed } from 'vue' import { useI18n } from 'vue-i18n' -import { listAlertGroupById } from '@/service/modules/alert-group' +import { listNormalAlertGroupById } from '@/service/modules/alert-group' import { queryAllWorkerGroups } from '@/service/modules/worker-groups' import { runningType, warningTypeList } from '@/common/common' import { IStartupParam } from './types' @@ -42,7 +42,7 @@ export default defineComponent({ const commandParam = JSON.parse(props.startupParam?.commandParam || '{}') const getAlertGroupList = () => { - listAlertGroupById().then((res: any) => { + listNormalAlertGroupById().then((res: any) => { alertGroupListRef.value = res }) } diff --git a/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-modal.ts b/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-modal.ts index fa1336909e..cc818103fd 100644 --- a/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-modal.ts +++ b/dolphinscheduler-ui/src/views/projects/workflow/definition/components/use-modal.ts @@ -28,7 +28,7 @@ import { } from '@/service/modules/process-definition' import { queryAllWorkerGroups } from '@/service/modules/worker-groups' import { queryAllEnvironmentList } from '@/service/modules/environment' -import { listAlertGroupById } from '@/service/modules/alert-group' +import { listNormalAlertGroupById } from '@/service/modules/alert-group' import { startProcessInstance } from '@/service/modules/executors' import { createSchedule, @@ -256,7 +256,7 @@ export function useModal( } const getAlertGroups = () => { - listAlertGroupById().then((res: any) => { + listNormalAlertGroupById().then((res: any) => { variables.alertGroups = res.map((item: any) => ({ label: item.groupName, value: item.id diff --git a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx index 9702bc75b2..86e39a27f2 100644 --- a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx +++ b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/detail.tsx @@ -23,7 +23,7 @@ import { ref, getCurrentInstance } from 'vue' -import { NSelect, NInput } from 'naive-ui' +import { NSelect, NInput, NSwitch, NRadioGroup, NSpace, NRadio } from 'naive-ui' import { isFunction } from 'lodash' import { useI18n } from 'vue-i18n' import { useForm } from './use-form' @@ -57,6 +57,7 @@ const DetailModal = defineComponent({ const rules = ref({}) const elements = ref([]) as IElements + const warningTypeSpan = ref(24) const { meta, @@ -95,6 +96,10 @@ const DetailModal = defineComponent({ props.show && props.currentRecord && setDetail(props.currentRecord) } ) + watch( + () => state.detailForm.instanceType, + () => warningTypeSpan.value = state.detailForm.instanceType === 'GLOBAL' ? 0 : 24 + ) watch( () => state.json, () => { @@ -121,6 +126,7 @@ const DetailModal = defineComponent({ ...toRefs(state), ...toRefs(status), meta, + warningTypeSpan, rules, elements, onChangePlugin, @@ -134,6 +140,7 @@ const DetailModal = defineComponent({ show, t, meta, + warningTypeSpan, rules, elements, detailForm, @@ -183,6 +190,38 @@ const DetailModal = defineComponent({ /> ) }, + { + path: 'instanceType', + label: t('security.alarm_instance.is_global_instance'), + widget: ( + + ) + }, + { + path: 'warningType', + label: t('security.alarm_instance.WarningType'), + span: warningTypeSpan, + widget: ( + + + + {"success"} + + + {"failure"} + + + {"all"} + + + + ) + }, { path: 'pluginDefineId', label: t('security.alarm_instance.select_plugin'), diff --git a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/types.ts b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/types.ts index 6dd54959c5..9abf03b93c 100644 --- a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/types.ts +++ b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/types.ts @@ -29,6 +29,8 @@ interface IRecord { createTime?: string id: number instanceName: string + instanceType: string + warningType: string pluginDefineId: number pluginInstanceParams?: string updateTime?: string diff --git a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-columns.ts b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-columns.ts index 86121592a8..875ce7a89a 100644 --- a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-columns.ts +++ b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-columns.ts @@ -35,6 +35,10 @@ export function useColumns(onCallback: Function) { title: t('security.alarm_instance.alarm_instance_name'), key: 'instanceName' }, + { + title: t('security.alarm_instance.alarm_instance_type'), + key: 'instanceType' + }, { title: t('security.alarm_instance.alarm_plugin_name'), key: 'alertPluginName' diff --git a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-detail.ts b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-detail.ts index 8f35dc153e..c6ac01a528 100644 --- a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-detail.ts +++ b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-detail.ts @@ -58,6 +58,7 @@ export function useDetail(getFormValues: Function) { { alertPluginInstanceId: values.pluginDefineId, instanceName: values.instanceName, + warningType: values.warningType, pluginInstanceParams: formatParams(json, values) }, currentRecord.id @@ -65,6 +66,8 @@ export function useDetail(getFormValues: Function) { : await createAlertPluginInstance({ instanceName: values.instanceName, pluginDefineId: values.pluginDefineId, + instanceType: values.instanceType, + warningType: values.warningType, pluginInstanceParams: formatParams(json, values) }) diff --git a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-form.ts b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-form.ts index 959361c38e..5e14148f2d 100644 --- a/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-form.ts +++ b/dolphinscheduler-ui/src/views/security/alarm-instance-manage/use-form.ts @@ -35,7 +35,9 @@ export function useForm() { const initialValues = { instanceName: '', - pluginDefineId: null + pluginDefineId: null, + instanceType: 'NORMAL', + warningType: 'ALL' } const state = reactive({ @@ -44,7 +46,7 @@ export function useForm() { uiPlugins: [], pluginsLoading: false, json: [] - } as { detailFormRef: Ref; json: IJsonItem[]; detailForm: { instanceName: string; pluginDefineId: number | null }; pluginsLoading: boolean; uiPlugins: [] }) + } as { detailFormRef: Ref; json: IJsonItem[]; detailForm: { instanceName: string; pluginDefineId: number | null; instanceType: string; warningType: string }; pluginsLoading: boolean; uiPlugins: [] }) const meta = { model: state.detailForm, @@ -109,6 +111,8 @@ export function useForm() { const setDetail = (record: IRecord) => { state.detailForm.instanceName = record.instanceName state.detailForm.pluginDefineId = record.pluginDefineId + state.detailForm.instanceType = record.instanceType + state.detailForm.warningType = record.warningType if (record.pluginInstanceParams) state.json = JSON.parse(record.pluginInstanceParams) }