Compare commits

...

2 Commits

Author SHA1 Message Date
tomsun28
4f23631e19 [web-app]bugfix: filter is missing when alert-center pageSize change 2022-04-16 22:11:40 +08:00
会编程的王学长
7c54bf0203 feature:Add alarm template custom console and help document (#93)
* feat: [manager,alerter,home]feature:Add alarm template custom console and help document #wqh

* Update common/src/main/java/com/usthe/common/util/CommonConstants.java

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

Co-authored-by: tomsun28 <tomsun28@outlook.com>
2022-04-16 10:34:20 +08:00
11 changed files with 78 additions and 66 deletions

View File

@@ -1,10 +1,12 @@
package com.usthe.alert; package com.usthe.alert;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
* 数据仓储配置属性 * 数据仓储配置属性
*
* @author tom * @author tom
* @date 2021/11/24 10:38 * @date 2021/11/24 10:38
*/ */
@@ -12,11 +14,22 @@ import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "alerter") @ConfigurationProperties(prefix = "alerter")
public class AlerterProperties { public class AlerterProperties {
private String consoleUrl = "https://console.tancloud.cn";
public String getConsoleUrl() {
return consoleUrl;
}
public void setConsoleUrl(String url) {
this.consoleUrl = url;
}
/** /**
* 数据入口配置属性 * 数据入口配置属性
*/ */
private EntranceProperties entrance; private EntranceProperties entrance;
public EntranceProperties getEntrance() { public EntranceProperties getEntrance() {
return entrance; return entrance;
} }
@@ -25,6 +38,7 @@ public class AlerterProperties {
this.entrance = entrance; this.entrance = entrance;
} }
/** /**
* 数据入口配置属性 * 数据入口配置属性
* 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据 * 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据
@@ -98,4 +112,5 @@ public class AlerterProperties {
} }
} }

View File

@@ -0,0 +1,18 @@
---
id: alert_console
title: 告警模板中自定义的控制台地址
sidebar_label: 告警模板登录台地址
---
> 阈值触发后发送告警信息,通过钉钉/企业微信/飞书机器人通知或者使用邮箱通知的时候,告警内容中有登录控制台的详情链接
### 自定义设置
在我们的启动配置文件application.yml中找到下面的配置
```yml
alerter:
console-url: #这里就是我们的自定义控制台地址
```
默认值是赫兹跳动的官方控制台地址

View File

@@ -1,6 +1,7 @@
package com.usthe.manager.component.alerter; package com.usthe.manager.component.alerter;
import com.usthe.alert.AlerterDataQueue; import com.usthe.alert.AlerterDataQueue;
import com.usthe.alert.AlerterProperties;
import com.usthe.alert.AlerterWorkerPool; import com.usthe.alert.AlerterWorkerPool;
import com.usthe.common.util.CommonUtil; import com.usthe.common.util.CommonUtil;
import com.usthe.common.entity.alerter.Alert; import com.usthe.common.entity.alerter.Alert;
@@ -24,6 +25,7 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -48,6 +50,8 @@ public class DispatchAlarm {
private JavaMailSender javaMailSender; private JavaMailSender javaMailSender;
private RestTemplate restTemplate; private RestTemplate restTemplate;
private MailService mailService; private MailService mailService;
@Resource
private AlerterProperties alerterProperties;
@Value("${spring.mail.username}") @Value("${spring.mail.username}")
private String emailFromUser; private String emailFromUser;
@@ -177,13 +181,13 @@ public class DispatchAlarm {
"\n所属监控ID :" + alert.getMonitorId() + "\n所属监控ID :" + alert.getMonitorId() +
"\n所属监控名称 :" + alert.getMonitorName() + "\n所属监控名称 :" + alert.getMonitorName() +
"\n告警级别 :" + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n告警级别 :" + CommonUtil.transferAlertPriority(alert.getPriority()) +
"\n内容详情 : " + alert.getContent(); "\n内容详情 : " + alert.getContent() + "\n";
flyBookContent.setText(text); flyBookContent.setText(text);
contents1.add(flyBookContent); contents1.add(flyBookContent);
FlyBookWebHookDto.FlyBookContent bookContent = new FlyBookWebHookDto.FlyBookContent(); FlyBookWebHookDto.FlyBookContent bookContent = new FlyBookWebHookDto.FlyBookContent();
bookContent.setTag("a"); bookContent.setTag("a");
bookContent.setText("登入控制台"); bookContent.setText("登入控制台");
bookContent.setHref("https://www.tancloud.cn"); bookContent.setHref(alerterProperties.getConsoleUrl());
contents1.add(bookContent); contents1.add(bookContent);
contents.add(contents1); contents.add(contents1);
zhCn.setTitle("[TanCloud探云告警通知]"); zhCn.setTitle("[TanCloud探云告警通知]");
@@ -214,14 +218,16 @@ public class DispatchAlarm {
private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) { private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) {
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto(); DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO(); DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO();
String content = "#### [TanCloud探云告警通知]\n##### **告警目标对象** : " + StringBuilder content = new StringBuilder();
content.append("#### [TanCloud探云告警通知]\n##### **告警目标对象** : " +
alert.getTarget() + "\n " + alert.getTarget() + "\n " +
"##### **所属监控ID** : " + alert.getMonitorId() + "\n " + "##### **所属监控ID** : " + alert.getMonitorId() + "\n " +
"##### **所属监控名称** : " + alert.getMonitorName() + "\n " + "##### **所属监控名称** : " + alert.getMonitorName() + "\n " +
"##### **告警级别** : " + "##### **告警级别** : " +
CommonUtil.transferAlertPriority(alert.getPriority()) + "\n " + CommonUtil.transferAlertPriority(alert.getPriority()) + "\n " +
"##### **内容详情** : " + alert.getContent(); "##### **内容详情** : " + alert.getContent());
markdownDTO.setText(content); content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")");
markdownDTO.setText(content.toString());
markdownDTO.setTitle("TanCloud探云告警通知"); markdownDTO.setTitle("TanCloud探云告警通知");
dingTalkWebHookDto.setMarkdown(markdownDTO); dingTalkWebHookDto.setMarkdown(markdownDTO);
String webHookUrl = DingTalkWebHookDto.WEBHOOK_URL + receiver.getAccessToken(); String webHookUrl = DingTalkWebHookDto.WEBHOOK_URL + receiver.getAccessToken();
@@ -261,8 +267,10 @@ public class DispatchAlarm {
content.append("告警级别 : <font color=\"comment\">") content.append("告警级别 : <font color=\"comment\">")
.append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n"); .append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n");
} }
content.append("内容详情 : ").append(alert.getContent()); content.append("内容详情 : ").append(alert.getContent() + "\n");
content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")");
markdownDTO.setContent(content.toString()); markdownDTO.setContent(content.toString());
//TODO 增加控制台地址登录可控制
weWorkWebHookDTO.setMarkdown(markdownDTO); weWorkWebHookDTO.setMarkdown(markdownDTO);
String webHookUrl = WeWorkWebHookDto.WEBHOOK_URL + receiver.getWechatId(); String webHookUrl = WeWorkWebHookDto.WEBHOOK_URL + receiver.getWechatId();
try { try {

View File

@@ -1,5 +1,6 @@
package com.usthe.manager.service.impl; package com.usthe.manager.service.impl;
import com.usthe.alert.AlerterProperties;
import com.usthe.common.entity.alerter.Alert; import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.util.CommonUtil; import com.usthe.common.util.CommonUtil;
import com.usthe.manager.service.MailService; import com.usthe.manager.service.MailService;
@@ -11,6 +12,7 @@ import org.thymeleaf.context.Context;
import javax.annotation.Resource; import javax.annotation.Resource;
/** /**
* Mailbox sending service interface implementation class
* 邮箱发送服务接口实现类 * 邮箱发送服务接口实现类
* *
* @author 花城 * @author 花城
@@ -23,16 +25,20 @@ public class MailServiceImpl implements MailService {
@Resource @Resource
private TemplateEngine templateEngine; private TemplateEngine templateEngine;
@Resource
private AlerterProperties alerterProperties;
@Override @Override
public String buildAlertHtmlTemplate(final Alert alert) { public String buildAlertHtmlTemplate(final Alert alert) {
// Introduce thymeleaf context parameters to render pages
// 引入thymeleaf上下文参数渲染页面 // 引入thymeleaf上下文参数渲染页面
Context context = new Context(); Context context = new Context();
context.setVariable("target",alert.getTarget()); context.setVariable("target", alert.getTarget());
context.setVariable("monitorId",alert.getMonitorId()); context.setVariable("monitorId", alert.getMonitorId());
context.setVariable("monitorName",alert.getMonitorName()); context.setVariable("monitorName", alert.getMonitorName());
context.setVariable("priority", CommonUtil.transferAlertPriority(alert.getPriority())); context.setVariable("priority", CommonUtil.transferAlertPriority(alert.getPriority()));
context.setVariable("content",alert.getContent()); context.setVariable("content", alert.getContent());
context.setVariable("consoleUrl", alerterProperties.getConsoleUrl());
return templateEngine.process("mailAlarm", context); return templateEngine.process("mailAlarm", context);
} }
} }

View File

@@ -69,3 +69,8 @@ warehouse:
url: jdbc:TAOS-RS://localhost:6041/hertzbeat url: jdbc:TAOS-RS://localhost:6041/hertzbeat
username: root username: root
password: taosdata password: taosdata
#自定义告警控制台地址
alerter:
#这里就是我们的自定义控制台地址
console-url: https://console.tancloud.cn

View File

@@ -700,7 +700,7 @@
<span style="font-family:Arial, Verdana; font-size:14px;color:#FFFFFF;"><a <span style="font-family:Arial, Verdana; font-size:14px;color:#FFFFFF;"><a
target="_blank" target="_blank"
style="color:#FFFFFF;text-decoration:none;" style="color:#FFFFFF;text-decoration:none;"
href="https://console.tancloud.cn" th:href="${consoleUrl}"
data-link-type="web">登入控制台</a></span> data-link-type="web">登入控制台</a></span>
</td> </td>
</tr> </tr>

View File

@@ -54,7 +54,7 @@ export class HeaderNotifyComponent implements OnInit {
return; return;
} }
this.loading = true; this.loading = true;
let loadAlerts$ = this.alertSvc.searchAlerts(0, undefined, undefined, 0, 5).subscribe( let loadAlerts$ = this.alertSvc.loadAlerts(0, undefined, undefined, 0, 5).subscribe(
message => { message => {
loadAlerts$.unsubscribe(); loadAlerts$.unsubscribe();
if (message.code === 0) { if (message.code === 0) {

View File

@@ -30,7 +30,7 @@
<i nz-icon nzType="sync" nzTheme="outline"></i> <i nz-icon nzType="sync" nzTheme="outline"></i>
</button> </button>
<button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="onFilterSearchAlerts()"> <button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="loadAlertsTable()">
{{ 'common.search' | i18n }} {{ 'common.search' | i18n }}
</button> </button>
<input <input
@@ -39,7 +39,7 @@
type="text" type="text"
[placeholder]="'alert.center.search' | i18n" [placeholder]="'alert.center.search' | i18n"
nzSize="default" nzSize="default"
(keyup.enter)="onFilterSearchAlerts()" (keyup.enter)="loadAlertsTable()"
[(ngModel)]="filterContent" [(ngModel)]="filterContent"
/> />
<nz-select <nz-select

View File

@@ -36,13 +36,16 @@ export class AlertCenterComponent implements OnInit {
this.loadAlertsTable(); this.loadAlertsTable();
} }
onFilterSearchAlerts() { sync() {
this.loadAlertsTable();
}
loadAlertsTable() {
this.tableLoading = true; this.tableLoading = true;
let filterAlerts$ = this.alertSvc let alertsInit$ = this.alertSvc
.searchAlerts(this.filterStatus, this.filterPriority, this.filterContent, this.pageIndex - 1, this.pageSize) .loadAlerts(this.filterStatus, this.filterPriority, this.filterContent, this.pageIndex - 1, this.pageSize)
.subscribe( .subscribe(
message => { message => {
filterAlerts$.unsubscribe();
this.tableLoading = false; this.tableLoading = false;
this.checkedAll = false; this.checkedAll = false;
this.checkedAlertIds.clear(); this.checkedAlertIds.clear();
@@ -54,44 +57,16 @@ export class AlertCenterComponent implements OnInit {
} else { } else {
console.warn(message.msg); console.warn(message.msg);
} }
alertsInit$.unsubscribe();
}, },
error => { error => {
this.tableLoading = false; this.tableLoading = false;
filterAlerts$.unsubscribe(); alertsInit$.unsubscribe();
console.error(error.msg); console.error(error.msg);
} }
); );
} }
sync() {
this.loadAlertsTable();
}
loadAlertsTable() {
this.tableLoading = true;
let alertsInit$ = this.alertSvc.getAlerts(this.pageIndex - 1, this.pageSize).subscribe(
message => {
this.tableLoading = false;
this.checkedAll = false;
this.checkedAlertIds.clear();
if (message.code === 0) {
let page = message.data;
this.alerts = page.content;
this.pageIndex = page.number + 1;
this.total = page.totalElements;
} else {
console.warn(message.msg);
}
alertsInit$.unsubscribe();
},
error => {
this.tableLoading = false;
alertsInit$.unsubscribe();
console.error(error.msg);
}
);
}
onDeleteAlerts() { onDeleteAlerts() {
if (this.checkedAlertIds == null || this.checkedAlertIds.size === 0) { if (this.checkedAlertIds == null || this.checkedAlertIds.size === 0) {
this.notifySvc.warning(this.i18nSvc.fanyi('alert.center.notify.no-delete'), ''); this.notifySvc.warning(this.i18nSvc.fanyi('alert.center.notify.no-delete'), '');

View File

@@ -347,7 +347,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
alertsDealLoading: boolean = true; alertsDealLoading: boolean = true;
refreshAlertContentList(): void { refreshAlertContentList(): void {
let alertsInit$ = this.alertSvc.getAlerts(0, 4).subscribe( let alertsInit$ = this.alertSvc.loadAlerts(undefined, undefined, undefined, 0, 4).subscribe(
message => { message => {
if (message.code === 0) { if (message.code === 0) {
let page = message.data; let page = message.data;

View File

@@ -16,22 +16,7 @@ const alerts_status_uri = '/alerts/status';
export class AlertService { export class AlertService {
constructor(private http: HttpClient) {} constructor(private http: HttpClient) {}
public getAlerts(pageIndex: number, pageSize: number): Observable<Message<Page<Alert>>> { public loadAlerts(
pageIndex = pageIndex ? pageIndex : 0;
pageSize = pageSize ? pageSize : 8;
// 注意HttpParams是不可变对象 需要保存set后返回的对象为最新对象
let httpParams = new HttpParams();
httpParams = httpParams.appendAll({
sort: 'id',
order: 'desc',
pageIndex: pageIndex,
pageSize: pageSize
});
const options = { params: httpParams };
return this.http.get<Message<Page<Alert>>>(alerts_uri, options);
}
public searchAlerts(
status: number | undefined, status: number | undefined,
priority: number | undefined, priority: number | undefined,
content: string | undefined, content: string | undefined,