Skip to content

Commit

Permalink
[alerter, manager] use thymeleaf to render notify content (#583)
Browse files Browse the repository at this point in the history
* [web-app] fix history echarts chart tooltip only show one instance (#365)

* [workflow] upgrade issues-translator version 2.7 (#367)

* [manger] add mockito unit test

* [manger] add globalExceptionHandler mockito unit test (#368)

* [manager] impl appController unit test case (#370)

* 英文注释的补充

* Supplement of English notes

* Supplementary English notes

* Supplement of English notes

* AppControllerTest Implementation of unit tests

Co-authored-by: gaoxingcun <gxc01514416@alibaba-inc.com>

* [warehouse] support Iotdb metrics data storage (#372)

* add iotdb storage (saveData part)

* implement getHistoryMetricData

* save multiple instances at the same time
implement getHistoryIntervalMetricData

* [warehouse] reformat code

* [warehouse] refactor code

* [warehouse] refactor code

* [warehouse] refactor code

* [warehouse] fix insert node path container " '  parsed error

* [warehouse] fix insert node path container " ' *  parsed error

* [warehouse] support iotdb rpc-port

* support iotdb version 0.12
fix save data and select bug

* replace Session with SessionPool

* rule fix, 修复魔法值问题

Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: hujiaofen <hujiaofen@2dfire.com>

* [webapp,warehouse] support historical interval aggregate data chart (#373)

* [manger] add mockito unit test

* [manger] impl unit test ParamDaoTest #360

* [manager] fix NoticeRuleDaoTest

* [manger] impl unit test ParamDefineDaoTest #361

* [manger] impl unit test TagDaoTest #362

* [manger] add manger sql dao mockito unit test (#375)

* [manger] add mockito unit test

* [manger] add mockito unit test

* [manger] impl unit test ParamDaoTest #360

* [manager] fix NoticeRuleDaoTest

* [manger] impl unit test ParamDefineDaoTest #361

* [manger] impl unit test TagDaoTest #362

* [manager] I18nControllerTest and MonitorControllerTest Unit tests are written (#376)

* I18ControllerTest Completion of the test class

* MonitorControllerTest Unit tests are written

* [manger] impl unit test AppServiceTest #355

* [hertzbeat] update use PromQL to collect metrics from promethues server (#456)

* [manager] enhancement manager-monitors-page added gmtUpdate desc (#455)

* [manager-monitors](增强)应用服务检测-网站检测-分页:添加默认name升序 (enhancement)manager-monitors-page added name asc

* [manager-monitors](增强)应用服务检测-网站检测-分页:添加默认gmtUpdate降序 (enhancement)manager-monitors-page added gmtUpdate desc

* [webapp] support monitors list sort by name, date (#458)

* [manager] bugfix the gmtUpdate time not change when update monitor params (#459)

* [alerter,collector,common,warehouse] refactor auto import component

* [manager] Notification type supports telegram

* [web-app] Notification type supports telegram

* fix PMD Failure LowerCamelCaseVariableNamingRule

* fix PMD check

* fix ESLint Error

* [manager] remove useless judgment

* [manager] use thymeleaf to render notify content

* [alerter, manager] use thymeleaf to render notify content

Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: 铁甲小宝 <85919258+TJxiaobao@users.noreply.github.com>
Co-authored-by: gaoxingcun <gxc01514416@alibaba-inc.com>
Co-authored-by: zcx <48920254+Ceilzcx@users.noreply.github.com>
Co-authored-by: hujiaofen <hujiaofen@2dfire.com>
Co-authored-by: luxx <58515565+luxx-lq@users.noreply.github.com>
  • Loading branch information
7 people committed Jan 16, 2024
1 parent 94efebc commit 4e9bd64
Show file tree
Hide file tree
Showing 21 changed files with 420 additions and 502 deletions.
117 changes: 13 additions & 104 deletions alerter/src/main/java/com/usthe/alert/AlerterProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package com.usthe.alert;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

Expand All @@ -28,6 +30,8 @@
*/
@Component
@ConfigurationProperties(prefix = "alerter")
@Getter
@Setter
public class AlerterProperties {

/**
Expand All @@ -51,6 +55,11 @@ public class AlerterProperties {
*/
private String flyBookWebHookUrl = "https://open.feishu.cn/open-apis/bot/v2/hook/";

/**
* Telegram Bot api url
*/
private String telegramBotApiUrl = "https://api.telegram.org/bot%s/sendMessage";

/**
* 告警评估时间间隔起始基数 每下一次乘2 单位毫秒
* base of alert eval interval time, unit:ms. The next time is 2 times the previous time.
Expand All @@ -74,90 +83,21 @@ public class AlerterProperties {
*/
private EntranceProperties entrance;

public String getConsoleUrl() {
return consoleUrl;
}

public void setConsoleUrl(String url) {
this.consoleUrl = url;
}

public String getWeWorkWebHookUrl() {
return weWorkWebHookUrl;
}

public void setWeWorkWebHookUrl(String weWorkWebHookUrl) {
this.weWorkWebHookUrl = weWorkWebHookUrl;
}

public String getDingTalkWebHookUrl() {
return dingTalkWebHookUrl;
}

public void setDingTalkWebHookUrl(String dingTalkWebHookUrl) {
this.dingTalkWebHookUrl = dingTalkWebHookUrl;
}

public String getFlyBookWebHookUrl() {
return flyBookWebHookUrl;
}

public void setFlyBookWebHookUrl(String flyBookWebHookUrl) {
this.flyBookWebHookUrl = flyBookWebHookUrl;
}

public long getAlertEvalIntervalBase() {
return alertEvalIntervalBase;
}

public void setAlertEvalIntervalBase(long alertEvalIntervalBase) {
this.alertEvalIntervalBase = alertEvalIntervalBase;
}

public long getMaxAlertEvalInterval() {
return maxAlertEvalInterval;
}

public void setMaxAlertEvalInterval(long maxAlertEvalInterval) {
this.maxAlertEvalInterval = maxAlertEvalInterval;
}

public int getSystemAlertTriggerTimes() {
return systemAlertTriggerTimes;
}

public void setSystemAlertTriggerTimes(int systemAlertTriggerTimes) {
this.systemAlertTriggerTimes = systemAlertTriggerTimes;
}

public EntranceProperties getEntrance() {
return entrance;
}

public void setEntrance(EntranceProperties entrance) {
this.entrance = entrance;
}


/**
* Data entry configuration properties 数据入口配置属性
* The entry can obtain data from messaging middleware such as kafka rabbitmq rocketmq 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据
*/
@Getter
@Setter
public static class EntranceProperties {

/**
* kafka configuration information kafka配置信息
*/
private KafkaProperties kafka;

public KafkaProperties getKafka() {
return kafka;
}

public void setKafka(KafkaProperties kafka) {
this.kafka = kafka;
}

@Getter
@Setter
public static class KafkaProperties {
/**
* Whether the kafka data entry is started kafka数据入口是否启动
Expand All @@ -177,37 +117,6 @@ public static class KafkaProperties {
*/
private String groupId;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public String getServers() {
return servers;
}

public void setServers(String servers) {
this.servers = servers;
}

public String getTopic() {
return topic;
}

public void setTopic(String topic) {
this.topic = topic;
}

public String getGroupId() {
return groupId;
}

public void setGroupId(String groupId) {
this.groupId = groupId;
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public class NoticeReceiver {
@Length(max = 300)
private String hookUrl;

@Schema(title = "openId : The notification method is valid for WeChat official account or enterprise WeChat robot",
description = "openId : 通知方式为微信公众号或企业微信机器人有效",
@Schema(title = "openId : The notification method is valid for WeChat official account, enterprise WeChat robot or FlyBook robot",
description = "openId : 通知方式为微信公众号,企业微信机器人或飞书机器人有效",
example = "343432", accessMode = READ_WRITE)
@Length(max = 300)
private String wechatId;
Expand Down
7 changes: 7 additions & 0 deletions common/src/main/java/com/usthe/common/util/CommonUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,11 @@ public static String getMessageFromThrowable(Throwable throwable) {
return message;
}

public static String removeBlankLine(String value) {
if (value == null) {
return null;
}
return value.replaceAll("(?m)^\\s*$(\\n|\\r\\n)", "");
}

}
1 change: 1 addition & 0 deletions manager/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
<include>*.xml</include>
<include>banner.txt</include>
<include>define/**</include>
<include>templates/**</include>
<include>**/*.html</include>
</includes>
</resource>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.usthe.manager.component.alerter.impl;

import com.usthe.alert.AlerterProperties;
import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.util.CommonUtil;
import com.usthe.common.util.ResourceBundleUtil;
import com.usthe.manager.component.alerter.AlertNotifyHandler;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ResourceBundle;

/**
* @author <a href="mailto:gcwm99@gmail.com">gcdd1993</a>
* @version 2.1
* Created by Musk.Chen on 2023/1/16
*/
abstract class AbstractAlertNotifyHandlerImpl implements AlertNotifyHandler {

protected final ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");
protected static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

@Resource
protected TemplateEngine templateEngine;

@Resource
protected RestTemplate restTemplate;

@Resource
protected AlerterProperties alerterProperties;

protected String renderContext(Alert alert) {
Context context = new Context();
context.setVariable("title", "[" + bundle.getString("alerter.notify.title") + "]");
if (alert.getTags() != null) {
alert.getTags().forEach(context::setVariable);
}
context.setVariable("monitorIdLabel", bundle.getString("alerter.notify.monitorId"));
context.setVariable("monitorNameLabel", bundle.getString("alerter.notify.monitorName"));
context.setVariable("targetLabel", bundle.getString("alerter.notify.target"));
context.setVariable("target", alert.getTarget());

context.setVariable("priorityLabel", bundle.getString("alerter.notify.priority"));
context.setVariable("priority", bundle.getString("alerter.priority." + alert.getPriority()));

context.setVariable("triggerTimeLabel", bundle.getString("alerter.notify.triggerTime"));
context.setVariable("triggerTime", DTF.format(Instant.ofEpochMilli(alert.getLastTriggerTime()).atZone(ZoneId.systemDefault()).toLocalDateTime()));

context.setVariable("contentLabel", bundle.getString("alerter.notify.content"));
context.setVariable("content", alert.getContent());

return CommonUtil.removeBlankLine(templateEngine.process(templateName(), context));
}

/**
* Get the Thymeleaf template name
* 获取Thymeleaf模板名称
*
* @return Thymeleaf模板名称
*/
protected abstract String templateName();

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,15 @@

package com.usthe.manager.component.alerter.impl;

import com.usthe.alert.AlerterProperties;
import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.entity.manager.NoticeReceiver;
import com.usthe.common.util.CommonConstants;
import com.usthe.common.util.ResourceBundleUtil;
import com.usthe.manager.component.alerter.AlertNotifyHandler;
import com.usthe.manager.pojo.dto.DingTalkWebHookDto;
import com.usthe.manager.support.exception.AlertNoticeException;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ResourceBundle;

/**
* Send alarm information through DingTalk robot
Expand All @@ -46,48 +37,17 @@
@Component
@RequiredArgsConstructor
@Slf4j
final class DingTalkRobotAlertNotifyHandlerImpl implements AlertNotifyHandler {

private final RestTemplate restTemplate;

private final AlerterProperties alerterProperties;

private ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");
final class DingTalkRobotAlertNotifyHandlerImpl extends AbstractAlertNotifyHandlerImpl {

@Override
public void send(NoticeReceiver receiver, Alert alert) {
String monitorId = null;
String monitorName = null;
if (alert.getTags() != null) {
monitorId = alert.getTags().get(CommonConstants.TAG_MONITOR_ID);
monitorName = alert.getTags().get(CommonConstants.TAG_MONITOR_NAME);
}
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO();
StringBuilder contentBuilder = new StringBuilder("#### [" + bundle.getString("alerter.notify.title")
+ "]\n##### **" + bundle.getString("alerter.notify.target") + "** : " +
alert.getTarget() + "\n ");
if (monitorId != null) {
contentBuilder.append("##### **").append(bundle.getString("alerter.notify.monitorId"))
.append("** : ").append(monitorId).append("\n ");
}
if (monitorName != null) {
contentBuilder.append("##### **").append(bundle.getString("alerter.notify.monitorName"))
.append("** : ").append(monitorName).append("\n ");
}
contentBuilder.append("##### **").append(bundle.getString("alerter.notify.priority"))
.append("** : ").append(bundle.getString("alerter.priority." + alert.getPriority())).append("\n ");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String triggerTime = simpleDateFormat.format(new Date(alert.getLastTriggerTime()));
contentBuilder.append("##### **").append(bundle.getString("alerter.notify.triggerTime"))
.append("** : ").append(triggerTime).append("\n ");
contentBuilder.append("##### **").append(bundle.getString("alerter.notify.content"))
.append("** : ").append(alert.getContent());
markdownDTO.setText(contentBuilder.toString());
markdownDTO.setTitle(bundle.getString("alerter.notify.title"));
dingTalkWebHookDto.setMarkdown(markdownDTO);
String webHookUrl = alerterProperties.getDingTalkWebHookUrl() + receiver.getAccessToken();
try {
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
MarkdownDTO markdownDTO = new MarkdownDTO();
markdownDTO.setText(renderContext(alert));
markdownDTO.setTitle(bundle.getString("alerter.notify.title"));
dingTalkWebHookDto.setMarkdown(markdownDTO);
String webHookUrl = alerterProperties.getDingTalkWebHookUrl() + receiver.getAccessToken();
ResponseEntity<CommonRobotNotifyResp> entity = restTemplate.postForEntity(webHookUrl,
dingTalkWebHookDto, CommonRobotNotifyResp.class);
if (entity.getStatusCode() == HttpStatus.OK) {
Expand All @@ -111,4 +71,45 @@ public void send(NoticeReceiver receiver, Alert alert) {
public byte type() {
return 5;
}

@Override
protected String templateName() {
return "alertNotifyDingTalkRobot";
}

/**
* 钉钉机器人请求消息体
*
* @author 花城
* @version 1.0
* @date 2022/2/21 6:55 下午
*/
@Data
private static class DingTalkWebHookDto {
private static final String MARKDOWN = "markdown";

/**
* 消息类型
*/
private String msgtype = MARKDOWN;

/**
* markdown消息
*/
private MarkdownDTO markdown;

}

@Data
private static class MarkdownDTO {
/**
* 消息内容
*/
private String text;
/**
* 消息标题
*/
private String title;
}

}
Loading

0 comments on commit 4e9bd64

Please sign in to comment.