Skip to content

Commit

Permalink
[manager,webapp]#245 Notification type supports telegram (#580)
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

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, 2023
1 parent f450e2f commit 5ecce73
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public class NoticeReceiver {
@NotNull
private String name;

@Schema(title = "Notification information method: 0-SMS 1-Email 2-webhook 3-WeChat Official Account 4-Enterprise WeChat Robot 5-DingTalk Robot 6-FeiShu Robot",
description = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人 6-飞书机器人",
@Schema(title = "Notification information method: 0-SMS 1-Email 2-webhook 3-WeChat Official Account 4-Enterprise WeChat Robot 5-DingTalk Robot 6-FeiShu Robot 7-Telegram Bot",
description = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人 6-飞书机器人 7-Telegram机器人",
accessMode = READ_WRITE)
@Min(0)
@Max(8)
Expand Down Expand Up @@ -106,6 +106,16 @@ public class NoticeReceiver {
@Length(max = 300)
private String accessToken;

@Schema(title = "Telegram bot token : The notification method is valid for Telegram Bot",
description = "Telegram bot token : 通知方式为Telegram机器人有效",
example = "1499012345:AAEOB_wEYS-DZyPM3h5NzI8voJMXXXXXX", accessMode = READ_WRITE)
private String tgBotToken;

@Schema(title = "Telegram user id: The notification method is valid for Telegram Bot",
description = "Telegram user id : 通知方式为Telegram机器人有效",
example = "779294123", accessMode = READ_WRITE)
private String tgUserId;

@Schema(title = "The creator of this record", description = "此条记录创建者", example = "tom",
accessMode = READ_ONLY)
@CreatedBy
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package com.usthe.manager.component.alerter.impl;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
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.support.exception.AlertNoticeException;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
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.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ResourceBundle;

/**
* Send alarm information by Telegram Bot
* 通过Telegram Bot发送告警信息
*
* @author <a href="mailto:gcwm99@gmail.com">gcdd1993</a>
* @version 2.1
* Created by Musk.Chen on 2023/1/16
*/
@Component
@RequiredArgsConstructor
@Slf4j
final class TelegramBotAlertNotifyHandlerImpl implements AlertNotifyHandler {
private final RestTemplate restTemplate;
private final ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final String TG_BOT_URL_TEMPLATE = "https://api.telegram.org/bot%s/sendMessage";

@Override
public void send(NoticeReceiver receiver, Alert alert) throws AlertNoticeException {
String url = String.format(TG_BOT_URL_TEMPLATE, receiver.getTgBotToken());
TelegramBotNotifyDTO notifyBody = TelegramBotNotifyDTO.builder()
.chatId(receiver.getTgUserId())
.text(buildMessage(alert))
.disableWebPagePreview(true)
.build();
try {
ResponseEntity<TelegramBotNotifyResponse> entity = restTemplate.postForEntity(url, notifyBody, TelegramBotNotifyResponse.class);
if (entity.getStatusCode() == HttpStatus.OK && entity.getBody() != null) {
TelegramBotNotifyResponse body = entity.getBody();
if (body.ok) {
log.debug("Send Telegram Bot Success");
} else {
log.warn("Send Telegram Bot Failed: {}, error_code: {}", body.description, body.errorCode);
throw new AlertNoticeException(body.description);
}
} else {
log.warn("Send Telegram Bot Failed {}", entity.getBody());
throw new AlertNoticeException("Http StatusCode " + entity.getStatusCode());
}
} catch (Exception e) {
throw new AlertNoticeException("[Telegram Bot Notify Error] " + e.getMessage());
}
}

@Override
public byte type() {
return 7;
}

private String buildMessage(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);
}
StringBuilder content = new StringBuilder();
content.append("[").append(bundle.getString("alerter.notify.title")).append("]\n")
.append(bundle.getString("alerter.notify.target")).append(" : ").append(alert.getTarget()).append("\n");
if (StringUtils.hasText(monitorId)) {
content.append(bundle.getString("alerter.notify.monitorId")).append(" : ")
.append(monitorId).append("\n");
}
if (StringUtils.hasText(monitorName)) {
content.append(bundle.getString("alerter.notify.monitorName")).append(" : ")
.append(monitorName).append("\n");
}
if (alert.getPriority() < CommonConstants.ALERT_PRIORITY_CODE_WARNING) {
content.append(bundle.getString("alerter.notify.priority")).append(" : ")
.append(bundle.getString("alerter.priority." + alert.getPriority())).append("\n");
} else {
content.append(bundle.getString("alerter.notify.priority")).append(" : ")
.append(bundle.getString("alerter.priority." + alert.getPriority())).append("\n");
}
String triggerTime = DTF.format(Instant.ofEpochMilli(alert.getLastTriggerTime()).atZone(ZoneId.systemDefault()).toLocalDateTime());
content.append(bundle.getString("alerter.notify.triggerTime")).append(" : ")
.append(triggerTime).append("\n");
content.append(bundle.getString("alerter.notify.content")).append(" : ").append(alert.getContent());

return content.toString();
}

@Data
@Builder
private static class TelegramBotNotifyDTO {
@JsonProperty("chat_id")
private String chatId;
private String text;
@JsonProperty("disable_web_page_preview")
private Boolean disableWebPagePreview;
}

@NoArgsConstructor
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
private static class TelegramBotNotifyResponse {
private boolean ok;
@JsonProperty("error_code")
private Integer errorCode;
private String description;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ final class WeWorkRobotAlertNotifyHandlerImpl implements AlertNotifyHandler {

private final AlerterProperties alerterProperties;

private ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");
private final ResourceBundle bundle = ResourceBundleUtil.getBundle("alerter");

@Override
public void send(NoticeReceiver receiver, Alert alert) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.usthe.manager.component.alerter.impl;

import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.entity.manager.NoticeReceiver;
import com.usthe.common.util.CommonConstants;
import com.usthe.manager.AbstractSpringIntegrationTest;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
* @author <a href="mailto:gcwm99@gmail.com">gcdd1993</a>
* @version 2.1
* Created by Musk.Chen on 2023/1/16
*/
@Slf4j
class TelegramBotAlertNotifyHandlerImplTest extends AbstractSpringIntegrationTest {

@Resource
private TelegramBotAlertNotifyHandlerImpl telegramBotAlertNotifyHandler;

@Test
void send() {
String tgBotToken = System.getenv("TG_BOT_TOKEN");
String tgUserId = System.getenv("TG_USER_ID");
if (!StringUtils.hasText(tgBotToken) || !StringUtils.hasText(tgUserId)) {
log.warn("Please provide environment variables TG_BOT_TOKEN, TG_USER_ID");
return;
}
NoticeReceiver receiver = new NoticeReceiver();
receiver.setId(1L);
receiver.setName("Mock 告警");
receiver.setTgBotToken(tgBotToken);
receiver.setTgUserId(tgUserId);
Alert alert = new Alert();
alert.setId(1L);
alert.setTarget("Mock Target");
Map<String, String> map = new HashMap<>();
map.put(CommonConstants.TAG_MONITOR_ID, "Mock monitor id");
map.put(CommonConstants.TAG_MONITOR_NAME, "Mock monitor name");
alert.setTags(map);
alert.setContent("mock content");
alert.setPriority((byte) 0);
alert.setLastTriggerTime(System.currentTimeMillis());

telegramBotAlertNotifyHandler.send(receiver, alert);
}
}
4 changes: 3 additions & 1 deletion web-app/src/app/pojo/NoticeReceiver.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
export class NoticeReceiver {
id!: number;
name!: string;
// 通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号
// 通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人 6-飞书机器人 7-Telegram机器人
type: number = 1;
phone!: string;
email!: string;
tgBotToken!: string;
tgUserId!: string;
hookUrl!: string;
wechatId!: string;
accessToken!: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.fei-shu' | i18n }}</span>
</nz-tag>
<nz-tag *ngIf="data.type == 7" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.telegram-bot' | i18n }}</span>
</nz-tag>
</td>
<td nzAlign="center">
<span *ngIf="data.type == 0">{{ data.phone }}</span>
Expand All @@ -91,6 +95,7 @@
<span *ngIf="data.type == 4">{{ data.wechatId }}</span>
<span *ngIf="data.type == 5">{{ data.accessToken }}</span>
<span *ngIf="data.type == 6">{{ data.wechatId }}</span>
<span *ngIf="data.type == 7">{{ data.tgBotToken }}<br />{{ data.tgUserId }}</span>
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | date : 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center">
Expand Down Expand Up @@ -219,6 +224,7 @@
<nz-option [nzValue]="4" [nzLabel]="'alert.notice.type.wework' | i18n"></nz-option>
<nz-option [nzValue]="5" [nzLabel]="'alert.notice.type.ding' | i18n"></nz-option>
<nz-option [nzValue]="6" [nzLabel]="'alert.notice.type.fei-shu' | i18n"></nz-option>
<nz-option [nzValue]="7" [nzLabel]="'alert.notice.type.telegram-bot' | i18n"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
Expand Down Expand Up @@ -272,6 +278,22 @@
<input [(ngModel)]="receiver.wechatId" nz-input [required]="receiver.type === 6" name="wechatId" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 7">
<nz-form-label [nzSpan]="7" nzFor="tgBotToken" [nzRequired]="receiver.type === 7">{{
'alert.notice.type.telegram-bot-token' | i18n
}}</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.tgBotToken" nz-input [required]="receiver.type === 7" name="tgBotToken" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 7">
<nz-form-label [nzSpan]="7" nzFor="tgUserId" [nzRequired]="receiver.type === 7">{{
'alert.notice.type.telegram-bot-user-id' | i18n
}}</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.tgUserId" nz-input [required]="receiver.type === 7" name="wechatId" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-control [nzOffset]="7" [nzSpan]="12">
<button nz-button nzDanger nzType="primary" [nzLoading]="isSendTestButtonLoading" (click)="onSendAlertTestMsg()">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ export class AlertNoticeComponent implements OnInit {
case 6:
label = `${label}FeiShu`;
break;
case 7:
label = `${label}TelegramBot`;
break;
}
this.receiversOption.push({
value: item.id,
Expand Down
3 changes: 3 additions & 0 deletions web-app/src/assets/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"alert.notice.type.ding": "DingDing Robot",
"alert.notice.type.fei-shu": "FeiShu Robot",
"alert.notice.type.fei-shu-key": "FeiShu Robot KEY",
"alert.notice.type.telegram-bot": "Telegram Bot",
"alert.notice.type.telegram-bot-token": "Telegram Bot Token",
"alert.notice.type.telegram-bot-user-id": "Telegram User Id",
"alert.notice.rule": "Alert Notice Policy",
"alert.notice.rule.new": "New Notice Policy",
"alert.notice.rule.edit": "Edit Notice Policy",
Expand Down
3 changes: 3 additions & 0 deletions web-app/src/assets/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"alert.notice.type.ding": "钉钉机器人",
"alert.notice.type.fei-shu": "飞书机器人",
"alert.notice.type.fei-shu-key": "飞书机器人KEY",
"alert.notice.type.telegram-bot": "Telegram机器人",
"alert.notice.type.telegram-bot-token": "Telegram Bot Token",
"alert.notice.type.telegram-bot-user-id": "Telegram User Id",
"alert.notice.rule": "告警通知策略",
"alert.notice.rule.new": "新增通知策略",
"alert.notice.rule.edit": "编辑通知策略",
Expand Down
3 changes: 3 additions & 0 deletions web-app/src/assets/i18n/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"alert.notice.type.ding": "釘釘機器人",
"alert.notice.type.fei-shu": "飛書機器人",
"alert.notice.type.fei-shu-key": "飛書機器人KEY",
"alert.notice.type.telegram-bot": "Telegram機器人",
"alert.notice.type.telegram-bot-token": "Telegram Bot Token",
"alert.notice.type.telegram-bot-user-id": "Telegram User Id",
"alert.notice.rule": "告警通知策略",
"alert.notice.rule.new": "新增通知策略",
"alert.notice.rule.edit": "編輯通知策略",
Expand Down

0 comments on commit 5ecce73

Please sign in to comment.