Skip to content

Commit

Permalink
[Feature] Add Alert Task Owner Functionality (DataLinkDC#3623)
Browse files Browse the repository at this point in the history
Co-authored-by: luoshangjie <[email protected]>
Co-authored-by: 18216499322 <[email protected]>
  • Loading branch information
3 people authored Jul 3, 2024
1 parent c3eeec4 commit c2163b8
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 2 deletions.
8 changes: 8 additions & 0 deletions dinky-admin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>
<dependency>
<groupId>org.dinky</groupId>
<artifactId>dinky-alert-dingtalk</artifactId>
</dependency>
<dependency>
<groupId>org.dinky</groupId>
<artifactId>dinky-alert-sms</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
101 changes: 99 additions & 2 deletions dinky-admin/src/main/java/org/dinky/job/handler/JobAlertHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import org.dinky.alert.Alert;
import org.dinky.alert.AlertConfig;
import org.dinky.alert.AlertResult;
import org.dinky.alert.dingtalk.DingTalkConstants;
import org.dinky.alert.sms.SmsConstants;
import org.dinky.assertion.Asserts;
import org.dinky.context.FreeMarkerHolder;
import org.dinky.context.SpringContextUtils;
Expand All @@ -30,6 +32,7 @@
import org.dinky.data.dto.TaskDTO;
import org.dinky.data.enums.JobLifeCycle;
import org.dinky.data.enums.Status;
import org.dinky.data.enums.TaskOwnerAlertStrategyEnum;
import org.dinky.data.exception.DinkyException;
import org.dinky.data.model.Configuration;
import org.dinky.data.model.SystemConfiguration;
Expand All @@ -38,16 +41,21 @@
import org.dinky.data.model.alert.AlertInstance;
import org.dinky.data.model.ext.JobAlertData;
import org.dinky.data.model.ext.JobInfoDetail;
import org.dinky.data.model.rbac.User;
import org.dinky.data.options.JobAlertRuleOptions;
import org.dinky.service.AlertHistoryService;
import org.dinky.service.TaskService;
import org.dinky.service.UserService;
import org.dinky.service.impl.AlertRuleServiceImpl;
import org.dinky.utils.JsonUtils;

import org.apache.commons.compress.utils.Lists;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

Expand All @@ -65,6 +73,7 @@
import com.google.common.cache.LoadingCache;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
Expand All @@ -78,6 +87,7 @@ public class JobAlertHandler {
private static final TaskService taskService;
private static final AlertRuleServiceImpl alertRuleService;
private static final SystemConfiguration systemConfiguration = SystemConfiguration.getInstances();
private static final UserService userService;

/**
* Rules for evaluating alert conditions.
Expand All @@ -103,12 +113,15 @@ public class JobAlertHandler {
*/
private static LoadingCache<Integer, Map<Integer, Integer>> alertCache;

private static LoadingCache<Integer, User> userCache;

private static volatile JobAlertHandler defaultJobAlertHandler;

static {
taskService = SpringContextUtils.getBean("taskServiceImpl", TaskService.class);
alertHistoryService = SpringContextUtils.getBean("alertHistoryServiceImpl", AlertHistoryService.class);
alertRuleService = SpringContextUtils.getBean("alertRuleServiceImpl", AlertRuleServiceImpl.class);
userService = SpringContextUtils.getBean("userServiceImpl", UserService.class);

Configuration<Integer> jobReSendDiffSecond = systemConfiguration.getJobReSendDiffSecond();
jobReSendDiffSecond.addChangeEvent((c) -> {
Expand All @@ -118,6 +131,15 @@ public class JobAlertHandler {
.build(CacheLoader.from(() -> new HashMap<>()));
});
jobReSendDiffSecond.runChangeEvent();

userCache = CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<Integer, User>() {
@Override
public User load(Integer id) { // no checked exception
return userService.getById(id);
}
});
}

public static JobAlertHandler getInstance() {
Expand Down Expand Up @@ -228,12 +250,87 @@ private void executeAlertAction(Facts facts, AlertRuleDTO alertRuleDTO) throws E
String alertContent = freeMarkerHolder.buildWithData(alertRuleDTO.getTemplateName(), dataModel);

if (!Asserts.isNull(task.getAlertGroup())) {
// 获取任务的责任人和维护人对应的用户信息|Get the responsible person and maintainer of the task
User ownerInfo = userCache.get(task.getFirstLevelOwner());
List<User> maintainerInfo = task.getSecondLevelOwners().stream()
.map(id -> {
try {
return userCache.get(id);
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
})
.collect(Collectors.toList());
AlertGroup alertGroup = task.getAlertGroup();
alertGroup.getInstances().stream()
.filter(Objects::nonNull)
.filter(AlertInstance::getEnabled)
.forEach(alertInstance -> sendAlert(
alertInstance, jobInstanceId, alertGroup.getId(), alertRuleDTO.getName(), alertContent));
.forEach(alertInstance -> {
addOwnerAlert(alertInstance, ownerInfo, maintainerInfo);
sendAlert(
alertInstance, jobInstanceId, alertGroup.getId(), alertRuleDTO.getName(), alertContent);
});
}
}

/**
* Add the contact number of the task owner to the phone list of the alarm instance to alert the task owner
* @param alertInstance
* @param ownerInfo
* @param maintainerInfo
*/
private void addOwnerAlert(AlertInstance alertInstance, User ownerInfo, List<User> maintainerInfo) {
List<String> extraMobileList = Lists.newArrayList();
TaskOwnerAlertStrategyEnum value =
SystemConfiguration.getInstances().getTaskOwnerAlertStrategy().getValue();
switch (value) {
case OWNER:
if (ownerInfo != null && ownerInfo.getMobile() != null) {
extraMobileList.add(ownerInfo.getMobile());
}
break;
case OWNER_AND_MAINTAINER:
if (ownerInfo != null && ownerInfo.getMobile() != null) {
extraMobileList.add(ownerInfo.getMobile());
}
extraMobileList.addAll(maintainerInfo.stream()
.filter(user -> Objects.nonNull(user) && StrUtil.isNotBlank(user.getMobile()))
.map(User::getMobile)
.collect(Collectors.toList()));
break;
case NONE:
default:
log.error("Alert Strategy Type: {} is not supported", value);
return;
}
// 获取告警实例的配置参数|Get the configuration parameters of the alert instance
Map<String, Object> alertInstanceParams = alertInstance.getParams();
switch (alertInstance.getType()) {
case DingTalkConstants.TYPE:
Boolean atAll =
(Boolean) alertInstanceParams.getOrDefault(DingTalkConstants.ALERT_TEMPLATE_AT_ALL, false);
if (!atAll) {
// 重新构告警实例的告警人员|Rebuild the alert personnel of the alert instance
List<String> atMobiles =
(List<String>) alertInstanceParams.get(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILES);
atMobiles.addAll(extraMobileList.stream()
.filter(mobile -> !atMobiles.contains(mobile))
.collect(Collectors.toList()));
alertInstanceParams.put(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILES, atMobiles);
alertInstance.setParams(alertInstanceParams);
}
break;
case SmsConstants.TYPE:
// 重新构告警实例的告警人员|Rebuild the alert personnel of the alert instance
List<String> phoneNumbers = (List<String>) alertInstanceParams.get(SmsConstants.PHONE_NUMBERS);
phoneNumbers.addAll(extraMobileList.stream()
.filter(mobile -> !phoneNumbers.contains(mobile))
.collect(Collectors.toList()));
alertInstanceParams.put(DingTalkConstants.ALERT_TEMPLATE_AT_MOBILES, phoneNumbers);
alertInstance.setParams(alertInstanceParams);
break;
default:
}
}

Expand Down
2 changes: 2 additions & 0 deletions dinky-common/src/main/java/org/dinky/data/enums/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ public enum Status {
SYS_ENV_SETTINGS_EXPRESSION_VARIABLE_NOTE(1176, "sys.env.settings.expressionVariable.note"),
SYS_ENV_SETTINGS_TASK_OWNER_LOCK_STRATEGY(1177, "sys.env.settings.taskOwnerLockStrategy"),
SYS_ENV_SETTINGS_TASK_OWNER_LOCK_STRATEGY_NOTE(1178, "sys.env.settings.taskOwnerLockStrategy.note"),
SYS_ENV_SETTINGS_TASK_OWNER_ALERT_STRATEGY(1179, "sys.env.settings.taskOwnerAlertStrategy"),
SYS_ENV_SETTINGS_TASK_OWNER_ALERT_STRATEGY_NOTE(1180, "sys.env.settings.taskOwnerAlertStrategy.note"),

SYS_DOLPHINSCHEDULER_SETTINGS_ENABLE(118, "sys.dolphinscheduler.settings.enable"),
SYS_DOLPHINSCHEDULER_SETTINGS_ENABLE_NOTE(119, "sys.dolphinscheduler.settings.enable.note"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.dinky.data.enums;

/** Business Operation Types */
public enum TaskOwnerAlertStrategyEnum {
/** Alert includes responsible person */
OWNER,

/** Alert includes responsible person and maintainer */
OWNER_AND_MAINTAINER,

/** Alert does not include responsible person and maintainer */
NONE,
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.dinky.context.EngineContextHolder;
import org.dinky.data.constant.CommonConstant;
import org.dinky.data.enums.Status;
import org.dinky.data.enums.TaskOwnerAlertStrategyEnum;
import org.dinky.data.enums.TaskOwnerLockStrategyEnum;
import org.dinky.data.properties.OssProperties;

Expand Down Expand Up @@ -139,6 +140,12 @@ public static Configuration.OptionBuilder key(Status status) {
.defaultValue(TaskOwnerLockStrategyEnum.ALL)
.note(Status.SYS_ENV_SETTINGS_TASK_OWNER_LOCK_STRATEGY_NOTE);

private final Configuration<TaskOwnerAlertStrategyEnum> taskOwnerAlertStrategy =
key(Status.SYS_ENV_SETTINGS_TASK_OWNER_ALERT_STRATEGY)
.enumType(TaskOwnerAlertStrategyEnum.class)
.defaultValue(TaskOwnerAlertStrategyEnum.NONE)
.note(Status.SYS_ENV_SETTINGS_TASK_OWNER_ALERT_STRATEGY_NOTE);

private final Configuration<Boolean> dolphinschedulerEnable = key(Status.SYS_DOLPHINSCHEDULER_SETTINGS_ENABLE)
.booleanType()
.defaultValue(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ sys.env.settings.expressionVariable=Expression variable list
sys.env.settings.expressionVariable.note= Used to use expression variables in task configuration, use , to separate multiple variables, need to use the fully qualified name of the class, for example: com.dinky.common.utils.DateUtils, please ensure that the class is in the classpath of Dinky
sys.env.settings.taskOwnerLockStrategy=Job Responsibility Person Locking Mechanism
sys.env.settings.taskOwnerLockStrategy.note=When [OWNER] is selected, only the assigned person in charge of the task can operate and modify it, while other users cannot. When [OWNER_AND_MAINTAINER] is chosen, both the assigned person in charge and the maintainer can operate and modify the task. When [ALL] is selected, anyone can operate and modify the task. The default setting is [ALL]
sys.env.settings.taskOwnerAlertStrategy=Job Responsibility Person Alert Mechanism
sys.env.settings.taskOwnerAlertStrategy.note=When selecting [OWNER], triggering alerts for jobs will additionally alert the responsible person. When selecting [OWNER_AND_MAINTAINER], triggering alerts for jobs will additionally alert the responsible person and the maintainer. When selecting [NONE], triggering alerts for jobs will not additionally alert the responsible person and the maintainer. The default is [NONE]
sys.dolphinscheduler.settings.enable=Whether to enable DolphinScheduler
sys.dolphinscheduler.settings.enable.note=Whether to enable DolphinScheduler. Only after enabling it can you use the related functions of DolphinScheduler. Please fill in the following configuration items first, and then enable this configuration after completion. Also: Please ensure that the related configurations of DolphinScheduler are correct.
sys.dolphinscheduler.settings.url=DolphinScheduler address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ sys.env.settings.expressionVariable=表达式变量列表
sys.env.settings.expressionVariable.note=用于在任务配置中使用表达式变量,逗号分割,需要使用类的全限定名,例如: com.dinky.common.utils.DateUtils,请确保类在Dinky的classpath中
sys.env.settings.taskOwnerLockStrategy=作业责任人锁机制
sys.env.settings.taskOwnerLockStrategy.note=当选择[OWNER]时,只有作业责任人才能操作作业,其他用户无法操作/修改作业; 当选择[OWNER_AND_MAINTAINER]时,作业责任人和维护人都可以操作/修改作业; 当选择[ALL]时,所有人都可以操作/修改作业; 默认为[ALL]
sys.env.settings.taskOwnerAlertStrategy=作业责任人告警策略
sys.env.settings.taskOwnerAlertStrategy.note=当选择[OWNER]时,作业触发告警时会额外告警责任人; 当选择[OWNER_AND_MAINTAINER]时,作业触发告警时会额外告警责任人和维护人; 当选择[NONE]时,作业触发告警时不会额外告警责任人和维护人; 默认为[NONE]
sys.dolphinscheduler.settings.enable=是否启用 DolphinScheduler
sys.dolphinscheduler.settings.enable.note=是否启用 DolphinScheduler ,启用后才能使用 DolphinScheduler 的相关功能,请先填写下列配置项,完成后再开启此项配置, 另:请确保 DolphinScheduler 的相关配置正确
sys.dolphinscheduler.settings.url=DolphinScheduler 地址
Expand Down

0 comments on commit c2163b8

Please sign in to comment.