Pre Merge pull request !36 from venus-suite/master
commit
8ab81b91e3
@ -0,0 +1,47 @@
|
|||||||
|
package com.xxl.job.admin.core.alarm;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.util.I18nUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tomj2ee 2022-02-20 11:11:23
|
||||||
|
*/
|
||||||
|
public enum AlarmTypeEnum {
|
||||||
|
/**
|
||||||
|
* 邮件
|
||||||
|
*/
|
||||||
|
EMAIL(1,I18nUtil.getString("jobinfo_field_email")),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* webhook
|
||||||
|
*/
|
||||||
|
WEBHOOK(2,I18nUtil.getString("jobinfo_field_webhook"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private int alarmType;
|
||||||
|
|
||||||
|
AlarmTypeEnum(int alarmType,String title) {
|
||||||
|
this.alarmType=alarmType;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAlarmType() {
|
||||||
|
return alarmType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static AlarmTypeEnum match(String name, AlarmTypeEnum defaultItem){
|
||||||
|
for (AlarmTypeEnum item: AlarmTypeEnum.values()) {
|
||||||
|
if (item.name().equals(name)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
package com.xxl.job.admin.core.alarm.impl;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.core.alarm.AlarmTypeEnum;
|
||||||
|
import com.xxl.job.admin.core.alarm.JobAlarm;
|
||||||
|
import com.xxl.job.admin.core.alarm.msg.FeiShuTextMsgReq;
|
||||||
|
import com.xxl.job.admin.core.alarm.msg.TextMsgReq;
|
||||||
|
import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobGroup;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobInfo;
|
||||||
|
import com.xxl.job.admin.core.model.XxlJobLog;
|
||||||
|
import com.xxl.job.admin.core.util.I18nUtil;
|
||||||
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* job alarm by webhook
|
||||||
|
*
|
||||||
|
* @author hcmyfs@163.com 2022-02-20
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class WebHookJobAlarm implements JobAlarm {
|
||||||
|
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
private static Logger log = LoggerFactory.getLogger(WebHookJobAlarm.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fail alarm
|
||||||
|
*
|
||||||
|
* @param jobLog
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doAlarm(XxlJobInfo info, XxlJobLog jobLog) {
|
||||||
|
boolean alarmResult = true;
|
||||||
|
String br = "\r\n";
|
||||||
|
restTemplate = new RestTemplate();
|
||||||
|
// send monitor webhook
|
||||||
|
if (info != null && info.getAlarmType() == AlarmTypeEnum.WEBHOOK.getAlarmType() &&
|
||||||
|
info.getAlarmUrl() != null && info.getAlarmUrl().trim().length() > 0) {
|
||||||
|
|
||||||
|
// alarmContent
|
||||||
|
String alarmContent = "Alarm Job LogId=" + jobLog.getId();
|
||||||
|
if (jobLog.getTriggerCode() != ReturnT.SUCCESS_CODE) {
|
||||||
|
alarmContent += br + "TriggerMsg=" + br + jobLog.getTriggerMsg();
|
||||||
|
}
|
||||||
|
if (jobLog.getHandleCode() > 0 && jobLog.getHandleCode() != ReturnT.SUCCESS_CODE) {
|
||||||
|
alarmContent += br + "HandleCode=" + jobLog.getHandleMsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
// email info
|
||||||
|
XxlJobGroup group = XxlJobAdminConfig.getAdminConfig().getXxlJobGroupDao().load(Integer.valueOf(info.getJobGroup()));
|
||||||
|
//String personal = I18nUtil.getString("admin_name_full");
|
||||||
|
String title = I18nUtil.getString("jobconf_monitor");
|
||||||
|
String content = MessageFormat.format(loadEmailJobAlarmTemplate(),
|
||||||
|
group != null ? group.getTitle() : "null",
|
||||||
|
info.getId(),
|
||||||
|
info.getJobDesc(),
|
||||||
|
alarmContent);
|
||||||
|
content=content.replace("<br>","\n");
|
||||||
|
content=content.replace("<span style=\"color:#00c0ef;\" >","");
|
||||||
|
content=content.replace("</span>","");
|
||||||
|
|
||||||
|
Set<String> urlList = new HashSet<String>(Arrays.asList(info.getAlarmUrl().split(",")));
|
||||||
|
for (String webHookUrl : urlList) {
|
||||||
|
// make mail
|
||||||
|
try {
|
||||||
|
sendRobot(webHookUrl, content, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(">>>>>>>>>>> xxl-job, job fail alarm webhook send error, JobLogId:{}", jobLog.getId(), e);
|
||||||
|
alarmResult = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alarmResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* load webhook job alarm template
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static final String loadEmailJobAlarmTemplate() {
|
||||||
|
String mailBodyTemplate = I18nUtil.getString("jobconf_monitor_detail") + "\n" +
|
||||||
|
"" + I18nUtil.getString("jobinfo_field_jobgroup") + ":{0}\n" +
|
||||||
|
"" + I18nUtil.getString("jobinfo_field_id") + ":{1}\n" +
|
||||||
|
"" + I18nUtil.getString("jobinfo_field_jobdesc") + ":{2}\n" +
|
||||||
|
"" + I18nUtil.getString("jobconf_monitor_alarm_title") + ":" + I18nUtil.getString("jobconf_monitor_alarm_type") + "\n" +
|
||||||
|
"" + I18nUtil.getString("jobconf_monitor_alarm_content") + ":{3}\n";
|
||||||
|
|
||||||
|
return mailBodyTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean sendRobot(String url, String msg, List<String> usersList) {
|
||||||
|
if (!StringUtils.hasText(url)) {
|
||||||
|
log.error("sendRobot url 格式错误!");
|
||||||
|
throw new RuntimeException("sendRobot url 格式错误!");
|
||||||
|
}
|
||||||
|
if (!url.startsWith("http")) {
|
||||||
|
throw new RuntimeException("sendRobot url 格式错误!");
|
||||||
|
}
|
||||||
|
//创建请求头
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
ResponseEntity<String> responseEntity = null;
|
||||||
|
if (url.contains("open.feishu.cn")) {
|
||||||
|
FeiShuTextMsgReq textMsgReq = new FeiShuTextMsgReq();
|
||||||
|
textMsgReq.withContent(msg);
|
||||||
|
HttpEntity<FeiShuTextMsgReq> entity = new HttpEntity<>(textMsgReq, headers);
|
||||||
|
responseEntity = restTemplate.postForEntity(url, entity, String.class);
|
||||||
|
} else {
|
||||||
|
TextMsgReq textMsgReq = new TextMsgReq();
|
||||||
|
textMsgReq.withContent(msg);
|
||||||
|
if (!CollectionUtils.isEmpty(usersList)) {
|
||||||
|
textMsgReq.withUserList(usersList);
|
||||||
|
}
|
||||||
|
HttpEntity<TextMsgReq> entity = new HttpEntity<>(textMsgReq, headers);
|
||||||
|
responseEntity = restTemplate.postForEntity(url, entity, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
String body = responseEntity.getBody();
|
||||||
|
log.info("sendRobot={}", body);
|
||||||
|
return responseEntity.getStatusCode() == HttpStatus.OK;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.xxl.job.admin.core.alarm.msg;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 飞书消息
|
||||||
|
*/
|
||||||
|
public class FeiShuTextMsgReq {
|
||||||
|
|
||||||
|
public FeiShuTextMsgReq() {
|
||||||
|
List<Map<String, Object>> elements = new ArrayList<>();
|
||||||
|
Map<String, Boolean> config = new HashMap<>();
|
||||||
|
config.put("wide_screen_mode", true);
|
||||||
|
card.put("config", config);
|
||||||
|
card.put("elements",elements);
|
||||||
|
text.put("tag", "markdown");
|
||||||
|
elements.add(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Map<String,Object> card=new HashMap<>();
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private Map<String,Object> text=new HashMap<>();
|
||||||
|
|
||||||
|
@JsonProperty(value = "msg_type")
|
||||||
|
private String msgType="interactive";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
public FeiShuTextMsgReq withContent(String content) {
|
||||||
|
text.put("content", content);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgType() {
|
||||||
|
return msgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgType(String msgType) {
|
||||||
|
this.msgType = msgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getCard() {
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCard(Map<String, Object> card) {
|
||||||
|
this.card = card;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.xxl.job.admin.core.alarm.msg;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业微信消息
|
||||||
|
*/
|
||||||
|
public class TextMsgReq {
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "msgtype": "text",
|
||||||
|
// "text": {
|
||||||
|
// "content": ""
|
||||||
|
// "mentioned_mobile_list":[]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@JsonProperty(value = "msgtype")
|
||||||
|
private String msgType = "text";
|
||||||
|
|
||||||
|
@JsonProperty(value = "text")
|
||||||
|
private Map<String, Object> text = new HashMap<>();
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public List<String> userList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置用户
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
public TextMsgReq withContent(String content) {
|
||||||
|
text.put("content", content);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置@人
|
||||||
|
*
|
||||||
|
* @param userList
|
||||||
|
*/
|
||||||
|
@JsonIgnore
|
||||||
|
public TextMsgReq withUserList(List<String> userList) {
|
||||||
|
text.put("mentioned_mobile_list", userList);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgType() {
|
||||||
|
return msgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgType(String msgType) {
|
||||||
|
this.msgType = msgType;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue