Compare commits
22 Commits
feature#or
...
fix_tanClo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d65fe3861 | ||
|
|
f3bd9930f1 | ||
|
|
dc61dd066c | ||
|
|
4ad7972956 | ||
|
|
e99dd2e870 | ||
|
|
95c36fd9a3 | ||
|
|
2553c6f61e | ||
|
|
cc92f82472 | ||
|
|
8dd2c1e47f | ||
|
|
6a9d65ba5d | ||
|
|
3c48b4c71f | ||
|
|
636303021f | ||
|
|
0cf66f32ff | ||
|
|
fbf7ebd834 | ||
|
|
327f527082 | ||
|
|
2f52ff5e63 | ||
|
|
abe24914d3 | ||
|
|
491ca17106 | ||
|
|
feef3e7054 | ||
|
|
5c7bb4b14e | ||
|
|
bb636c9bae | ||
|
|
d871572438 |
@@ -76,7 +76,7 @@
|
||||
|
||||
##### 安装TDengine
|
||||
1. docker安装TDengine
|
||||
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
|
||||
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/tcp -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
|
||||
2. 创建名称为hertzbeat的数据库
|
||||
|
||||
详细步骤参考 [依赖服务TDengine安装初始化](https://hertzbeat.com/docs/start/tdengine-init)
|
||||
@@ -138,7 +138,8 @@ HertzBeat赫兹跳动为 [Dromara开源社区](https://dromara.org/) 孵化项
|
||||
|
||||
##### 赞助
|
||||
|
||||
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com)赞助服务器采集节点
|
||||
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
|
||||
感谢[天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) 赞助服务器采集节点
|
||||
|
||||
## 🛡️ License
|
||||
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
@@ -30,11 +30,12 @@ import java.util.List;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
/**
|
||||
* 告警管理API
|
||||
* Alarm Management API 告警管理API
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/9 10:32
|
||||
*/
|
||||
@Api(tags = "告警批量管理API")
|
||||
@Api(tags = "en: Alarm batch management API, zh:告警批量管理API")
|
||||
@RestController
|
||||
@RequestMapping(path = "/alerts", produces = {APPLICATION_JSON_VALUE})
|
||||
public class AlertsController {
|
||||
@@ -43,23 +44,23 @@ public class AlertsController {
|
||||
private AlertService alertService;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation(value = "查询告警列表", notes = "根据查询过滤项获取告警信息列表")
|
||||
@ApiOperation(value = "Get a list of alarm information based on query filter items", notes = "根据查询过滤项获取告警信息列表")
|
||||
public ResponseEntity<Message<Page<Alert>>> getAlerts(
|
||||
@ApiParam(value = "告警ID", example = "6565466456") @RequestParam(required = false) List<Long> ids,
|
||||
@ApiParam(value = "告警监控对象ID", example = "6565463543") @RequestParam(required = false) Long monitorId,
|
||||
@ApiParam(value = "告警级别", example = "6565463543") @RequestParam(required = false) Byte priority,
|
||||
@ApiParam(value = "告警状态", example = "6565463543") @RequestParam(required = false) Byte status,
|
||||
@ApiParam(value = "告警内容模糊查询", example = "linux") @RequestParam(required = false) String content,
|
||||
@ApiParam(value = "排序字段,默认id", example = "name") @RequestParam(defaultValue = "id") String sort,
|
||||
@ApiParam(value = "排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
|
||||
@ApiParam(value = "列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@ApiParam(value = "列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
@ApiParam(value = "en: Alarm ID List,zh: 告警IDS", example = "6565466456") @RequestParam(required = false) List<Long> ids,
|
||||
@ApiParam(value = "en: Alarm monitor object ID,zh: 告警监控对象ID", example = "6565463543") @RequestParam(required = false) Long monitorId,
|
||||
@ApiParam(value = "en: Alarm level,zh: 告警级别", example = "6565463543") @RequestParam(required = false) Byte priority,
|
||||
@ApiParam(value = "en: Alarm Status,zh: 告警状态", example = "6565463543") @RequestParam(required = false) Byte status,
|
||||
@ApiParam(value = "en: Alarm content fuzzy query,zh:告警内容模糊查询", example = "linux") @RequestParam(required = false) String content,
|
||||
@ApiParam(value = "en: Sort field, default id,zh: 排序字段,默认id", example = "name") @RequestParam(defaultValue = "id") String sort,
|
||||
@ApiParam(value = "en: Sort Type,zh: 排序方式,asc:升序,desc:降序", example = "desc") @RequestParam(defaultValue = "desc") String order,
|
||||
@ApiParam(value = "en: List current page,zh: 列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
|
||||
@ApiParam(value = "en: Number of list pagination,zh: 列表分页数量", example = "8") @RequestParam(defaultValue = "8") int pageSize) {
|
||||
|
||||
Specification<Alert> specification = (root, query, criteriaBuilder) -> {
|
||||
List<Predicate> andList = new ArrayList<>();
|
||||
|
||||
if (ids != null && !ids.isEmpty()) {
|
||||
CriteriaBuilder.In<Long> inPredicate= criteriaBuilder.in(root.get("id"));
|
||||
CriteriaBuilder.In<Long> inPredicate = criteriaBuilder.in(root.get("id"));
|
||||
for (long id : ids) {
|
||||
inPredicate.value(id);
|
||||
}
|
||||
@@ -92,10 +93,9 @@ public class AlertsController {
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@ApiOperation(value = "批量删除告警", notes = "根据告警ID列表批量删除告警")
|
||||
@ApiOperation(value = "Delete alarms in batches", notes = "根据告警ID列表批量删除告警")
|
||||
public ResponseEntity<Message<Void>> deleteAlertDefines(
|
||||
@ApiParam(value = "告警IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids
|
||||
) {
|
||||
@ApiParam(value = "en:Alarm List ID,zh: 告警IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
|
||||
if (ids != null && !ids.isEmpty()) {
|
||||
alertService.deleteAlerts(new HashSet<>(ids));
|
||||
}
|
||||
@@ -104,10 +104,10 @@ public class AlertsController {
|
||||
}
|
||||
|
||||
@PutMapping(path = "/status/{status}")
|
||||
@ApiOperation(value = "批量修改告警状态", notes = "批量修改告警状态,设置已读未读")
|
||||
@ApiOperation(value = "Batch modify alarm status, set read and unread", notes = "批量修改告警状态,设置已读未读")
|
||||
public ResponseEntity<Message<Void>> applyAlertDefinesStatus(
|
||||
@ApiParam(value = "告警状态值", example = "0") @PathVariable Byte status,
|
||||
@ApiParam(value = "告警IDs", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
|
||||
@ApiParam(value = "en:Alarm status value,zh: 告警状态值", example = "0") @PathVariable Byte status,
|
||||
@ApiParam(value = "en:Alarm List IDS,zh: 告警IDS", example = "6565463543") @RequestParam(required = false) List<Long> ids) {
|
||||
if (ids != null && status != null && !ids.isEmpty()) {
|
||||
alertService.editAlertStatus(status, ids);
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class AlertsController {
|
||||
}
|
||||
|
||||
@GetMapping(path = "/summary")
|
||||
@ApiOperation(value = "获取告警统计信息", notes = "获取告警统计信息")
|
||||
@ApiOperation(value = "Get alarm statistics", notes = "获取告警统计信息")
|
||||
public ResponseEntity<Message<AlertSummary>> getAlertsSummary() {
|
||||
AlertSummary alertSummary = alertService.getAlertsSummary();
|
||||
Message<AlertSummary> message = new Message<>(alertSummary);
|
||||
|
||||
@@ -12,30 +12,35 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Alert 数据库操作
|
||||
* Alert Database Operations Alert数据库表操作
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/9 10:03
|
||||
*/
|
||||
public interface AlertDao extends JpaRepository<Alert, Long>, JpaSpecificationExecutor<Alert> {
|
||||
|
||||
/**
|
||||
* 根据ID列表删除告警
|
||||
* @param alertIds 告警ID列表
|
||||
* Delete alerts based on ID list 根据ID列表删除告警
|
||||
*
|
||||
* @param alertIds Alert ID List 告警ID列表
|
||||
*/
|
||||
void deleteAlertsByIdIn(Set<Long> alertIds);
|
||||
|
||||
/**
|
||||
* 根据告警ID-状态值 更新告警状态
|
||||
*
|
||||
* @param status 状态值
|
||||
* @param ids 告警ID列表
|
||||
* @param ids 告警ID列表
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update Alert set status = :status where id in :ids")
|
||||
void updateAlertsStatus(@Param(value = "status") Byte status, @Param(value = "ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* Query the number of unhandled alarms of each alarm severity
|
||||
* 查询各个告警级别的未处理告警数量
|
||||
* @return 告警数量
|
||||
*
|
||||
* @return Number of alerts 告警数量
|
||||
*/
|
||||
@Query("select new com.usthe.alert.dto.AlertPriorityNum(mo.priority, count(mo.id)) from Alert mo where mo.status = 0 group by mo.priority")
|
||||
List<AlertPriorityNum> findAlertPriorityNum();
|
||||
|
||||
@@ -4,7 +4,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 监控级别告警数量
|
||||
* Number of monitoring level alarms 监控级别告警数量
|
||||
*
|
||||
* @author tom
|
||||
* @date 2022/3/6 19:52
|
||||
*/
|
||||
@@ -12,7 +13,13 @@ import lombok.Data;
|
||||
@AllArgsConstructor
|
||||
public class AlertPriorityNum {
|
||||
|
||||
/**
|
||||
* Alarm level 告警级别
|
||||
*/
|
||||
private byte priority;
|
||||
|
||||
/**
|
||||
* count 数量
|
||||
*/
|
||||
private long num;
|
||||
}
|
||||
|
||||
@@ -9,31 +9,43 @@ import lombok.NoArgsConstructor;
|
||||
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
|
||||
|
||||
/**
|
||||
* 告警统计信息
|
||||
* Alarm Statistics Information 告警统计信息
|
||||
*
|
||||
* @author tom
|
||||
* @date 2022/3/6 19:25
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(description = "告警统计信息")
|
||||
@ApiModel(description = "en:Alarm Statistics Information,zh: 告警统计信息")
|
||||
public class AlertSummary {
|
||||
|
||||
@ApiModelProperty(value = "告警总数量(包括已处理未处理告警)", example = "134", accessMode = READ_ONLY, position = 0)
|
||||
@ApiModelProperty(value = "Total number of alerts (including processed and unprocessed alerts)",
|
||||
notes = "告警总数量(包括已处理未处理告警)",
|
||||
example = "134", accessMode = READ_ONLY, position = 0)
|
||||
private long total;
|
||||
|
||||
@ApiModelProperty(value = "已处理告警数量", example = "34", accessMode = READ_ONLY, position = 1)
|
||||
@ApiModelProperty(value = "Number of alerts handled",
|
||||
notes = "已处理告警数量",
|
||||
example = "34", accessMode = READ_ONLY, position = 1)
|
||||
private long dealNum;
|
||||
|
||||
@ApiModelProperty(value = "告警处理率", example = "39.34", accessMode = READ_ONLY, position = 2)
|
||||
@ApiModelProperty(value = "Alarm handling rate",
|
||||
notes = "告警处理率",
|
||||
example = "39.34", accessMode = READ_ONLY, position = 2)
|
||||
private float rate;
|
||||
|
||||
@ApiModelProperty(value = "告警级别为警告告警的告警数量(指未处理告警)", example = "43", accessMode = READ_ONLY, position = 3)
|
||||
@ApiModelProperty(value = "Number of alarms whose alarm severity is warning alarms (referring to unhandled alarms)",
|
||||
notes = "告警级别为警告告警的告警数量(指未处理告警)",
|
||||
example = "43", accessMode = READ_ONLY, position = 3)
|
||||
private long priorityWarningNum;
|
||||
|
||||
@ApiModelProperty(value = "告警级别为严重告警的告警数量(指未处理告警)", example = "56", accessMode = READ_ONLY, position = 4)
|
||||
@ApiModelProperty(value = "Number of alarms whose alarm severity is critical alarms (referring to unhandled alarms)",
|
||||
notes = "告警级别为严重告警的告警数量(指未处理告警)",
|
||||
example = "56", accessMode = READ_ONLY, position = 4)
|
||||
private long priorityCriticalNum;
|
||||
|
||||
@ApiModelProperty(value = "告警级别为紧急告警的告警数量(指未处理告警)", example = "23", accessMode = READ_ONLY, position = 5)
|
||||
@ApiModelProperty(value = "Number of alarms whose alarm severity is urgent alarms (referring to unhandled alarms)",
|
||||
notes = "告警级别为紧急告警的告警数量(指未处理告警)", example = "23", accessMode = READ_ONLY, position = 5)
|
||||
private long priorityEmergencyNum;
|
||||
}
|
||||
|
||||
@@ -10,43 +10,54 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Alarm information management interface
|
||||
* 告警信息管理接口
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/9 10:06
|
||||
*/
|
||||
public interface AlertService {
|
||||
|
||||
/**
|
||||
* 新增告警
|
||||
* @param alert 告警实体
|
||||
* @throws RuntimeException 新增过程异常抛出
|
||||
* Add alarm record
|
||||
* 新增告警记录
|
||||
*
|
||||
* @param alert Alert entity 告警实体
|
||||
* @throws RuntimeException Add process exception throw 新增过程异常抛出
|
||||
*/
|
||||
void addAlert(Alert alert) throws RuntimeException;
|
||||
|
||||
/**
|
||||
* Dynamic conditional query
|
||||
* 动态条件查询
|
||||
* @param specification 查询条件
|
||||
* @param pageRequest 分页参数
|
||||
* @return 查询结果
|
||||
*
|
||||
* @param specification Query conditions 查询条件
|
||||
* @param pageRequest pagination parameters 分页参数
|
||||
* @return search result 查询结果
|
||||
*/
|
||||
Page<Alert> getAlerts(Specification<Alert> specification, PageRequest pageRequest);
|
||||
|
||||
/**
|
||||
* Delete alarms in batches according to the alarm ID list
|
||||
* 根据告警ID列表批量删除告警
|
||||
* @param ids 告警IDs
|
||||
*
|
||||
* @param ids Alarm ID List 告警IDS
|
||||
*/
|
||||
void deleteAlerts(HashSet<Long> ids);
|
||||
|
||||
/**
|
||||
* Update the alarm status according to the alarm ID-status value
|
||||
* 根据告警ID-状态值 更新告警状态
|
||||
* @param status 待修改为的告警状态
|
||||
* @param ids 待修改的告警IDs
|
||||
*
|
||||
* @param status Alarm status to be modified 待修改为的告警状态
|
||||
* @param ids Alarm ID List to be modified 待修改的告警ID集合
|
||||
*/
|
||||
void editAlertStatus(Byte status, List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获取告警统计信息
|
||||
* @return 告警统计
|
||||
* Get alarm statistics information 获取告警统计信息
|
||||
*
|
||||
* @return Alarm statistics information 告警统计
|
||||
*/
|
||||
AlertSummary getAlertsSummary();
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 告警信息服务实现
|
||||
* Realization of Alarm Information Service 告警信息服务实现
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/10 15:39
|
||||
*/
|
||||
@@ -55,18 +56,24 @@ public class AlertServiceImpl implements AlertService {
|
||||
@Override
|
||||
public AlertSummary getAlertsSummary() {
|
||||
AlertSummary alertSummary = new AlertSummary();
|
||||
//Statistics on the alarm information in the alarm state
|
||||
//统计正在告警状态下的告警信息
|
||||
List<AlertPriorityNum> priorityNums = alertDao.findAlertPriorityNum();
|
||||
if (priorityNums != null) {
|
||||
for (AlertPriorityNum priorityNum : priorityNums) {
|
||||
switch (priorityNum.getPriority()) {
|
||||
case CommonConstants
|
||||
.ALERT_PRIORITY_CODE_WARNING:
|
||||
alertSummary.setPriorityWarningNum(priorityNum.getNum());break;
|
||||
alertSummary.setPriorityWarningNum(priorityNum.getNum());
|
||||
break;
|
||||
case CommonConstants.ALERT_PRIORITY_CODE_CRITICAL:
|
||||
alertSummary.setPriorityCriticalNum(priorityNum.getNum());break;
|
||||
alertSummary.setPriorityCriticalNum(priorityNum.getNum());
|
||||
break;
|
||||
case CommonConstants.ALERT_PRIORITY_CODE_EMERGENCY:
|
||||
alertSummary.setPriorityEmergencyNum(priorityNum.getNum());break;
|
||||
default: break;
|
||||
alertSummary.setPriorityEmergencyNum(priorityNum.getNum());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,12 @@
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>10.2.0.jre8</version>
|
||||
</dependency>
|
||||
<!-- oracle -->
|
||||
<dependency>
|
||||
<groupId>com.oracle.database.jdbc</groupId>
|
||||
<artifactId>ojdbc8</artifactId>
|
||||
<version>21.5.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -17,7 +17,9 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -75,7 +77,18 @@ public class CommonHttpClient {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
|
||||
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
|
||||
// 判断服务器证书有效期时间
|
||||
Date now = new Date();
|
||||
if (x509Certificates != null && x509Certificates.length > 0) {
|
||||
for (X509Certificate certificate : x509Certificates) {
|
||||
Date deadline = certificate.getNotAfter();
|
||||
if (deadline != null && now.after(deadline)) {
|
||||
throw new CertificateExpiredException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() { return null; }
|
||||
};
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.usthe.collector.collect.common.ssh;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.sshd.client.SshClient;
|
||||
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
|
||||
import org.apache.sshd.common.PropertyResolverUtils;
|
||||
import org.apache.sshd.core.CoreModuleProperties;
|
||||
|
||||
/**
|
||||
* ssh公共client
|
||||
@@ -16,6 +19,14 @@ public class CommonSshClient {
|
||||
|
||||
static {
|
||||
sshClient = SshClient.setUpDefaultClient();
|
||||
// 接受所有服务端公钥校验,会打印warn日志 Server at {} presented unverified {} key: {}
|
||||
AcceptAllServerKeyVerifier verifier = AcceptAllServerKeyVerifier.INSTANCE;
|
||||
sshClient.setServerKeyVerifier(verifier);
|
||||
// 设置链接保活心跳10000毫秒一次, 客户端等待保活心跳超时响应时间3000毫秒
|
||||
PropertyResolverUtils.updateProperty(
|
||||
sshClient, CoreModuleProperties.HEARTBEAT_INTERVAL.getName(), 10000);
|
||||
PropertyResolverUtils.updateProperty(
|
||||
sshClient, CoreModuleProperties.HEARTBEAT_REPLY_WAIT.getName(), 3000);
|
||||
sshClient.start();
|
||||
}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@ public class JdbcCommonCollect extends AbstractCollect {
|
||||
}
|
||||
JdbcProtocol jdbcProtocol = metrics.getJdbc();
|
||||
String databaseUrl = constructDatabaseUrl(jdbcProtocol);
|
||||
// 查询超时时间默认3000毫秒
|
||||
int timeout = 3000;
|
||||
// 查询超时时间默认6000毫秒
|
||||
int timeout = 6000;
|
||||
try {
|
||||
// 获取查询语句超时时间
|
||||
if (jdbcProtocol.getTimeout() != null) {
|
||||
@@ -285,6 +285,10 @@ public class JdbcCommonCollect extends AbstractCollect {
|
||||
url = "jdbc:sqlserver://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
|
||||
+ ";" + (jdbcProtocol.getDatabase() == null ? "" : "DatabaseName=" + jdbcProtocol.getDatabase());
|
||||
break;
|
||||
case "oracle":
|
||||
url = "jdbc:oracle:thin:@" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
|
||||
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Not support database platform: " + jdbcProtocol.getPlatform());
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ public class JdbcSpiLoader implements CommandLineRunner {
|
||||
Class.forName("com.mysql.cj.jdbc.Driver");
|
||||
Class.forName("org.postgresql.Driver");
|
||||
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
|
||||
Class.forName("oracle.jdbc.driver.OracleDriver");
|
||||
} catch (Exception e) {
|
||||
log.error("load jdbc error: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ public class IcmpCollectImpl extends AbstractCollect {
|
||||
return;
|
||||
}
|
||||
IcmpProtocol icmp = metrics.getIcmp();
|
||||
// 超时时间默认300毫秒
|
||||
int timeout = 300;
|
||||
// 超时时间默认6000毫秒
|
||||
int timeout = 6000;
|
||||
try {
|
||||
timeout = Integer.parseInt(icmp.getTimeout());
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.usthe.collector.collect.common.cache.CacheIdentifier;
|
||||
import com.usthe.collector.collect.common.cache.CommonCache;
|
||||
import com.usthe.collector.collect.common.ssh.CommonSshClient;
|
||||
import com.usthe.collector.util.CollectorConstants;
|
||||
import com.usthe.collector.util.KeyPairUtil;
|
||||
import com.usthe.common.entity.job.Metrics;
|
||||
import com.usthe.common.entity.job.protocol.SshProtocol;
|
||||
import com.usthe.common.entity.message.CollectRep;
|
||||
@@ -19,6 +20,7 @@ import org.springframework.util.StringUtils;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.security.KeyPair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -56,8 +58,8 @@ public class SshCollectImpl extends AbstractCollect {
|
||||
return;
|
||||
}
|
||||
SshProtocol sshProtocol = metrics.getSsh();
|
||||
// 超时时间默认300毫秒
|
||||
int timeout = 3000;
|
||||
// 超时时间默认6000毫秒
|
||||
int timeout = 6000;
|
||||
try {
|
||||
timeout = Integer.parseInt(sshProtocol.getTimeout());
|
||||
} catch (Exception e) {
|
||||
@@ -181,6 +183,13 @@ public class SshCollectImpl extends AbstractCollect {
|
||||
.verify(timeout, TimeUnit.MILLISECONDS).getSession();
|
||||
if (StringUtils.hasText(sshProtocol.getPassword())) {
|
||||
clientSession.addPasswordIdentity(sshProtocol.getPassword());
|
||||
} else if (StringUtils.hasText(sshProtocol.getPublicKey())) {
|
||||
KeyPair keyPair = KeyPairUtil.getKeyPairFromPublicKey(sshProtocol.getPublicKey());
|
||||
if (keyPair != null) {
|
||||
clientSession.addPublicKeyIdentity(keyPair);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("需填写账户登陆密码或公钥");
|
||||
}
|
||||
// 进行认证
|
||||
if (!clientSession.auth().verify(timeout, TimeUnit.MILLISECONDS).isSuccess()) {
|
||||
|
||||
@@ -38,8 +38,8 @@ public class TelnetCollectImpl extends AbstractCollect {
|
||||
}
|
||||
|
||||
TelnetProtocol telnet = metrics.getTelnet();
|
||||
// 超时时间默认300毫秒
|
||||
int timeout = 300;
|
||||
// 超时时间默认6000毫秒
|
||||
int timeout = 6000;
|
||||
try {
|
||||
timeout = Integer.parseInt(telnet.getTimeout());
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.usthe.common.entity.job.Job;
|
||||
import com.usthe.common.entity.job.Metrics;
|
||||
import com.usthe.common.util.AesUtil;
|
||||
import com.usthe.common.util.CommonConstants;
|
||||
import com.usthe.common.util.GsonUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -84,6 +85,26 @@ public class WheelTimerTask implements TimerTask {
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, JsonElement> entry = iterator.next();
|
||||
JsonElement element = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
// 替换KEY-VALUE情况的属性 比如http headers params
|
||||
if (key != null && key.startsWith("^_^") && key.endsWith("^_^")) {
|
||||
key = key.replaceAll("\\^_\\^", "");
|
||||
Configmap param = configmap.get(key);
|
||||
if (param != null && param.getType() == (byte) 3) {
|
||||
String jsonValue = (String) param.getValue();
|
||||
Map<String, String> map = GsonUtil.fromJson(jsonValue, Map.class);
|
||||
if (map != null) {
|
||||
map.forEach((name, value) -> {
|
||||
if (name != null && !"".equals(name.trim())) {
|
||||
jsonObject.addProperty(name, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
// 替换正常的VALUE值
|
||||
if (element.isJsonPrimitive()) {
|
||||
// 判断是否含有特殊字符 替换
|
||||
String value = element.getAsString();
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.usthe.collector.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 密钥工具类
|
||||
* @author tom
|
||||
* @date 2022/4/2 17:04
|
||||
*/
|
||||
@Slf4j
|
||||
public class KeyPairUtil {
|
||||
|
||||
private static KeyFactory keyFactory;
|
||||
|
||||
static {
|
||||
try {
|
||||
keyFactory = KeyFactory.getInstance("RSA");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取密钥对
|
||||
*/
|
||||
public static KeyPair getKeyPairFromPublicKey(String publicKeyStr) {
|
||||
try {
|
||||
if (publicKeyStr == null || "".equals(publicKeyStr)) {
|
||||
return null;
|
||||
}
|
||||
// todo fix 公钥解析
|
||||
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
|
||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||
return new KeyPair(publicKey, null);
|
||||
} catch (Exception e) {
|
||||
log.info("[keyPair] parse failed, {}." + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,8 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
|
||||
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
|
||||
/**
|
||||
* 告警记录
|
||||
* Alarm record entity 告警记录实体
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/9 15:37
|
||||
*/
|
||||
@@ -33,52 +34,68 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(description = "告警记录实体")
|
||||
@ApiModel(description = "en: Alarm record entity zh: 告警记录实体")
|
||||
public class Alert {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "告警记录实体主键索引ID", example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
@ApiModelProperty(value = "Alarm record entity primary key index ID",
|
||||
notes = "告警记录实体主键索引ID",
|
||||
example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "告警目标对象: 监控可用性-available 指标-app.metrics.field",
|
||||
@ApiModelProperty(value = "Alert target object: monitor availability-available metrics-app.metrics.field",
|
||||
notes = "告警目标对象: 监控可用性-available 指标-app.metrics.field",
|
||||
example = "1", accessMode = READ_WRITE, position = 1)
|
||||
@Length(max = 255)
|
||||
private String target;
|
||||
|
||||
@ApiModelProperty(value = "告警对象关联的监控ID", example = "87432674336", accessMode = READ_WRITE, position = 2)
|
||||
@ApiModelProperty(value = "Monitoring ID associated with the alarm object",
|
||||
notes = "告警对象关联的监控ID",
|
||||
example = "87432674336", accessMode = READ_WRITE, position = 2)
|
||||
private Long monitorId;
|
||||
|
||||
@ApiModelProperty(value = "告警对象关联的监控名称", example = "Linux_192.132.23.1",
|
||||
accessMode = READ_WRITE, position = 3)
|
||||
@ApiModelProperty(value = "Monitoring name associated with the alarm object",
|
||||
notes = "告警对象关联的监控名称",
|
||||
example = "Linux_192.132.23.1", accessMode = READ_WRITE, position = 3)
|
||||
private String monitorName;
|
||||
|
||||
@ApiModelProperty(value = "告警关联的告警定义ID", example = "8743267443543", accessMode = READ_WRITE, position = 4)
|
||||
@ApiModelProperty(value = "Alarm definition ID associated with the alarm",
|
||||
notes = "告警关联的告警定义ID",
|
||||
example = "8743267443543", accessMode = READ_WRITE, position = 4)
|
||||
private Long alertDefineId;
|
||||
|
||||
@ApiModelProperty(value = "告警级别 0:高-emergency-紧急告警-红色 1:中-critical-严重告警-橙色 2:低-warning-警告告警-黄色",
|
||||
@ApiModelProperty(value = "Alarm level 0: high-emergency-critical alarm-red 1: medium-critical-critical alarm-orange 2: low-warning-warning alarm-yellow",
|
||||
notes = "告警级别 0:高-emergency-紧急告警-红色 1:中-critical-严重告警-橙色 2:低-warning-警告告警-黄色",
|
||||
example = "1", accessMode = READ_WRITE, position = 5)
|
||||
@Min(0)
|
||||
@Max(2)
|
||||
private byte priority;
|
||||
|
||||
@ApiModelProperty(value = "告警通知实际内容", example = "linux_192.134.32.1: 534543534 cpu usage high",
|
||||
@ApiModelProperty(value = "The actual content of the alarm notification",
|
||||
notes = "告警通知实际内容",
|
||||
example = "linux_192.134.32.1: 534543534 cpu usage high",
|
||||
accessMode = READ_WRITE, position = 6)
|
||||
@Length(max = 1024)
|
||||
private String content;
|
||||
|
||||
@ApiModelProperty(value = "告警状态: 0-正常告警(待处理) 1-阈值触发但未达到告警次数 2-恢复告警 3-已处理",
|
||||
@ApiModelProperty(value = "Alarm status: 0-normal alarm (to be processed) 1-threshold triggered but not reached the number of alarms 2-recovered alarm 3-processed",
|
||||
notes = "告警状态: 0-正常告警(待处理) 1-阈值触发但未达到告警次数 2-恢复告警 3-已处理",
|
||||
example = "1", accessMode = READ_WRITE, position = 7)
|
||||
@Min(0)
|
||||
@Max(2)
|
||||
private byte status;
|
||||
|
||||
@ApiModelProperty(value = "告警阈值触发次数", example = "3", accessMode = READ_WRITE, position = 8)
|
||||
@ApiModelProperty(value = "Alarm threshold trigger times",
|
||||
notes = "告警阈值触发次数",
|
||||
example = "3", accessMode = READ_WRITE, position = 8)
|
||||
@Min(0)
|
||||
@Max(10)
|
||||
private int times;
|
||||
|
||||
@ApiModelProperty(value = "告警触发时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@ApiModelProperty(value = "Alarm trigger time (timestamp in milliseconds)",
|
||||
notes = "告警触发时间(毫秒时间戳)",
|
||||
example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class Configmap {
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* 参数类型 0:数字 1:字符串 2:加密串
|
||||
* 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
|
||||
* number,string,secret
|
||||
* 数字,非加密字符串,加密字符串
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,7 @@ public class SshProtocol {
|
||||
/**
|
||||
* 超时时间
|
||||
*/
|
||||
private String timeout = "3000";
|
||||
private String timeout;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
|
||||
@@ -23,7 +23,9 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
|
||||
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
|
||||
/**
|
||||
* Message notification recipient entity
|
||||
* 消息通知接收人实体
|
||||
*
|
||||
* @author tomsun28
|
||||
* @date 2021/11/13 22:19
|
||||
*/
|
||||
@@ -33,56 +35,80 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(description = "消息通知接收人实体")
|
||||
@ApiModel(description = "en: Message notification recipient entity,zh:消息通知接收人实体")
|
||||
public class NoticeReceiver {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "接收人实体主键索引ID", example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
@ApiModelProperty(value = "Recipient entity primary key index ID",
|
||||
notes = "接收人实体主键索引ID",
|
||||
example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "接收人名称", example = "tom", accessMode = READ_WRITE, position = 1)
|
||||
@ApiModelProperty(value = "Recipient name",
|
||||
notes = "接收人名称",
|
||||
example = "tom", accessMode = READ_WRITE, position = 1)
|
||||
@Length(max = 100)
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人 6-飞书机器人", accessMode = READ_WRITE, position = 2)
|
||||
@ApiModelProperty(value = "Notification information method: 0-SMS 1-Email 2-webhook 3-WeChat Official Account 4-Enterprise WeChat Robot 5-DingTalk Robot 6-FeiShu Robot",
|
||||
notes = "通知信息方式: 0-手机短信 1-邮箱 2-webhook 3-微信公众号 4-企业微信机器人 5-钉钉机器人 6-飞书机器人",
|
||||
accessMode = READ_WRITE, position = 2)
|
||||
@Min(0)
|
||||
@Max(8)
|
||||
@NotNull
|
||||
private Byte type;
|
||||
|
||||
@ApiModelProperty(value = "手机号, 通知方式为手机短信时有效", example = "18923435643", accessMode = READ_WRITE, position = 3)
|
||||
@ApiModelProperty(value = "Mobile number: Valid when the notification method is SMS",
|
||||
notes = "手机号 : 通知方式为手机短信时有效",
|
||||
example = "18923435643", accessMode = READ_WRITE, position = 3)
|
||||
@Length(max = 100)
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty(value = "邮箱账号, 通知方式为邮箱时有效", example = "tom@qq.com", accessMode = READ_WRITE, position = 4)
|
||||
@ApiModelProperty(value = "Email account: Valid when the notification method is email",
|
||||
notes = "邮箱账号 : 通知方式为邮箱时有效",
|
||||
example = "tom@qq.com", accessMode = READ_WRITE, position = 4)
|
||||
@Length(max = 100)
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty(value = "URL地址, 通知方式为webhook有效", example = "https://www.tancloud.cn", accessMode = READ_WRITE, position = 5)
|
||||
@ApiModelProperty(value = "URL address: The notification method is valid for webhook",
|
||||
notes = "URL地址 : 通知方式为webhook有效",
|
||||
example = "https://www.tancloud.cn", accessMode = READ_WRITE, position = 5)
|
||||
@Length(max = 300)
|
||||
private String hookUrl;
|
||||
|
||||
@ApiModelProperty(value = "openId, 通知方式为微信公众号或企业微信机器人有效", example = "343432", accessMode = READ_WRITE, position = 6)
|
||||
@ApiModelProperty(value = "openId : The notification method is valid for WeChat official account or enterprise WeChat robot",
|
||||
notes = "openId : 通知方式为微信公众号或企业微信机器人有效",
|
||||
example = "343432", accessMode = READ_WRITE, position = 6)
|
||||
@Length(max = 300)
|
||||
private String wechatId;
|
||||
|
||||
@ApiModelProperty(value = "访问token, 通知方式为钉钉机器人有效", example = "34823984635647", accessMode = READ_WRITE, position = 7)
|
||||
@ApiModelProperty(value = "Access token : The notification method is valid for DingTalk robot",
|
||||
notes = "访问token : 通知方式为钉钉机器人有效",
|
||||
example = "34823984635647", accessMode = READ_WRITE, position = 7)
|
||||
@Length(max = 300)
|
||||
private String accessToken;
|
||||
|
||||
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 7)
|
||||
@ApiModelProperty(value = "The creator of this record",
|
||||
notes = "此条记录创建者",
|
||||
example = "tom", accessMode = READ_ONLY, position = 7)
|
||||
private String creator;
|
||||
|
||||
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 8)
|
||||
@ApiModelProperty(value = "This record was last modified by",
|
||||
notes = "此条记录最新修改者",
|
||||
example = "tom", accessMode = READ_ONLY, position = 8)
|
||||
private String modifier;
|
||||
|
||||
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@ApiModelProperty(value = "Record creation time (millisecond timestamp)",
|
||||
notes = "记录创建时间(毫秒时间戳)",
|
||||
example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 10)
|
||||
@ApiModelProperty(value = "Record the latest modification time (timestamp in milliseconds)",
|
||||
notes = "记录最新修改时间(毫秒时间戳)",
|
||||
example = "1612198444000", accessMode = READ_ONLY, position = 10)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_ONLY;
|
||||
import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
|
||||
/**
|
||||
* Notification strategy entity
|
||||
* 通知策略
|
||||
*
|
||||
* @author tomsun28
|
||||
* @date 2021/11/13 22:19
|
||||
*/
|
||||
@@ -31,45 +33,65 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@ApiModel(description = "通知策略实体")
|
||||
@ApiModel(description = "en: Notify Policy Entity,zh: 通知策略实体")
|
||||
public class NoticeRule {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "通知策略实体主键索引ID", example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
@ApiModelProperty(value = "Notification Policy Entity Primary Key Index ID",
|
||||
notes = "通知策略实体主键索引ID",
|
||||
example = "87584674384", accessMode = READ_ONLY, position = 0)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "策略名称", example = "dispatch-1", accessMode = READ_WRITE, position = 1)
|
||||
@ApiModelProperty(value = "Policy name",
|
||||
notes = "策略名称",
|
||||
example = "dispatch-1", accessMode = READ_WRITE, position = 1)
|
||||
@Length(max = 100)
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "接收人ID", example = "4324324", accessMode = READ_WRITE, position = 2)
|
||||
@ApiModelProperty(value = "Recipient ID",
|
||||
notes = "接收人ID",
|
||||
example = "4324324", accessMode = READ_WRITE, position = 2)
|
||||
@NotNull
|
||||
private Long receiverId;
|
||||
|
||||
@ApiModelProperty(value = "接收人标识", example = "tom", accessMode = READ_WRITE, position = 3)
|
||||
@ApiModelProperty(value = "Recipient identification",
|
||||
notes = "接收人标识",
|
||||
example = "tom", accessMode = READ_WRITE, position = 3)
|
||||
@Length(max = 100)
|
||||
@NotNull
|
||||
private String receiverName;
|
||||
|
||||
@ApiModelProperty(value = "是否启用此策略", example = "true", accessMode = READ_WRITE, position = 4)
|
||||
@ApiModelProperty(value = "Whether to enable this policy",
|
||||
notes = "是否启用此策略",
|
||||
example = "true", accessMode = READ_WRITE, position = 4)
|
||||
private boolean enable = true;
|
||||
|
||||
@ApiModelProperty(value = "是否转发所有", example = "false", accessMode = READ_WRITE, position = 5)
|
||||
@ApiModelProperty(value = "Whether to forward all",
|
||||
notes = "是否转发所有",
|
||||
example = "false", accessMode = READ_WRITE, position = 5)
|
||||
private boolean filterAll = true;
|
||||
|
||||
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 7)
|
||||
@ApiModelProperty(value = "The creator of this record",
|
||||
notes = "此条记录创建者",
|
||||
example = "tom", accessMode = READ_ONLY, position = 7)
|
||||
private String creator;
|
||||
|
||||
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 8)
|
||||
@ApiModelProperty(value = "This record was last modified by",
|
||||
notes = "此条记录最新修改者",
|
||||
example = "tom", accessMode = READ_ONLY, position = 8)
|
||||
private String modifier;
|
||||
|
||||
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@ApiModelProperty(value = "This record creation time (millisecond timestamp)",
|
||||
notes = "记录创建时间(毫秒时间戳)",
|
||||
example = "1612198922000", accessMode = READ_ONLY, position = 9)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 10)
|
||||
@ApiModelProperty(value = "Record the latest modification time (timestamp in milliseconds)",
|
||||
notes = "记录最新修改时间(毫秒时间戳)",
|
||||
example = "1612198444000", accessMode = READ_ONLY, position = 10)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
|
||||
@@ -59,15 +59,15 @@ public class Param {
|
||||
* 参数值
|
||||
*/
|
||||
@ApiModelProperty(value = "参数值", example = "8080", accessMode = READ_WRITE, position = 3)
|
||||
@Length(max = 255)
|
||||
@Length(max = 8126)
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* 参数类型 0:数字 1:字符串 2:加密串
|
||||
* 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
|
||||
*/
|
||||
@ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串", accessMode = READ_WRITE, position = 4)
|
||||
@ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串", accessMode = READ_WRITE, position = 4)
|
||||
@Min(0)
|
||||
@Max(2)
|
||||
@Max(3)
|
||||
private byte type;
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,29 +110,41 @@ public class ParamDefine {
|
||||
@Convert(converter = JsonOptionListAttributeConverter.class)
|
||||
private List<Option> options;
|
||||
|
||||
/**
|
||||
* 当type为key-value时有效,表示key的别名描述
|
||||
*/
|
||||
@ApiModelProperty(value = "当type为key-value时有效,表示key的别名描述", example = "Name", accessMode = READ_WRITE, position = 9)
|
||||
private String keyAlias;
|
||||
|
||||
/**
|
||||
* 当type为key-value时有效,表示value的别名描述
|
||||
*/
|
||||
@ApiModelProperty(value = "当type为key-value时有效,表示value的别名描述", example = "Value", accessMode = READ_WRITE, position = 10)
|
||||
private String valueAlias;
|
||||
|
||||
/**
|
||||
* 此条记录创建者
|
||||
*/
|
||||
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 9)
|
||||
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11)
|
||||
private String creator;
|
||||
|
||||
/**
|
||||
* 此条记录最新修改者
|
||||
*/
|
||||
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 10)
|
||||
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12)
|
||||
private String modifier;
|
||||
|
||||
/**
|
||||
* 记录创建时间
|
||||
*/
|
||||
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 11)
|
||||
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtCreate;
|
||||
|
||||
/**
|
||||
* 记录最新修改时间
|
||||
*/
|
||||
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 12)
|
||||
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14)
|
||||
@Column(insertable = false, updatable = false)
|
||||
private LocalDateTime gmtUpdate;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ sidebar_label: 帮助入门
|
||||
|
||||
### 数据库监控
|
||||
|
||||
[MYSQL数据库监控](mysql)      [MariaDB数据库监控](mariadb)      [PostgreSQL数据库监控](postgresql)      [SqlServer数据库监控](sqlserver)
|
||||
[MYSQL数据库监控](mysql)      [MariaDB数据库监控](mariadb)      [PostgreSQL数据库监控](postgresql)      [SqlServer数据库监控](sqlserver)      [Oracle数据库监控](oracle)
|
||||
|
||||
### 操作系统监控
|
||||
|
||||
|
||||
62
home/docs/help/oracle.md
Normal file
62
home/docs/help/oracle.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: oracle
|
||||
title: 监控:ORACLE数据库监控
|
||||
sidebar_label: ORACLE数据库
|
||||
---
|
||||
|
||||
> 对ORACLE数据库的通用性能指标进行采集监控。
|
||||
|
||||
### 配置参数
|
||||
|
||||
| 参数名称 | 参数帮助描述 |
|
||||
| ----------- | ----------- |
|
||||
| 监控Host | 被监控的对端IPV4,IPV6或域名。注意⚠️不带协议头(eg: https://, http://)。 |
|
||||
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
|
||||
| 端口 | 数据库对外提供的端口,默认为1521。 |
|
||||
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间,单位ms毫秒,默认3000毫秒。 |
|
||||
| 数据库名称 | 数据库实例名称,可选。 |
|
||||
| 用户名 | 数据库连接用户名,可选 |
|
||||
| 密码 | 数据库连接密码,可选 |
|
||||
| URL | 数据库连接URL,可选,若配置,则URL里面的数据库名称,用户名密码等参数会覆盖上面配置的参数 |
|
||||
| 采集间隔 | 监控周期性采集数据间隔时间,单位秒,可设置的最小间隔为10秒 |
|
||||
| 是否探测 | 新增监控前是否先探测检查监控可用性,探测成功才会继续新增修改操作 |
|
||||
| 描述备注 | 更多标识和描述此监控的备注信息,用户可以在这里备注信息 |
|
||||
|
||||
### 采集指标
|
||||
|
||||
#### 指标集合:basic
|
||||
|
||||
| 指标名称 | 指标单位 | 指标帮助描述 |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| database_version | 无 | 数据库版本 |
|
||||
| database_type | 无 | 数据库类型 |
|
||||
| hostname | 无 | 主机名称 |
|
||||
| instance_name | 无 | 数据库实例名称 |
|
||||
| startup_time | 无 | 数据库启动时间 |
|
||||
| status | 无 | 数据库状态 |
|
||||
|
||||
#### 指标集合:tablespace
|
||||
|
||||
| 指标名称 | 指标单位 | 指标帮助描述 |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| file_id | 无 | 文件ID |
|
||||
| file_name | 无 | 文件名称 |
|
||||
| tablespace_name | 无 | 所属表空间名称 |
|
||||
| status | 无 | 状态 |
|
||||
| bytes | MB | 大小 |
|
||||
| blocks | 无 | 区块数量 |
|
||||
|
||||
#### 指标集合:user_connect
|
||||
|
||||
| 指标名称 | 指标单位 | 指标帮助描述 |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| username | 无 | 用户名 |
|
||||
| counts | 个数 | 当前连接数量 |
|
||||
|
||||
#### 指标集合:performance
|
||||
|
||||
| 指标名称 | 指标单位 | 指标帮助描述 |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| qps | QPS | I/O Requests per Second 每秒IO请求数量 |
|
||||
| tps | TPS | User Transaction Per Sec 每秒用户事物处理数量 |
|
||||
| mbps | MBPS | I/O Megabytes per Second 每秒 I/O 兆字节数量 |
|
||||
@@ -11,8 +11,9 @@ sidebar_label: 赞助
|
||||
|
||||

|
||||
|
||||
|
||||
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com)赞助服务器采集节点
|
||||
|
||||
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
|
||||
感谢[天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) 赞助服务器采集节点
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,10 +43,56 @@ sidebar_label: Docker方式部署
|
||||
HertzBeat默认内置三个用户账户,分别为 admin/admin tom/tom@123 lili/lili
|
||||
若需要新增删除修改账户或密码,可以通过配置 `sureness.yml` 实现,若无此需求可忽略此步骤
|
||||
在主机目录下创建sureness.yml,eg:/opt/sureness.yml
|
||||
配置文件内容参考 项目仓库[/script/sureness.yml](https://gitee.com/dromara/hertzbeat/blob/master/script/sureness.yml)
|
||||
修改sureness.yml的如下部分参数:[注意⚠️sureness配置的其它默认参数需保留]
|
||||
配置文件内容参考 项目仓库[/script/sureness.yml](https://gitee.com/dromara/hertzbeat/blob/master/script/sureness.yml)
|
||||
|
||||
```yaml
|
||||
|
||||
resourceRole:
|
||||
- /account/auth/refresh===post===[role1,role2,role3,role4]
|
||||
|
||||
excludedResource:
|
||||
- /account/auth/**===*
|
||||
- /===get
|
||||
- /i18n/**===get
|
||||
- /apps/hierarchy===get
|
||||
- /console/**===get
|
||||
- /**/*.html===get
|
||||
- /**/*.js===get
|
||||
- /**/*.css===get
|
||||
- /**/*.ico===get
|
||||
- /**/*.ttf===get
|
||||
- /**/*.png===get
|
||||
- /**/*.gif===get
|
||||
- /**/*.png===*
|
||||
- /swagger-resources/**===get
|
||||
- /v2/api-docs===get
|
||||
- /v3/api-docs===get
|
||||
|
||||
# 用户账户信息
|
||||
# 下面有 admin tom lili 三个账户
|
||||
# eg: admin 拥有[role1,role2]角色,密码为admin
|
||||
# eg: tom 拥有[role1,role2,role3],密码为tom@123
|
||||
# eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
|
||||
account:
|
||||
- appId: admin
|
||||
credential: admin
|
||||
role: [role1,role2]
|
||||
- appId: tom
|
||||
credential: tom@123
|
||||
role: [role1,role2,role3]
|
||||
- appId: lili
|
||||
# 注意 Digest认证不支持加盐加密的密码账户
|
||||
# 加盐加密的密码,通过 MD5(password+salt)计算
|
||||
# 此账户的原始密码为 lili
|
||||
credential: 1A676730B0C7F54654B0E09184448289
|
||||
salt: 123
|
||||
role: [role1,role2]
|
||||
```
|
||||
|
||||
修改sureness.yml的如下**部分参数**:**[注意⚠️sureness配置的其它默认参数需保留]**
|
||||
|
||||
```yaml
|
||||
|
||||
# 用户账户信息
|
||||
# 下面有 admin tom lili 三个账户
|
||||
# eg: admin 拥有[role1,role2]角色,密码为admin
|
||||
|
||||
@@ -46,7 +46,7 @@ sidebar_label: 安装包方式部署
|
||||
4. 配置用户配置文件(非必须,配置账户需要)
|
||||
HertzBeat默认内置三个用户账户,分别为 admin/admin tom/tom@123 lili/lili
|
||||
若需要新增删除修改账户或密码,可以通过修改位于 `hertzbeat/config/sureness.yml` 的配置文件实现,若无此需求可忽略此步骤
|
||||
修改sureness.yml的如下部分参数:[注意⚠️sureness配置的其它默认参数需保留]
|
||||
修改sureness.yml的如下**部分参数**:**[注意⚠️sureness配置的其它默认参数需保留]**
|
||||
|
||||
```yaml
|
||||
# 用户账户信息
|
||||
|
||||
@@ -7,8 +7,8 @@ const repoUrl = `https://github.com/dromara/${projectName}`
|
||||
const cdnUrl = 'https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/'
|
||||
|
||||
module.exports = {
|
||||
title: 'TANCLOUD探云',
|
||||
tagline: '易用友好的高性能监控云',
|
||||
title: 'HertzBeat',
|
||||
tagline: '易用友好的云监控系统',
|
||||
url: 'https://hertzbeat.com',
|
||||
baseUrl: '/',
|
||||
onBrokenLinks: 'throw',
|
||||
|
||||
@@ -65,7 +65,8 @@
|
||||
"help/mysql",
|
||||
"help/mariadb",
|
||||
"help/postgresql",
|
||||
"help/sqlserver"
|
||||
"help/sqlserver",
|
||||
"help/oracle"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
4
home/static/img/hertzbeat-brand-white.svg
Normal file
4
home/static/img/hertzbeat-brand-white.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.9 KiB |
4
home/static/img/tancloud-brand-white.svg
Normal file
4
home/static/img/tancloud-brand-white.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="199" height="53" viewBox="0 0 199 53" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M60.0112 15.3828V36H57.3208V15.3828H60.0112ZM66.6382 15.3828V17.6201H50.708V15.3828H66.6382ZM76.1963 17.2095L69.3711 36H66.5815L74.4404 15.3828H76.2388L76.1963 17.2095ZM81.917 36L75.0776 17.2095L75.0352 15.3828H76.8335L84.7207 36H81.917ZM81.563 28.3677V30.605H69.98V28.3677H81.563ZM103.341 15.3828V36H100.594L90.2148 20.0981V36H87.4819V15.3828H90.2148L100.637 31.3271V15.3828H103.341ZM120.631 29.4438H123.35C123.208 30.7466 122.835 31.9124 122.231 32.9414C121.627 33.9704 120.772 34.7869 119.668 35.3911C118.563 35.9858 117.185 36.2832 115.533 36.2832C114.325 36.2832 113.225 36.0566 112.234 35.6035C111.252 35.1504 110.407 34.5085 109.699 33.6777C108.991 32.8376 108.444 31.8322 108.057 30.6616C107.679 29.4816 107.49 28.1694 107.49 26.7251V24.6719C107.49 23.2275 107.679 21.9201 108.057 20.7495C108.444 19.5695 108.996 18.5594 109.713 17.7192C110.44 16.8791 111.313 16.2324 112.333 15.7793C113.353 15.3262 114.5 15.0996 115.774 15.0996C117.332 15.0996 118.648 15.3923 119.725 15.9775C120.801 16.5628 121.636 17.3747 122.231 18.4131C122.835 19.4421 123.208 20.6362 123.35 21.9956H120.631C120.499 21.0327 120.253 20.2067 119.895 19.5176C119.536 18.819 119.026 18.2809 118.365 17.9033C117.704 17.5257 116.841 17.3369 115.774 17.3369C114.858 17.3369 114.051 17.5116 113.353 17.8608C112.663 18.2101 112.083 18.7057 111.611 19.3477C111.148 19.9896 110.799 20.759 110.563 21.6558C110.327 22.5526 110.209 23.5485 110.209 24.6436V26.7251C110.209 27.7352 110.313 28.6839 110.521 29.5713C110.738 30.4587 111.063 31.2375 111.498 31.9077C111.932 32.578 112.484 33.1066 113.154 33.4937C113.825 33.8713 114.618 34.0601 115.533 34.0601C116.694 34.0601 117.619 33.876 118.309 33.5078C118.998 33.1396 119.517 32.611 119.866 31.9219C120.225 31.2327 120.48 30.4067 120.631 29.4438ZM139.577 33.7769V36H129.269V33.7769H139.577ZM129.807 15.3828V36H127.074V15.3828H129.807ZM157.646 25.04V26.3428C157.646 27.891 157.452 29.2786 157.065 30.5059C156.678 31.7331 156.121 32.7762 155.394 33.6353C154.667 34.4943 153.794 35.1504 152.774 35.6035C151.764 36.0566 150.632 36.2832 149.376 36.2832C148.158 36.2832 147.04 36.0566 146.02 35.6035C145.01 35.1504 144.132 34.4943 143.386 33.6353C142.65 32.7762 142.079 31.7331 141.673 30.5059C141.267 29.2786 141.064 27.891 141.064 26.3428V25.04C141.064 23.4919 141.262 22.1089 141.659 20.8911C142.065 19.6639 142.636 18.6208 143.372 17.7617C144.108 16.8932 144.982 16.2324 145.992 15.7793C147.011 15.3262 148.13 15.0996 149.348 15.0996C150.603 15.0996 151.736 15.3262 152.746 15.7793C153.766 16.2324 154.639 16.8932 155.366 17.7617C156.102 18.6208 156.664 19.6639 157.051 20.8911C157.447 22.1089 157.646 23.4919 157.646 25.04ZM154.941 26.3428V25.0117C154.941 23.7845 154.813 22.6989 154.559 21.7549C154.313 20.8109 153.95 20.0179 153.468 19.376C152.987 18.734 152.397 18.2479 151.698 17.9175C151.009 17.5871 150.226 17.4219 149.348 17.4219C148.498 17.4219 147.729 17.5871 147.04 17.9175C146.36 18.2479 145.775 18.734 145.284 19.376C144.802 20.0179 144.429 20.8109 144.165 21.7549C143.901 22.6989 143.769 23.7845 143.769 25.0117V26.3428C143.769 27.5794 143.901 28.6745 144.165 29.6279C144.429 30.5719 144.807 31.3696 145.298 32.021C145.798 32.6629 146.388 33.1491 147.068 33.4795C147.757 33.8099 148.526 33.9751 149.376 33.9751C150.263 33.9751 151.052 33.8099 151.741 33.4795C152.43 33.1491 153.01 32.6629 153.482 32.021C153.964 31.3696 154.327 30.5719 154.573 29.6279C154.818 28.6745 154.941 27.5794 154.941 26.3428ZM173.533 15.3828H176.252V29.3306C176.252 30.8787 175.907 32.1673 175.218 33.1963C174.529 34.2253 173.613 34.9993 172.471 35.5186C171.338 36.0283 170.106 36.2832 168.775 36.2832C167.378 36.2832 166.113 36.0283 164.98 35.5186C163.857 34.9993 162.965 34.2253 162.304 33.1963C161.653 32.1673 161.327 30.8787 161.327 29.3306V15.3828H164.032V29.3306C164.032 30.4067 164.23 31.2941 164.626 31.9927C165.023 32.6912 165.575 33.2104 166.283 33.5503C167.001 33.8901 167.831 34.0601 168.775 34.0601C169.729 34.0601 170.56 33.8901 171.268 33.5503C171.985 33.2104 172.542 32.6912 172.938 31.9927C173.335 31.2941 173.533 30.4067 173.533 29.3306V15.3828ZM186.122 36H181.817L181.845 33.7769H186.122C187.594 33.7769 188.821 33.4701 189.803 32.8564C190.785 32.2334 191.521 31.3649 192.012 30.251C192.513 29.1276 192.763 27.8154 192.763 26.3145V25.0542C192.763 23.8742 192.621 22.8263 192.338 21.9106C192.055 20.9855 191.639 20.2067 191.092 19.5742C190.544 18.9323 189.874 18.4461 189.081 18.1157C188.298 17.7853 187.396 17.6201 186.376 17.6201H181.732V15.3828H186.376C187.726 15.3828 188.958 15.6094 190.072 16.0625C191.186 16.5062 192.144 17.1528 192.947 18.0024C193.759 18.8426 194.382 19.8621 194.816 21.061C195.25 22.2505 195.467 23.591 195.467 25.0825V26.3145C195.467 27.806 195.25 29.1512 194.816 30.3501C194.382 31.5396 193.754 32.5544 192.933 33.3945C192.121 34.2347 191.139 34.8813 189.987 35.3345C188.845 35.7782 187.556 36 186.122 36ZM183.275 15.3828V36H180.542V15.3828H183.275Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.001 0C10.748 0 0 10.745 0 24.001C0 33.826 5.90999 42.271 14.369 45.982C14.301 44.308 14.357 42.293 14.784 40.47C15.246 38.522 17.106 27.5 17.106 27.5C17.106 27.5 17.106 25.861 17.106 23.595C17.106 20.039 19.434 21.819 22 21.819L25.5 23C32 23 42.5 23 42.5 23C42.5 23 32.943 15.5 26.5 15.5C19.221 15.5 18.5 15.5 18.5 15.5C18.5 17.594 13.5 18 13.5 18L11.5 15.5L9 14.5C9 7.684 13.52 8.069 24.922 8.069C34.086 8.069 48 14.5 42.5 23C42.5 23 33.219 23 25.5 23C22.912 23 28.336 31.09 27.5 29.5C27.5 29.5 28 33 22 37C21.492 38.85 18.111 45.575 17.2 47.015C19.359 47.653 21.64 48 24.001 48C37.255 48 48 37.255 48 24.001C48 10.745 37.255 0 24.001 0Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -30,7 +30,9 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Alarm information storage and distribution
|
||||
* 告警信息入库分发
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/10 12:58
|
||||
*/
|
||||
@@ -70,7 +72,7 @@ public class DispatchAlarm {
|
||||
try {
|
||||
Alert alert = dataQueue.pollAlertData();
|
||||
if (alert != null) {
|
||||
// 判断告警类型入库
|
||||
// Determining alarm type storage 判断告警类型入库
|
||||
storeAlertData(alert);
|
||||
// 通知分发
|
||||
sendAlertDataListener(alert);
|
||||
@@ -86,7 +88,7 @@ public class DispatchAlarm {
|
||||
}
|
||||
|
||||
private void storeAlertData(Alert alert) {
|
||||
// todo 使用缓存不直接操作库
|
||||
// todo Using the cache does not directly manipulate the library 使用缓存不直接操作库
|
||||
Monitor monitor = monitorService.getMonitor(alert.getMonitorId());
|
||||
if (monitor == null) {
|
||||
log.warn("Dispatch alarm the monitorId: {} not existed, ignored.", alert.getMonitorId());
|
||||
@@ -94,50 +96,70 @@ public class DispatchAlarm {
|
||||
}
|
||||
alert.setMonitorName(monitor.getName());
|
||||
if (monitor.getStatus() == CommonConstants.UN_MANAGE_CODE) {
|
||||
// When monitoring is not managed, ignore and silence its alarm messages
|
||||
// 当监控未管理时 忽略静默其告警信息
|
||||
return;
|
||||
}
|
||||
if (monitor.getStatus() == CommonConstants.AVAILABLE_CODE) {
|
||||
if (CommonConstants.AVAILABLE.equals(alert.getTarget())) {
|
||||
// Availability Alarm Need to change the monitoring status to unavailable
|
||||
// 可用性告警 需变更监控状态为不可用
|
||||
monitorService.updateMonitorStatus(monitor.getId(), CommonConstants.UN_AVAILABLE_CODE);
|
||||
} else if (CommonConstants.REACHABLE.equals(alert.getTarget())) {
|
||||
// Reachability alarm The monitoring status needs to be changed to unreachable
|
||||
// 可达性告警 需变更监控状态为不可达
|
||||
monitorService.updateMonitorStatus(monitor.getId(), CommonConstants.UN_REACHABLE_CODE);
|
||||
}
|
||||
} else {
|
||||
// If the alarm is restored, the monitoring state needs to be restored
|
||||
// 若是恢复告警 需对监控状态进行恢复
|
||||
if (alert.getStatus() == CommonConstants.ALERT_STATUS_CODE_RESTORED) {
|
||||
monitorService.updateMonitorStatus(alert.getMonitorId(), CommonConstants.AVAILABLE_CODE);
|
||||
}
|
||||
if (alert.getStatus() == CommonConstants.ALERT_STATUS_CODE_RESTORED) {
|
||||
monitorService.updateMonitorStatus(alert.getMonitorId(), CommonConstants.AVAILABLE_CODE);
|
||||
}
|
||||
}
|
||||
// 告警落库
|
||||
// Alarm drop library 告警落库
|
||||
alertService.addAlert(alert);
|
||||
}
|
||||
|
||||
private void sendAlertDataListener(Alert alert) {
|
||||
// todo 转发配置的邮件 微信 webhook
|
||||
// todo Forward configured email WeChat webhook 转发配置的邮件 微信 webhook
|
||||
List<NoticeReceiver> receivers = matchReceiverByNoticeRules(alert);
|
||||
// todo 发送通知这里暂时单线程
|
||||
// todo Send notification here temporarily single thread 发送通知这里暂时单线程
|
||||
for (NoticeReceiver receiver : receivers) {
|
||||
switch (receiver.getType()) {
|
||||
// todo 短信通知
|
||||
case 0: break;
|
||||
case 1: sendEmailAlert(receiver, alert); break;
|
||||
case 2: sendWebHookAlert(receiver, alert); break;
|
||||
case 3: sendWeChatAlert(receiver, alert); break;
|
||||
case 4: sendWeWorkRobotAlert(receiver, alert); break;
|
||||
case 5: sendDingTalkRobotAlert(receiver, alert); break;
|
||||
case 6: sendFlyBookAlert(receiver,alert); break;
|
||||
default: break;
|
||||
// todo SMS notification 短信通知
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
sendEmailAlert(receiver, alert);
|
||||
break;
|
||||
case 2:
|
||||
sendWebHookAlert(receiver, alert);
|
||||
break;
|
||||
case 3:
|
||||
sendWeChatAlert(receiver, alert);
|
||||
break;
|
||||
case 4:
|
||||
sendWeWorkRobotAlert(receiver, alert);
|
||||
break;
|
||||
case 5:
|
||||
sendDingTalkRobotAlert(receiver, alert);
|
||||
break;
|
||||
case 6:
|
||||
sendFlyBookAlert(receiver, alert);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send alert information through FeiShu
|
||||
* 通过飞书发送告警信息
|
||||
* @param receiver 接收人
|
||||
* @param alert 告警信息
|
||||
*
|
||||
* @param receiver Notification configuration information 通知配置信息
|
||||
* @param alert Alarm information 告警信息
|
||||
*/
|
||||
private void sendFlyBookAlert(NoticeReceiver receiver, Alert alert) {
|
||||
FlyBookWebHookDto flyBookWebHookDto = new FlyBookWebHookDto();
|
||||
@@ -183,9 +205,11 @@ public class DispatchAlarm {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send alarm information through DingTalk robot
|
||||
* 通过钉钉机器人发送告警信息
|
||||
* @param receiver 通知配置信息
|
||||
* @param alert 告警信息
|
||||
*
|
||||
* @param receiver Notification configuration information 通知配置信息
|
||||
* @param alert Alarm information 告警信息
|
||||
*/
|
||||
private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) {
|
||||
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
|
||||
@@ -216,9 +240,11 @@ public class DispatchAlarm {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send alarm information through enterprise WeChat
|
||||
* 通过企业微信发送告警信息
|
||||
* @param receiver 通知配置信息
|
||||
* @param alert 告警信息
|
||||
*
|
||||
* @param receiver Notification configuration information 通知配置信息
|
||||
* @param alert Alarm information 告警信息
|
||||
*/
|
||||
private void sendWeWorkRobotAlert(NoticeReceiver receiver, Alert alert) {
|
||||
WeWorkWebHookDto weWorkWebHookDTO = new WeWorkWebHookDto();
|
||||
@@ -231,7 +257,7 @@ public class DispatchAlarm {
|
||||
if (alert.getPriority() < CommonConstants.ALERT_PRIORITY_CODE_WARNING) {
|
||||
content.append("告警级别 : <font color=\"warning\">")
|
||||
.append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n");
|
||||
}else {
|
||||
} else {
|
||||
content.append("告警级别 : <font color=\"comment\">")
|
||||
.append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n");
|
||||
}
|
||||
@@ -273,28 +299,28 @@ public class DispatchAlarm {
|
||||
}
|
||||
|
||||
|
||||
private void sendEmailAlert(final NoticeReceiver receiver,final Alert alert){
|
||||
try{
|
||||
private void sendEmailAlert(final NoticeReceiver receiver, final Alert alert) {
|
||||
try {
|
||||
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
|
||||
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,true,"UTF-8");
|
||||
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
|
||||
messageHelper.setSubject("TanCloud探云-监控告警");
|
||||
//设置发件人Email
|
||||
//Set sender Email 设置发件人Email
|
||||
messageHelper.setFrom(emailFromUser);
|
||||
//设定收件人Email
|
||||
messageHelper.setTo(receiver.getEmail());
|
||||
//Set recipient Email 设定收件人Email
|
||||
messageHelper.setTo(receiver.getEmail());
|
||||
messageHelper.setSentDate(new Date());
|
||||
//构建邮件模版
|
||||
//Build email templates 构建邮件模版
|
||||
String process = mailService.buildAlertHtmlTemplate(alert);
|
||||
//设置邮件内容模版
|
||||
messageHelper.setText(process,true);
|
||||
//Set Email Content Template 设置邮件内容模版
|
||||
messageHelper.setText(process, true);
|
||||
javaMailSender.send(mimeMessage);
|
||||
}catch (Exception e){
|
||||
log.error("[邮箱告警] error,Exception information={}",e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("[Email Alert] Exception,Exception information={}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private List<NoticeReceiver> matchReceiverByNoticeRules(Alert alert) {
|
||||
// todo 使用缓存
|
||||
// todo use cache 使用缓存
|
||||
return noticeConfigService.getReceiverFilterRule(alert);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,13 @@ import java.util.List;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
/**
|
||||
* Message Notification Configuration API
|
||||
* 消息通知配置API
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/16 16:18
|
||||
*/
|
||||
@Api(tags = "消息通知配置API")
|
||||
@Api(tags = "en: Message Notification Configuration API,zh: 消息通知配置API")
|
||||
@RestController()
|
||||
@RequestMapping(value = "/notice", produces = {APPLICATION_JSON_VALUE})
|
||||
public class NoticeConfigController {
|
||||
@@ -41,33 +43,36 @@ public class NoticeConfigController {
|
||||
private NoticeConfigService noticeConfigService;
|
||||
|
||||
@PostMapping(path = "/receiver")
|
||||
@ApiOperation(value = "新增接收人", notes = "新增一个接收人")
|
||||
@ApiOperation(value = "Add a recipient", notes = "新增一个接收人")
|
||||
public ResponseEntity<Message<Void>> addNewNoticeReceiver(@Valid @RequestBody NoticeReceiver noticeReceiver) {
|
||||
noticeConfigService.addReceiver(noticeReceiver);
|
||||
return ResponseEntity.ok(new Message<>("Add success"));
|
||||
}
|
||||
|
||||
@PutMapping(path = "/receiver")
|
||||
@ApiOperation(value = "修改接收人", notes = "修改已存在的接收人信息")
|
||||
@ApiOperation(value = "Modify existing recipient information", notes = "修改已存在的接收人信息")
|
||||
public ResponseEntity<Message<Void>> editNoticeReceiver(@Valid @RequestBody NoticeReceiver noticeReceiver) {
|
||||
noticeConfigService.editReceiver(noticeReceiver);
|
||||
return ResponseEntity.ok(new Message<>("Edit success"));
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/receiver/{id}")
|
||||
@ApiOperation(value = "删除指定接收人", notes = "删除已存在的接收人信息")
|
||||
@ApiOperation(value = "Delete existing recipient information", notes = "删除已存在的接收人信息")
|
||||
public ResponseEntity<Message<Void>> deleteNoticeReceiver(
|
||||
@ApiParam(value = "接收人ID", example = "6565463543") @PathVariable("id") final Long receiverId) {
|
||||
// 不存在或删除成功都返回成功
|
||||
@ApiParam(value = "en: Recipient ID,zh: 接收人ID", example = "6565463543") @PathVariable("id") final Long receiverId) {
|
||||
// Returns success if it does not exist or if the deletion is successful
|
||||
// todo 不存在或删除成功都返回成功
|
||||
noticeConfigService.deleteReceiver(receiverId);
|
||||
return ResponseEntity.ok(new Message<>("Delete success"));
|
||||
}
|
||||
|
||||
@GetMapping(path = "/receivers")
|
||||
@ApiOperation(value = "查询消息通知接收人", notes = "根据查询过滤项获取消息通知接收人列表")
|
||||
@ApiOperation(value = "Get a list of message notification recipients based on query filter items",
|
||||
notes = "根据查询过滤项获取消息通知接收人列表")
|
||||
public ResponseEntity<Message<List<NoticeReceiver>>> getReceivers(
|
||||
@ApiParam(value = "接收人名称,模糊查询", example = "tom") @RequestParam(required = false) final String name) {
|
||||
@ApiParam(value = "en: Recipient name,zh: 接收人名称,模糊查询", example = "tom") @RequestParam(required = false) final String name) {
|
||||
|
||||
//todo Writing can be optimized 写法可优化
|
||||
Specification<NoticeReceiver> specification = (root, query, criteriaBuilder) -> {
|
||||
Predicate predicate = criteriaBuilder.conjunction();
|
||||
if (name != null && !"".equals(name)) {
|
||||
@@ -83,32 +88,34 @@ public class NoticeConfigController {
|
||||
|
||||
|
||||
@PostMapping(path = "/rule")
|
||||
@ApiOperation(value = "新增通知策略", notes = "新增一个通知策略")
|
||||
@ApiOperation(value = "Add a notification policy", notes = "新增一个通知策略")
|
||||
public ResponseEntity<Message<Void>> addNewNoticeRule(@Valid @RequestBody NoticeRule noticeRule) {
|
||||
noticeConfigService.addNoticeRule(noticeRule);
|
||||
return ResponseEntity.ok(new Message<>("Add success"));
|
||||
}
|
||||
|
||||
@PutMapping(path = "/rule")
|
||||
@ApiOperation(value = "修改通知策略", notes = "修改已存在的通知策略信息")
|
||||
@ApiOperation(value = "Modify existing notification policy information", notes = "修改已存在的通知策略信息")
|
||||
public ResponseEntity<Message<Void>> editNoticeRule(@Valid @RequestBody NoticeRule noticeRule) {
|
||||
noticeConfigService.editNoticeRule(noticeRule);
|
||||
return ResponseEntity.ok(new Message<>("Edit success"));
|
||||
}
|
||||
|
||||
@DeleteMapping(path = "/rule/{id}")
|
||||
@ApiOperation(value = "删除指定通知策略", notes = "删除已存在的通知策略信息")
|
||||
@ApiOperation(value = "Delete existing notification policy information", notes = "删除已存在的通知策略信息")
|
||||
public ResponseEntity<Message<Void>> deleteNoticeRule(
|
||||
@ApiParam(value = "通知策略ID", example = "6565463543") @PathVariable("id") final Long ruleId) {
|
||||
// 不存在或删除成功都返回成功
|
||||
@ApiParam(value = "en: Notification Policy ID,zh: 通知策略ID", example = "6565463543") @PathVariable("id") final Long ruleId) {
|
||||
// Returns success if it does not exist or if the deletion is successful
|
||||
// todo 不存在或删除成功都返回成功
|
||||
noticeConfigService.deleteNoticeRule(ruleId);
|
||||
return ResponseEntity.ok(new Message<>("Delete success"));
|
||||
}
|
||||
|
||||
@GetMapping(path = "/rules")
|
||||
@ApiOperation(value = "查询消息通知策略", notes = "根据查询过滤项获取消息通知策略列表")
|
||||
@ApiOperation(value = "Get a list of message notification policies based on query filter items",
|
||||
notes = "根据查询过滤项获取消息通知策略列表")
|
||||
public ResponseEntity<Message<List<NoticeRule>>> getRules(
|
||||
@ApiParam(value = "接收人名称,模糊查询", example = "rule1") @RequestParam(required = false) final String name) {
|
||||
@ApiParam(value = "en: Recipient name,zh: 接收人名称,模糊查询", example = "rule1") @RequestParam(required = false) final String name) {
|
||||
|
||||
Specification<NoticeRule> specification = (root, query, criteriaBuilder) -> {
|
||||
Predicate predicate = criteriaBuilder.conjunction();
|
||||
|
||||
@@ -18,11 +18,13 @@ import java.util.List;
|
||||
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
|
||||
|
||||
/**
|
||||
* System Summary Statistics API
|
||||
* 系统摘要统计API
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/7 15:57
|
||||
*/
|
||||
@Api(tags = "系统摘要统计API")
|
||||
@Api(tags = "en: System Summary Statistics API,zh: 系统摘要统计API")
|
||||
@RestController
|
||||
@RequestMapping(path = "/summary", produces = {APPLICATION_JSON_VALUE})
|
||||
public class SummaryController {
|
||||
@@ -31,7 +33,7 @@ public class SummaryController {
|
||||
private MonitorService monitorService;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation(value = "查询应用类别监控统计", notes = "查询所有应用类别监控统计信息")
|
||||
@ApiOperation(value = "Query all application category monitoring statistics", notes = "查询所有应用类别监控统计信息")
|
||||
public ResponseEntity<Message<Dashboard>> appMonitors() {
|
||||
List<AppCount> appsCount = monitorService.getAllAppMonitorsCount();
|
||||
Message<Dashboard> message = new Message<>(new Dashboard(appsCount));
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* AuthResources 数据库操作
|
||||
*
|
||||
* @author tomsun28
|
||||
* @date 2021/11/14 11:24
|
||||
*/
|
||||
@@ -22,12 +23,14 @@ public interface MonitorDao extends JpaRepository<Monitor, Long>, JpaSpecificati
|
||||
|
||||
/**
|
||||
* 根据监控ID列表删除监控
|
||||
*
|
||||
* @param monitorIds 监控ID列表
|
||||
*/
|
||||
void deleteAllByIdIn(Set<Long> monitorIds);
|
||||
|
||||
/**
|
||||
* 根据监控ID列表查询监控
|
||||
*
|
||||
* @param monitorIds 监控ID列表
|
||||
* @return 监控列表
|
||||
*/
|
||||
@@ -35,6 +38,7 @@ public interface MonitorDao extends JpaRepository<Monitor, Long>, JpaSpecificati
|
||||
|
||||
/**
|
||||
* 根据监控类型查询监控
|
||||
*
|
||||
* @param app 监控类型
|
||||
* @return 监控列表
|
||||
*/
|
||||
@@ -42,29 +46,35 @@ public interface MonitorDao extends JpaRepository<Monitor, Long>, JpaSpecificati
|
||||
|
||||
/**
|
||||
* 查询已下发采集任务的监控
|
||||
*
|
||||
* @param status 监控状态
|
||||
* @return 监控列表
|
||||
*/
|
||||
List<Monitor> findMonitorsByStatusNotInAndAndJobIdNotNull(List<Byte> status);
|
||||
|
||||
/**
|
||||
* 根据监控名称查询监控
|
||||
* @param name 监控名称
|
||||
* @return 监控列表
|
||||
* Query monitoring by monitoring name 根据监控名称查询监控
|
||||
*
|
||||
* @param name monitoring name 监控名称
|
||||
* @return monitoring list 监控列表
|
||||
*/
|
||||
Optional<Monitor> findMonitorByNameEquals(String name);
|
||||
|
||||
/**
|
||||
* Query the monitoring category - the number of monitoring corresponding to the status
|
||||
* 查询监控类别-状态对应的监控数量
|
||||
* @return 监控类别-状态与监控数量映射
|
||||
*
|
||||
* @return Monitoring Category-Status and Monitoring Quantity Mapping 监控类别-状态与监控数量映射
|
||||
*/
|
||||
@Query("select new com.usthe.manager.pojo.dto.AppCount(mo.app, mo.status, COUNT(mo.id)) from Monitor mo group by mo.app, mo.status")
|
||||
List<AppCount> findAppsStatusCount();
|
||||
|
||||
/**
|
||||
* Update the status of the specified monitor
|
||||
* 更新指定监控的状态
|
||||
* @param id 监控ID
|
||||
* @param status 监控状态
|
||||
*
|
||||
* @param id Monitor ID 监控ID
|
||||
* @param status 监控状态 Monitor Status
|
||||
*/
|
||||
@Modifying
|
||||
@Query("update Monitor set status = :status where id = :id")
|
||||
|
||||
@@ -7,6 +7,7 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 企业微信机器人请求消息体
|
||||
*
|
||||
* @author 花城
|
||||
* @version 1.0
|
||||
* @date 2022/2/21 6:55 下午
|
||||
@@ -18,7 +19,14 @@ import lombok.NoArgsConstructor;
|
||||
public class WeWorkWebHookDto {
|
||||
|
||||
public static final String WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=";
|
||||
/**
|
||||
* markdown格式
|
||||
*/
|
||||
private static final String MARKDOWN = "markdown";
|
||||
/**
|
||||
* 文本格式
|
||||
*/
|
||||
private static final String TEXT = "TEXT";
|
||||
|
||||
/**
|
||||
* 消息类型
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 邮箱发送服务
|
||||
* Email delivery service 邮箱发送服务
|
||||
*
|
||||
* @author 花城
|
||||
* @version 1.0
|
||||
@@ -15,9 +15,11 @@ import org.springframework.stereotype.Service;
|
||||
public interface MailService {
|
||||
|
||||
/**
|
||||
* Build an alert email template
|
||||
* 构建告警邮件模版
|
||||
* @param alert 告警信息
|
||||
* @return 邮件内容
|
||||
*
|
||||
* @param alert Alarm data element information 告警数据元信息
|
||||
* @return content of email 邮件内容
|
||||
*/
|
||||
String buildAlertHtmlTemplate(Alert alert);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* 监控管理服务
|
||||
*
|
||||
* @author tomsun28
|
||||
* @date 2021/11/14 11:28
|
||||
*/
|
||||
@@ -23,38 +24,43 @@ public interface MonitorService {
|
||||
|
||||
/**
|
||||
* 监控可用性探测
|
||||
*
|
||||
* @param monitor 监控实体信息
|
||||
* @param params 参数信息
|
||||
* @param params 参数信息
|
||||
* @throws MonitorDetectException 探测失败抛出
|
||||
*/
|
||||
void detectMonitor(Monitor monitor, List<Param> params) throws MonitorDetectException;
|
||||
|
||||
/**
|
||||
* 新增监控
|
||||
*
|
||||
* @param monitor 监控实体
|
||||
* @param params 参数信息
|
||||
* @param params 参数信息
|
||||
* @throws RuntimeException 新增过程异常抛出
|
||||
*/
|
||||
void addMonitor(Monitor monitor, List<Param> params) throws RuntimeException;
|
||||
|
||||
/**
|
||||
* 校验请求数据参数正确性
|
||||
*
|
||||
* @param monitorDto monitorDto
|
||||
* @param isModify 是否是修改监控
|
||||
* @param isModify 是否是修改监控
|
||||
* @throws IllegalArgumentException 校验参数错误抛出
|
||||
*/
|
||||
void validate(MonitorDto monitorDto, Boolean isModify) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* 修改更新监控
|
||||
*
|
||||
* @param monitor 监控实体
|
||||
* @param params 参数信息
|
||||
* @param params 参数信息
|
||||
* @throws RuntimeException 修改过程中异常抛出
|
||||
*/
|
||||
void modifyMonitor(Monitor monitor, List<Param> params) throws RuntimeException;
|
||||
|
||||
/**
|
||||
* 删除监控
|
||||
*
|
||||
* @param id 监控ID
|
||||
* @throws RuntimeException 删除过程中异常抛出
|
||||
*/
|
||||
@@ -62,6 +68,7 @@ public interface MonitorService {
|
||||
|
||||
/**
|
||||
* 批量删除监控
|
||||
*
|
||||
* @param ids 监控ID
|
||||
* @throws RuntimeException 删除过程中异常抛出
|
||||
*/
|
||||
@@ -69,6 +76,7 @@ public interface MonitorService {
|
||||
|
||||
/**
|
||||
* 获取监控信息
|
||||
*
|
||||
* @param id 监控ID
|
||||
* @return MonitorDto
|
||||
* @throws RuntimeException 查询过程中异常抛出
|
||||
@@ -77,46 +85,55 @@ public interface MonitorService {
|
||||
|
||||
/**
|
||||
* 动态条件查询
|
||||
*
|
||||
* @param specification 查询条件
|
||||
* @param pageRequest 分页参数
|
||||
* @param pageRequest 分页参数
|
||||
* @return 查询结果
|
||||
*/
|
||||
Page<Monitor> getMonitors(Specification<Monitor> specification, PageRequest pageRequest);
|
||||
|
||||
/**
|
||||
* 根据监控ID列表批量取消纳管监控项
|
||||
*
|
||||
* @param ids 监控IDs
|
||||
*/
|
||||
void cancelManageMonitors(HashSet<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据监控ID列表批量启动纳管监控项
|
||||
*
|
||||
* @param ids 监控IDs
|
||||
*/
|
||||
void enableManageMonitors(HashSet<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询监控类别及其对应的监控数量
|
||||
*
|
||||
* @return 监控类别与监控数量映射
|
||||
*/
|
||||
List<AppCount> getAllAppMonitorsCount();
|
||||
|
||||
/**
|
||||
* Query monitoring
|
||||
* 查询监控
|
||||
* @param monitorId 监控ID
|
||||
* @return 监控信息
|
||||
*
|
||||
* @param monitorId Monitor ID 监控ID
|
||||
* @return Monitor information 监控信息
|
||||
*/
|
||||
Monitor getMonitor(Long monitorId);
|
||||
|
||||
/**
|
||||
* Update the status of the specified monitor
|
||||
* 更新指定监控的状态
|
||||
* @param monitorId 监控ID
|
||||
* @param status 监控状态
|
||||
*
|
||||
* @param monitorId monitorId 监控ID
|
||||
* @param status monitor status 监控状态
|
||||
*/
|
||||
void updateMonitorStatus(Long monitorId, byte status);
|
||||
|
||||
/**
|
||||
* 查询指定监控类型下的所有监控信息列表
|
||||
*
|
||||
* @param app 监控类型
|
||||
* @return 监控列表
|
||||
*/
|
||||
|
||||
@@ -8,66 +8,86 @@ import org.springframework.data.jpa.domain.Specification;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Message notification configuration interface
|
||||
* 消息通知配置接口
|
||||
*
|
||||
* @author tom
|
||||
* @date 2021/12/16 16:14
|
||||
*/
|
||||
public interface NoticeConfigService {
|
||||
|
||||
/**
|
||||
* Dynamic conditional query
|
||||
* 动态条件查询
|
||||
* @param specification 查询条件
|
||||
* @return 查询结果
|
||||
*
|
||||
* @param specification Query conditions 查询条件
|
||||
* @return Search result 查询结果
|
||||
*/
|
||||
List<NoticeReceiver> getNoticeReceivers(Specification<NoticeReceiver> specification);
|
||||
|
||||
/**
|
||||
* Dynamic conditional query
|
||||
* 动态条件查询
|
||||
* @param specification 查询条件
|
||||
* @return 查询结果
|
||||
*
|
||||
* @param specification Query conditions 查询条件
|
||||
* @return Search result 查询结果
|
||||
*/
|
||||
List<NoticeRule> getNoticeRules(Specification<NoticeRule> specification);
|
||||
|
||||
/**
|
||||
* Add a notification recipient
|
||||
* 新增一个通知接收人
|
||||
* @param noticeReceiver 接收人信息
|
||||
*
|
||||
* @param noticeReceiver recipient information 接收人信息
|
||||
*/
|
||||
void addReceiver(NoticeReceiver noticeReceiver);
|
||||
|
||||
/**
|
||||
* Modify notification recipients
|
||||
* 修改通知接收人
|
||||
* @param noticeReceiver 接收人信息
|
||||
*
|
||||
* @param noticeReceiver recipient information 接收人信息
|
||||
*/
|
||||
void editReceiver(NoticeReceiver noticeReceiver);
|
||||
|
||||
/**
|
||||
* Delete recipient information based on recipient ID
|
||||
* 根据接收人ID删除接收人信息
|
||||
* @param receiverId 接收人ID
|
||||
*
|
||||
* @param receiverId Recipient ID 接收人ID
|
||||
*/
|
||||
void deleteReceiver(Long receiverId);
|
||||
|
||||
/**
|
||||
* Added notification policy
|
||||
* 新增通知策略
|
||||
* @param noticeRule 通知策略
|
||||
*
|
||||
* @param noticeRule Notification strategy 通知策略
|
||||
*/
|
||||
void addNoticeRule(NoticeRule noticeRule);
|
||||
|
||||
/**
|
||||
* Modify Notification Policy
|
||||
* 修改通知策略
|
||||
* @param noticeRule 通知策略
|
||||
*
|
||||
* @param noticeRule Notification strategy 通知策略
|
||||
*/
|
||||
void editNoticeRule(NoticeRule noticeRule);
|
||||
|
||||
/**
|
||||
* Delete the specified notification policy
|
||||
* 删除指定的通知策略
|
||||
* @param ruleId 通知策略ID
|
||||
*
|
||||
* @param ruleId Notification Policy ID 通知策略ID
|
||||
*/
|
||||
void deleteNoticeRule(Long ruleId);
|
||||
|
||||
/**
|
||||
* According to the alarm information matching all notification policies, filter out the recipients who need to be notified
|
||||
* 根据告警信息与所有通知策略匹配,过滤出需要通知的接收人
|
||||
* @param alert 告警信息
|
||||
* @return 接收人
|
||||
*
|
||||
* @param alert Alarm information 告警信息
|
||||
* @return Receiver 接收人
|
||||
*/
|
||||
List<NoticeReceiver> getReceiverFilterRule(Alert alert);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.usthe.manager.service.AppService;
|
||||
import com.usthe.manager.service.MonitorService;
|
||||
import com.usthe.manager.support.exception.MonitorDatabaseException;
|
||||
import com.usthe.manager.support.exception.MonitorDetectException;
|
||||
import jdk.nashorn.internal.runtime.regexp.joni.constants.Traverse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -40,6 +41,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 监控管理服务实现
|
||||
*
|
||||
* @author tomsun28
|
||||
* @date 2021/11/14 13:06
|
||||
*/
|
||||
@@ -236,6 +238,9 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
case "checkbox":
|
||||
// todo checkbox校验
|
||||
break;
|
||||
case "key-value":
|
||||
// todo key-value校验
|
||||
break;
|
||||
// todo 更多参数定义与实际值格式校验
|
||||
default:
|
||||
throw new IllegalArgumentException("ParamDefine type " + paramDefine.getType() + " is invalid.");
|
||||
@@ -384,7 +389,8 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
if (appCounts == null) {
|
||||
return null;
|
||||
}
|
||||
// 关联大类别信息 计算每个状态对应数量
|
||||
//Statistical category information, calculate the number of corresponding states for each monitor
|
||||
//统计类别信息,计算每个监控分别对应状态的数量
|
||||
Map<String, AppCount> appCountMap = new HashMap<>(appCounts.size());
|
||||
for (AppCount item : appCounts) {
|
||||
AppCount appCount = appCountMap.getOrDefault(item.getApp(), new AppCount());
|
||||
@@ -402,10 +408,13 @@ public class MonitorServiceImpl implements MonitorService {
|
||||
case CommonConstants.UN_REACHABLE_CODE:
|
||||
appCount.setUnReachableSize(appCount.getUnReachableSize() + item.getSize());
|
||||
break;
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
appCountMap.put(item.getApp(), appCount);
|
||||
}
|
||||
//Traverse the map obtained by statistics and convert it into a List<App Count> result set
|
||||
//遍历统计得到的map,转换成List<App Count>结果集
|
||||
return appCountMap.values().stream().peek(item -> {
|
||||
item.setSize(item.getAvailableSize() + item.getUnManageSize()
|
||||
+ item.getUnReachableSize() + item.getUnAvailableSize());
|
||||
|
||||
@@ -5,7 +5,7 @@ app: example
|
||||
name:
|
||||
zh-CN: 模拟应用类型
|
||||
en-US: EXAMPLE APP
|
||||
# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
|
||||
# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串, 3-map映射的json串
|
||||
# 强制固定必须参数 - host
|
||||
configmap:
|
||||
- key: host
|
||||
@@ -16,6 +16,8 @@ configmap:
|
||||
type: 1
|
||||
- key: password
|
||||
type: 2
|
||||
- key: headers
|
||||
type: 3
|
||||
# 指标组列表
|
||||
metrics:
|
||||
# 第一个监控指标组 cpu
|
||||
@@ -69,7 +71,7 @@ metrics:
|
||||
ssl: false
|
||||
# 请求头内容
|
||||
headers:
|
||||
apiVersion: v1
|
||||
^_^headers^_^: ^_^headers^_^
|
||||
# 请求参数内容
|
||||
params:
|
||||
param1: param1
|
||||
|
||||
@@ -26,6 +26,12 @@ configmap:
|
||||
type: 1
|
||||
- key: payload
|
||||
type: 1
|
||||
- key: authType
|
||||
type: 1
|
||||
- key: headers
|
||||
type: 3
|
||||
- key: params
|
||||
type: 3
|
||||
# 指标组列表
|
||||
metrics:
|
||||
# 第一个监控指标组 cpu
|
||||
@@ -58,12 +64,18 @@ metrics:
|
||||
# 请求头内容
|
||||
headers:
|
||||
content-type: ^_^contentType^_^
|
||||
^_^headers^_^: ^_^headers^_^
|
||||
# 请求参数内容
|
||||
params:
|
||||
^_^params^_^: ^_^params^_^
|
||||
# 认证
|
||||
authorization:
|
||||
# 认证方式: Basic Auth, Digest Auth, Bearer Token
|
||||
type: Basic Auth
|
||||
type: ^_^authType^_^
|
||||
basicAuthUsername: ^_^username^_^
|
||||
basicAuthPassword: ^_^password^_^
|
||||
digestAuthUsername: ^_^username^_^
|
||||
digestAuthPassword: ^_^password^_^
|
||||
# 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-网站可用性指标监控
|
||||
# todo xmlPath-xmlPath脚本,prometheus-Prometheus数据规则
|
||||
parseType: website
|
||||
@@ -16,6 +16,8 @@ configmap:
|
||||
type: 1
|
||||
- key: password
|
||||
type: 2
|
||||
- key: timeout
|
||||
type: 0
|
||||
# 指标组列表
|
||||
metrics:
|
||||
# 第一个监控指标组 basic
|
||||
@@ -44,6 +46,7 @@ metrics:
|
||||
port: ^_^port^_^
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
timeout: ^_^timeout^_^
|
||||
script: (uname -r ; hostname ; uptime | awk -F "," '{print $1}' | sed "s/ //g") | sed ":a;N;s/\n/^/g;ta" | awk -F '^' 'BEGIN{print "version hostname uptime"} {print $1, $2, $3}'
|
||||
# 响应数据解析方式:oneRow, multiRow
|
||||
parseType: multiRow
|
||||
@@ -75,6 +78,7 @@ metrics:
|
||||
port: ^_^port^_^
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
timeout: ^_^timeout^_^
|
||||
script: "LANG=C lscpu | awk -F: '/Model name/ {print $2}';awk '/processor/{core++} END{print core}' /proc/cpuinfo;uptime | sed 's/,/ /g' | awk '{for(i=NF-2;i<=NF;i++)print $i }' | xargs;vmstat 1 1 | awk 'NR==3{print $11}';vmstat 1 1 | awk 'NR==3{print $12}'"
|
||||
parseType: oneRow
|
||||
|
||||
@@ -107,6 +111,7 @@ metrics:
|
||||
port: ^_^port^_^
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
timeout: ^_^timeout^_^
|
||||
script: free -m | grep Mem | awk 'BEGIN{print "total used free buff_cache available"} {print $2,$3,$4,$6,$7}'
|
||||
parseType: multiRow
|
||||
|
||||
@@ -139,6 +144,7 @@ metrics:
|
||||
port: ^_^port^_^
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
timeout: ^_^timeout^_^
|
||||
script: vmstat -D | awk 'NR==1{print $1}';vmstat -D | awk 'NR==2{print $1}';vmstat 1 1 | awk 'NR==3{print $10}';vmstat 1 1 | awk 'NR==3{print $9}';vmstat 1 1 | awk 'NR==3{print $16}'
|
||||
parseType: oneRow
|
||||
|
||||
@@ -164,5 +170,6 @@ metrics:
|
||||
port: ^_^port^_^
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
timeout: ^_^timeout^_^
|
||||
script: cat /proc/net/dev | tail -n +3 | awk 'BEGIN{ print "interface_name receive_bytes transmit_bytes"} {print $1,$2,$10}'
|
||||
parseType: multiRow
|
||||
182
manager/src/main/resources/define/app/oracle.yml
Normal file
182
manager/src/main/resources/define/app/oracle.yml
Normal file
@@ -0,0 +1,182 @@
|
||||
category: db
|
||||
app: oracle
|
||||
name:
|
||||
zh-CN: Oracle数据库
|
||||
en-US: Oracle DB
|
||||
# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
|
||||
# 强制固定必须参数 - host
|
||||
configmap:
|
||||
- key: host
|
||||
type: 1
|
||||
- key: port
|
||||
type: 0
|
||||
- key: username
|
||||
type: 1
|
||||
- key: password
|
||||
type: 2
|
||||
- key: database
|
||||
type: 1
|
||||
- key: timeout
|
||||
type: 0
|
||||
- key: url
|
||||
type: 1
|
||||
# 指标组列表
|
||||
metrics:
|
||||
- name: basic
|
||||
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
|
||||
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
|
||||
priority: 0
|
||||
# 指标组中的具体监控指标
|
||||
fields:
|
||||
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
|
||||
- field: database_version
|
||||
type: 1
|
||||
instance: true
|
||||
- field: database_type
|
||||
type: 1
|
||||
- field: hostname
|
||||
type: 1
|
||||
- field: instance_name
|
||||
type: 1
|
||||
- field: startup_time
|
||||
type: 1
|
||||
- field: status
|
||||
type: 1
|
||||
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
|
||||
aliasFields:
|
||||
- VERSION
|
||||
- DATABASE_TYPE
|
||||
- HOST_NAME
|
||||
- INSTANCE_NAME
|
||||
- STARTUP_TIME
|
||||
- STATUS
|
||||
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
|
||||
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
|
||||
calculates:
|
||||
- database_version=VERSION
|
||||
- database_type=DATABASE_TYPE
|
||||
- hostname=HOST_NAME
|
||||
- instance_name=INSTANCE_NAME
|
||||
- startup_time=STARTUP_TIME
|
||||
- status=STATUS
|
||||
protocol: jdbc
|
||||
jdbc:
|
||||
# 主机host: ipv4 ipv6 域名
|
||||
host: ^_^host^_^
|
||||
# 端口
|
||||
port: ^_^port^_^
|
||||
platform: oracle
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
database: ^_^database^_^
|
||||
timeout: ^_^timeout^_^
|
||||
# SQL查询方式: oneRow, multiRow, columns
|
||||
queryType: oneRow
|
||||
# sql
|
||||
sql: select * from sys.v_$instance
|
||||
url: ^_^url^_^
|
||||
|
||||
- name: tablespace
|
||||
priority: 1
|
||||
# 指标组中的具体监控指标
|
||||
fields:
|
||||
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
|
||||
- field: file_id
|
||||
type: 1
|
||||
instance: true
|
||||
- field: file_name
|
||||
type: 1
|
||||
- field: tablespace_name
|
||||
type: 1
|
||||
- field: status
|
||||
type: 1
|
||||
- field: bytes
|
||||
type: 0
|
||||
unit: MB
|
||||
- field: blocks
|
||||
type: 0
|
||||
unit: 块数
|
||||
protocol: jdbc
|
||||
jdbc:
|
||||
# 主机host: ipv4 ipv6 域名
|
||||
host: ^_^host^_^
|
||||
# 端口
|
||||
port: ^_^port^_^
|
||||
platform: oracle
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
database: ^_^database^_^
|
||||
timeout: ^_^timeout^_^
|
||||
# SQL查询方式: oneRow, multiRow, columns
|
||||
queryType: oneRow
|
||||
# sql
|
||||
sql: select file_id, file_name, tablespace_name, status, bytes / 1024 / 1024 as bytes, blocks from dba_data_files
|
||||
url: ^_^url^_^
|
||||
|
||||
- name: user_connect
|
||||
priority: 1
|
||||
fields:
|
||||
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
|
||||
- field: username
|
||||
type: 1
|
||||
instance: true
|
||||
- field: counts
|
||||
type: 0
|
||||
unit: 连接数
|
||||
protocol: jdbc
|
||||
jdbc:
|
||||
# 主机host: ipv4 ipv6 域名
|
||||
host: ^_^host^_^
|
||||
# 端口
|
||||
port: ^_^port^_^
|
||||
platform: oracle
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
database: ^_^database^_^
|
||||
timeout: ^_^timeout^_^
|
||||
# SQL查询方式: oneRow, multiRow, columns
|
||||
queryType: oneRow
|
||||
# sql
|
||||
sql: SELECT username, count( username ) as counts FROM v$session WHERE username IS NOT NULL GROUP BY username
|
||||
url: ^_^url^_^
|
||||
|
||||
- name: performance
|
||||
priority: 1
|
||||
fields:
|
||||
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
|
||||
- field: qps
|
||||
type: 0
|
||||
unit: qps
|
||||
- field: tps
|
||||
type: 0
|
||||
unit: tps
|
||||
- field: mbps
|
||||
type: 0
|
||||
unit: mbps
|
||||
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
|
||||
aliasFields:
|
||||
- I/O Requests per Second
|
||||
- User Transaction Per Sec
|
||||
- I/O Megabytes per Second
|
||||
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
|
||||
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
|
||||
calculates:
|
||||
- qps=I/O Requests per Second
|
||||
- tps=User Transaction Per Sec
|
||||
- mbps=I/O Megabytes per Second
|
||||
protocol: jdbc
|
||||
jdbc:
|
||||
# 主机host: ipv4 ipv6 域名
|
||||
host: ^_^host^_^
|
||||
# 端口
|
||||
port: ^_^port^_^
|
||||
platform: oracle
|
||||
username: ^_^username^_^
|
||||
password: ^_^password^_^
|
||||
database: ^_^database^_^
|
||||
timeout: ^_^timeout^_^
|
||||
# SQL查询方式: oneRow, multiRow, columns
|
||||
queryType: columns
|
||||
# sql
|
||||
sql: select metric_name, value from gv$sysmetric where metric_name = 'I/O Megabytes per Second' or metric_name = 'User Transaction Per Sec' or metric_name = 'I/O Requests per Second'
|
||||
url: ^_^url^_^
|
||||
@@ -12,6 +12,12 @@ configmap:
|
||||
type: 1
|
||||
- key: ssl
|
||||
type: 1
|
||||
- key: authType
|
||||
type: 1
|
||||
- key: username
|
||||
type: 1
|
||||
- key: password
|
||||
type: 2
|
||||
# 指标组列表
|
||||
metrics:
|
||||
# 第一个监控指标组 cpu
|
||||
@@ -40,6 +46,13 @@ metrics:
|
||||
method: GET
|
||||
# 是否启用ssl/tls,即是http还是https,默认false
|
||||
ssl: ^_^ssl^_^
|
||||
authorization:
|
||||
# 认证方式: Basic Auth, Digest Auth, Bearer Token
|
||||
type: ^_^authType^_^
|
||||
basicAuthUsername: ^_^username^_^
|
||||
basicAuthPassword: ^_^password^_^
|
||||
digestAuthUsername: ^_^username^_^
|
||||
digestAuthPassword: ^_^password^_^
|
||||
# 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-网站可用性指标监控
|
||||
# todo xmlPath-xmlPath脚本,prometheus-Prometheus数据规则
|
||||
parseType: website
|
||||
@@ -48,4 +48,10 @@ param:
|
||||
- label: PUT请求
|
||||
value: PUT
|
||||
- label: DELETE请求
|
||||
value: DELETE
|
||||
value: DELETE
|
||||
- field: headers
|
||||
name: 请求Headers
|
||||
type: key-value
|
||||
required: false
|
||||
keyAlias: Header Name
|
||||
valueAlias: Header Value
|
||||
@@ -17,13 +17,6 @@ param:
|
||||
range: '[0,65535]'
|
||||
required: true
|
||||
defaultValue: 80
|
||||
- field: uri
|
||||
name: 相对路径
|
||||
type: text
|
||||
# 当type为text时,用limit表示字符串限制大小
|
||||
limit: 200
|
||||
required: false
|
||||
placeholder: 'API地址除IP端口外的路径 例如:/v2/book/bar'
|
||||
- field: method
|
||||
name: 请求方式
|
||||
type: radio
|
||||
@@ -38,21 +31,30 @@ param:
|
||||
value: PUT
|
||||
- label: DELETE请求
|
||||
value: DELETE
|
||||
- field: uri
|
||||
name: 相对路径
|
||||
type: text
|
||||
# 当type为text时,用limit表示字符串限制大小
|
||||
limit: 200
|
||||
required: false
|
||||
placeholder: 'API地址除IP端口外的路径 例如:/v2/book/bar'
|
||||
- field: ssl
|
||||
name: 启用HTTPS
|
||||
# 当type为boolean时,前端用switch展示开关
|
||||
type: boolean
|
||||
required: true
|
||||
- field: username
|
||||
name: 用户名
|
||||
type: text
|
||||
# 当type为text时,用limit表示字符串限制大小
|
||||
limit: 20
|
||||
- field: headers
|
||||
name: 请求Headers
|
||||
type: key-value
|
||||
required: false
|
||||
- field: password
|
||||
name: 密码
|
||||
type: password
|
||||
keyAlias: Header Name
|
||||
valueAlias: Header Value
|
||||
- field: params
|
||||
name: 查询Params
|
||||
type: key-value
|
||||
required: false
|
||||
keyAlias: Param Key
|
||||
valueAlias: Param Value
|
||||
- field: contentType
|
||||
name: Content-Type
|
||||
type: text
|
||||
@@ -63,3 +65,23 @@ param:
|
||||
type: textarea
|
||||
placeholder: 'POST PUT请求时有效'
|
||||
required: false
|
||||
- field: authType
|
||||
name: 认证方式
|
||||
type: radio
|
||||
required: false
|
||||
# 当type为radio单选框,checkbox复选框时,option表示可选项值列表 {name1:value1,name2:value2}
|
||||
options:
|
||||
- label: Basic Auth
|
||||
value: Basic Auth
|
||||
- label: Digest Auth
|
||||
value: Digest Auth
|
||||
- field: username
|
||||
name: 用户名
|
||||
type: text
|
||||
# 当type为text时,用limit表示字符串限制大小
|
||||
limit: 20
|
||||
required: false
|
||||
- field: password
|
||||
name: 密码
|
||||
type: password
|
||||
required: false
|
||||
|
||||
@@ -11,6 +11,12 @@ param:
|
||||
required: true
|
||||
defaultValue: 22
|
||||
placeholder: '请输入端口'
|
||||
- field: timeout
|
||||
name: 超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 6000
|
||||
placeholder: '超时时间'
|
||||
- field: username
|
||||
name: 用户名
|
||||
type: text
|
||||
@@ -19,4 +25,4 @@ param:
|
||||
- field: password
|
||||
name: 密码
|
||||
type: password
|
||||
required: true
|
||||
required: false
|
||||
@@ -15,7 +15,7 @@ param:
|
||||
name: 查询超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
placeholder: '查询超时时间'
|
||||
- field: database
|
||||
name: 数据库名称
|
||||
|
||||
@@ -15,7 +15,7 @@ param:
|
||||
name: 查询超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
placeholder: '查询超时时间'
|
||||
- field: database
|
||||
name: 数据库名称
|
||||
|
||||
36
manager/src/main/resources/define/param/oracle.yml
Normal file
36
manager/src/main/resources/define/param/oracle.yml
Normal file
@@ -0,0 +1,36 @@
|
||||
app: oracle
|
||||
param:
|
||||
- field: host
|
||||
name: 主机Host
|
||||
type: host
|
||||
required: true
|
||||
- field: port
|
||||
name: 端口
|
||||
type: number
|
||||
range: '[0,65535]'
|
||||
required: true
|
||||
defaultValue: 1521
|
||||
placeholder: '请输入端口'
|
||||
- field: timeout
|
||||
name: 查询超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 6000
|
||||
placeholder: '查询超时时间'
|
||||
- field: database
|
||||
name: 数据库名称
|
||||
type: text
|
||||
required: false
|
||||
- field: username
|
||||
name: 用户名
|
||||
type: text
|
||||
limit: 20
|
||||
required: false
|
||||
- field: password
|
||||
name: 密码
|
||||
type: password
|
||||
required: false
|
||||
- field: url
|
||||
name: URL
|
||||
type: text
|
||||
required: false
|
||||
@@ -17,4 +17,4 @@ param:
|
||||
range: '[0,100000]'
|
||||
required: true
|
||||
placeholder: '请输入超时时间,单位毫秒'
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
@@ -24,4 +24,4 @@ param:
|
||||
range: '[0,100000]'
|
||||
required: true
|
||||
placeholder: '请输入超时时间,单位毫秒'
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
@@ -15,7 +15,7 @@ param:
|
||||
name: 查询超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
placeholder: '查询超时时间'
|
||||
- field: database
|
||||
name: 数据库名称
|
||||
|
||||
@@ -15,7 +15,7 @@ param:
|
||||
name: 查询超时时间
|
||||
type: number
|
||||
required: false
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
placeholder: '查询超时时间'
|
||||
- field: database
|
||||
name: 数据库名称
|
||||
|
||||
@@ -24,4 +24,4 @@ param:
|
||||
range: '[0,100000]'
|
||||
required: true
|
||||
placeholder: '请输入超时时间,单位毫秒'
|
||||
defaultValue: 3000
|
||||
defaultValue: 6000
|
||||
@@ -28,4 +28,24 @@ param:
|
||||
name: 启用HTTPS
|
||||
# 当type为boolean时,前端用switch展示开关
|
||||
type: boolean
|
||||
required: true
|
||||
required: true
|
||||
- field: authType
|
||||
name: 认证方式
|
||||
type: radio
|
||||
required: false
|
||||
# 当type为radio单选框,checkbox复选框时,option表示可选项值列表 {name1:value1,name2:value2}
|
||||
options:
|
||||
- label: Basic Auth
|
||||
value: Basic Auth
|
||||
- label: Digest Auth
|
||||
value: Digest Auth
|
||||
- field: username
|
||||
name: 用户名
|
||||
type: text
|
||||
# 当type为text时,用limit表示字符串限制大小
|
||||
limit: 20
|
||||
required: false
|
||||
- field: password
|
||||
name: 密码
|
||||
type: password
|
||||
required: false
|
||||
23
script/assembly/server/bin/shutdown.bat
Normal file
23
script/assembly/server/bin/shutdown.bat
Normal file
@@ -0,0 +1,23 @@
|
||||
@title HertzBeat
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem 项目名称
|
||||
set SERVER_NAME="${project.artifactId}"
|
||||
|
||||
|
||||
rem 应用的端口号
|
||||
set SERVER_PORT=1157
|
||||
|
||||
echo Start shutdown HertzBeat %SERVER_NAME%
|
||||
|
||||
for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%SERVER_PORT%"') do (
|
||||
echo kill the process %%m who use the port
|
||||
taskkill /pid %%m -t -f
|
||||
echo Shutdown HertzBeat %SERVER_NAME% Success!
|
||||
goto q
|
||||
)
|
||||
echo Faild shutdown HertzBeat %SERVER_NAME%
|
||||
|
||||
:q
|
||||
pause
|
||||
56
script/assembly/server/bin/startup.bat
Normal file
56
script/assembly/server/bin/startup.bat
Normal file
@@ -0,0 +1,56 @@
|
||||
@title HertzBeat
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
rem 项目名称
|
||||
set SERVER_NAME=${project.artifactId}
|
||||
|
||||
rem jar名称
|
||||
set JAR_NAME=${project.build.finalName}.jar
|
||||
|
||||
rem 进入bin目录
|
||||
cd /d %~dp0
|
||||
rem 返回到上一级项目根目录路径
|
||||
cd ..
|
||||
rem 打印项目安装根目录绝对路径
|
||||
set DEPLOY_DIR=%~dp0..
|
||||
echo %DEPLOY_DIR%
|
||||
rem 外部配置文件绝对目录,如果是目录需要/结尾,也可以直接指定文件
|
||||
rem 如果指定的是目录,spring则会读取目录中的所有配置文件
|
||||
set CONF_DIR=%DEPLOY_DIR%\config
|
||||
echo %CONF_DIR%
|
||||
|
||||
rem 应用的端口号
|
||||
set SERVER_PORT=1157
|
||||
|
||||
for /f "tokens=1-5" %%i in ('netstat -ano^|findstr "0.0.0.0:%SERVER_PORT%"') do (
|
||||
echo The HertzBeat %SERVER_NAME% port %SERVER_PORT% already used!
|
||||
echo exit!
|
||||
goto q
|
||||
)
|
||||
|
||||
|
||||
rem 项目日志输出绝对路径
|
||||
set LOGS_DIR=%DEPLOY_DIR%\logs
|
||||
|
||||
rem JVM Configuration
|
||||
set JAVA_OPTS= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Duser.timezone=Asia/Shanghai
|
||||
|
||||
set JAVA_MEM_OPTS= -server -Xms256m -Xmx1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC
|
||||
|
||||
rem 加载外部log文件的配置
|
||||
set LOGGING_CONFIG=-Dlogging.config=%CONF_DIR%\logback-spring.xml
|
||||
rem 注意配置文件目录最后的后缀需为 / 而不是 windows \
|
||||
set CONFIG_FILES= -Dlogging.path=%LOGS_DIR% %LOGGING_CONFIG% -Dspring.config.location=%CONF_DIR%/
|
||||
echo Starting the %SERVER_NAME% ...
|
||||
|
||||
start javaw %JAVA_OPTS% %JAVA_MEM_OPTS% %CONFIG_FILES% -jar %DEPLOY_DIR%\%JAR_NAME%
|
||||
|
||||
echo "Service starting OK!"
|
||||
for /f "tokens=1-5" %%i in ('netstat -ano^|findstr ":%SERVER_PORT%"') do (
|
||||
echo Service PID: %%m , Port %SERVER_PORT%
|
||||
goto q
|
||||
)
|
||||
|
||||
:q
|
||||
pause
|
||||
@@ -34,7 +34,7 @@ CREATE TABLE param
|
||||
id bigint not null auto_increment comment '参数ID',
|
||||
monitor_id bigint not null comment '监控ID',
|
||||
field varchar(100) not null comment '参数标识符',
|
||||
value varchar(255) comment '参数值,最大字符长度255',
|
||||
value varchar(8126) comment '参数值,最大字符长度8126',
|
||||
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
|
||||
gmt_create timestamp default current_timestamp comment 'create time',
|
||||
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',
|
||||
|
||||
@@ -36,10 +36,10 @@ excludedResource:
|
||||
# eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
|
||||
account:
|
||||
- appId: admin
|
||||
credential: admin@123.
|
||||
credential: admin
|
||||
role: [role1,role2]
|
||||
- appId: tom
|
||||
credential: tom@123.
|
||||
credential: tom
|
||||
role: [role1,role2,role3]
|
||||
- appId: lili
|
||||
# 注意 Digest认证不支持加盐加密的密码账户
|
||||
|
||||
@@ -34,7 +34,7 @@ CREATE TABLE param
|
||||
id bigint not null auto_increment comment '参数ID',
|
||||
monitor_id bigint not null comment '监控ID',
|
||||
field varchar(100) not null comment '参数标识符',
|
||||
value varchar(255) comment '参数值,最大字符长度255',
|
||||
value varchar(8126) comment '参数值,最大字符长度8126',
|
||||
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
|
||||
gmt_create timestamp default current_timestamp comment 'create time',
|
||||
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',
|
||||
|
||||
@@ -23,7 +23,7 @@ excludedResource:
|
||||
- /**/*.ttf===get
|
||||
- /**/*.png===get
|
||||
- /**/*.gif===get
|
||||
- /**/*.png===*
|
||||
- /**/*.png===*
|
||||
# swagger ui 资源
|
||||
- /swagger-resources/**===get
|
||||
- /v2/api-docs===get
|
||||
|
||||
@@ -61,11 +61,11 @@ public class TdEngineDataStorage implements DisposableBean {
|
||||
log.error("init error, please config Warehouse TdEngine props in application.yml");
|
||||
throw new IllegalArgumentException("please config Warehouse TdEngine props");
|
||||
}
|
||||
initTdEngineDatasource(properties.getStore().getTdEngine());
|
||||
startStorageData();
|
||||
boolean success = initTdEngineDatasource(properties.getStore().getTdEngine());
|
||||
startStorageData(success);
|
||||
}
|
||||
|
||||
private void initTdEngineDatasource(WarehouseProperties.StoreProperties.TdEngineProperties tdEngineProperties) {
|
||||
private boolean initTdEngineDatasource(WarehouseProperties.StoreProperties.TdEngineProperties tdEngineProperties) {
|
||||
HikariConfig config = new HikariConfig();
|
||||
// jdbc properties
|
||||
config.setJdbcUrl(tdEngineProperties.getUrl());
|
||||
@@ -84,16 +84,28 @@ public class TdEngineDataStorage implements DisposableBean {
|
||||
config.setIdleTimeout(0);
|
||||
//validation query
|
||||
config.setConnectionTestQuery("select server_status()");
|
||||
this.hikariDataSource = new HikariDataSource(config);
|
||||
try {
|
||||
this.hikariDataSource = new HikariDataSource(config);
|
||||
} catch (Exception e) {
|
||||
log.error("\n\t------------------WARN WARN WARN------------------\n" +
|
||||
"\t---------------Init TdEngine Failed---------------\n" +
|
||||
"\t---------------Init TdEngine Failed---------------\n" +
|
||||
"\t--------------Please Config Tdengine--------------\n" +
|
||||
"\t----------Can Not Use Metric History Now----------\n" +
|
||||
"\t----------Can Not Use Metric History Now----------\n" +
|
||||
"\t----------Can Not Use Metric History Now----------\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startStorageData() {
|
||||
private void startStorageData(boolean consume) {
|
||||
Runnable runnable = () -> {
|
||||
Thread.currentThread().setName("warehouse-tdEngine-data-storage");
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
CollectRep.MetricsData metricsData = dataExporter.pollPersistentStorageMetricsData();
|
||||
if (metricsData != null) {
|
||||
if (consume && metricsData != null) {
|
||||
saveData(metricsData);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
@@ -232,6 +244,12 @@ public class TdEngineDataStorage implements DisposableBean {
|
||||
Connection connection = null;
|
||||
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
|
||||
try {
|
||||
if (hikariDataSource == null) {
|
||||
log.error("\n\t---------------TdEngine Init Failed---------------\n" +
|
||||
"\t--------------Please Config Tdengine--------------\n" +
|
||||
"\t----------Can Not Use Metric History Now----------\n");
|
||||
return instanceValuesMap;
|
||||
}
|
||||
connection = hikariDataSource.getConnection();
|
||||
Statement statement = connection.createStatement();
|
||||
ResultSet resultSet = statement.executeQuery(selectSql);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<global-footer [links]="links">
|
||||
Copyright
|
||||
<i nz-icon nzType="copyright" nzTheme="outline"></i>
|
||||
2021
|
||||
2022
|
||||
<a href="https://tancloud.cn" target="_blank">探云 tancloud.cn | </a>
|
||||
<a href="https://hertzbeat.com" target="_blank">赫兹跳动 hertzbeat.com</a>
|
||||
</global-footer>
|
||||
|
||||
@@ -9,4 +9,7 @@ export class ParamDefine {
|
||||
limit: number | undefined;
|
||||
//'[{"label":"GET请求","value":"GET"},{"label":"PUT请求","value":"PUT"}]'
|
||||
options!: any[];
|
||||
// 当type为key-value时有效,表示别名描述
|
||||
keyAlias!: string;
|
||||
valueAlias!: string;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
>{{ paramDefine.name }}
|
||||
</nz-form-label>
|
||||
<nz-form-control *ngIf="paramDefine.type === 'password'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<nz-input-group [nzSuffix]="suffixTemplate">
|
||||
<nz-input-group [nzSuffix]="suffixTemplate" style="width: 100%">
|
||||
<input
|
||||
[type]="passwordVisible ? 'text' : 'password'"
|
||||
nz-input
|
||||
@@ -125,6 +125,7 @@
|
||||
<nz-form-control *ngIf="paramDefine.type === 'boolean'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<nz-switch
|
||||
[(ngModel)]="params[i].value"
|
||||
(ngModelChange)="onParamBooleanChanged($event, paramDefine.field)"
|
||||
[required]="paramDefine.required"
|
||||
[name]="paramDefine.field"
|
||||
[id]="paramDefine.field"
|
||||
@@ -147,6 +148,18 @@
|
||||
</label>
|
||||
</nz-radio-group>
|
||||
</nz-form-control>
|
||||
|
||||
<nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
|
||||
>{{ paramDefine.name }}
|
||||
</nz-form-label>
|
||||
<nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<app-key-value-input
|
||||
[(value)]="params[i].value"
|
||||
[id]="paramDefine.field"
|
||||
keyAlias="Header Name"
|
||||
valueAlias="Header Value"
|
||||
></app-key-value-input>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
<nz-divider></nz-divider>
|
||||
|
||||
@@ -78,7 +78,13 @@ export class MonitorEditComponent implements OnInit {
|
||||
if (param === undefined) {
|
||||
param = new Param();
|
||||
param.field = define.field;
|
||||
param.type = define.type === 'number' ? 0 : 1;
|
||||
if (define.type === 'number') {
|
||||
param.type = 0;
|
||||
} else if (define.type === 'key-value') {
|
||||
param.type = 3;
|
||||
} else {
|
||||
param.type = 1;
|
||||
}
|
||||
if (define.type === 'boolean') {
|
||||
param.value = false;
|
||||
}
|
||||
@@ -102,6 +108,21 @@ export class MonitorEditComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
onParamBooleanChanged(booleanValue: boolean, field: string) {
|
||||
// 对SSL的端口联动处理, 不开启SSL默认80端口,开启SSL默认443
|
||||
if (field === 'ssl') {
|
||||
this.params.forEach(param => {
|
||||
if (param.field === 'port') {
|
||||
if (booleanValue) {
|
||||
param.value = '443';
|
||||
} else {
|
||||
param.value = '80';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit(formGroup: FormGroup) {
|
||||
if (formGroup.invalid) {
|
||||
Object.values(formGroup.controls).forEach(control => {
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
>{{ paramDefine.name }}
|
||||
</nz-form-label>
|
||||
<nz-form-control *ngIf="paramDefine.type === 'password'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<nz-input-group [nzSuffix]="suffixTemplate">
|
||||
<nz-input-group [nzSuffix]="suffixTemplate" style="width: 100%">
|
||||
<input
|
||||
[type]="passwordVisible ? 'text' : 'password'"
|
||||
nz-input
|
||||
@@ -134,6 +134,7 @@
|
||||
<nz-form-control *ngIf="paramDefine.type === 'boolean'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<nz-switch
|
||||
[(ngModel)]="params[i].value"
|
||||
(ngModelChange)="onParamBooleanChanged($event, paramDefine.field)"
|
||||
[required]="paramDefine.required"
|
||||
[name]="paramDefine.field"
|
||||
[id]="paramDefine.field"
|
||||
@@ -156,6 +157,18 @@
|
||||
</label>
|
||||
</nz-radio-group>
|
||||
</nz-form-control>
|
||||
|
||||
<nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
|
||||
>{{ paramDefine.name }}
|
||||
</nz-form-label>
|
||||
<nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
|
||||
<app-key-value-input
|
||||
[(value)]="params[i].value"
|
||||
[id]="paramDefine.field"
|
||||
[keyAlias]="paramDefine.keyAlias ? paramDefine.keyAlias : 'Name'"
|
||||
[valueAlias]="paramDefine.valueAlias ? paramDefine.valueAlias : 'Value'"
|
||||
></app-key-value-input>
|
||||
</nz-form-control>
|
||||
</nz-form-item>
|
||||
|
||||
<nz-divider></nz-divider>
|
||||
|
||||
@@ -58,7 +58,13 @@ export class MonitorNewComponent implements OnInit {
|
||||
this.paramDefines.forEach(define => {
|
||||
let param = new Param();
|
||||
param.field = define.field;
|
||||
param.type = define.type === 'number' ? 0 : 1;
|
||||
if (define.type === 'number') {
|
||||
param.type = 0;
|
||||
} else if (define.type === 'key-value') {
|
||||
param.type = 3;
|
||||
} else {
|
||||
param.type = 1;
|
||||
}
|
||||
if (define.type === 'boolean') {
|
||||
param.value = false;
|
||||
}
|
||||
@@ -83,6 +89,21 @@ export class MonitorNewComponent implements OnInit {
|
||||
this.monitor.name = `${this.monitor.app.toUpperCase()}_${hostValue}`;
|
||||
}
|
||||
|
||||
onParamBooleanChanged(booleanValue: boolean, field: string) {
|
||||
// 对SSL的端口联动处理, 不开启SSL默认80端口,开启SSL默认443
|
||||
if (field === 'ssl') {
|
||||
this.params.forEach(param => {
|
||||
if (param.field === 'port') {
|
||||
if (booleanValue) {
|
||||
param.value = '443';
|
||||
} else {
|
||||
param.value = '80';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit(formGroup: FormGroup) {
|
||||
if (formGroup.invalid) {
|
||||
Object.values(formGroup.controls).forEach(control => {
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
### 公共通用小组件
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<div *ngFor="let item of keyValues; let i = index" nz-row>
|
||||
<div nz-col nzSpan="10">
|
||||
<input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key" (ngModelChange)="onChange()" />
|
||||
</div>
|
||||
<div nz-col nzSpan="11">
|
||||
<input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value" (ngModelChange)="onChange()" />
|
||||
</div>
|
||||
<div nz-col nzSpan="3">
|
||||
<i nz-icon nzType="plus-circle" class="dynamic-button" *ngIf="i === 0" (click)="addNew($event)"></i>
|
||||
<i nz-icon nzType="minus-circle" class="dynamic-button" (click)="removeCurrent(i, $event)"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,12 @@
|
||||
.dynamic-button {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
top: 20%;
|
||||
font-size: 15px;
|
||||
transition: all 0.3s;
|
||||
margin-left: 12%;
|
||||
}
|
||||
|
||||
.dynamic-button:hover {
|
||||
font-size: 26px;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { KeyValueInputComponent } from './key-value-input.component';
|
||||
|
||||
describe('KeyValueInputComponent', () => {
|
||||
let component: KeyValueInputComponent;
|
||||
let fixture: ComponentFixture<KeyValueInputComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ KeyValueInputComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(KeyValueInputComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-key-value-input',
|
||||
templateUrl: './key-value-input.component.html',
|
||||
styleUrls: ['./key-value-input.component.less']
|
||||
})
|
||||
export class KeyValueInputComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
@Input() value!: any;
|
||||
@Output() readonly valueChange = new EventEmitter<string>();
|
||||
|
||||
@Input()
|
||||
keyAlias: string = 'Key';
|
||||
@Input()
|
||||
valueAlias: string = 'Value';
|
||||
|
||||
keyValues: any[] = [];
|
||||
|
||||
ngOnInit(): void {
|
||||
if (this.value == undefined) {
|
||||
this.value = {
|
||||
'': ''
|
||||
};
|
||||
} else {
|
||||
this.value = JSON.parse(this.value);
|
||||
}
|
||||
Object.keys(this.value).map(item => {
|
||||
this.keyValues.push({
|
||||
key: item,
|
||||
value: this.value[item]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addNew(e?: MouseEvent) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
this.keyValues.push({
|
||||
key: '',
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
removeCurrent(index: number, e?: MouseEvent) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (this.keyValues.length > 1) {
|
||||
this.keyValues.splice(index, 1);
|
||||
}
|
||||
}
|
||||
onChange() {
|
||||
this.value = {};
|
||||
this.keyValues.forEach(item => {
|
||||
if (item != null && item.key != null) {
|
||||
this.value[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
this.valueChange.emit(JSON.stringify(this.value));
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import { DelonACLModule } from '@delon/acl';
|
||||
import { DelonFormModule } from '@delon/form';
|
||||
import { AlainThemeModule } from '@delon/theme';
|
||||
|
||||
import { KeyValueInputComponent } from './components/key-value-input/key-value-input.component';
|
||||
import { TimezonePipe } from './pipe/timezone.pipe';
|
||||
import { SHARED_DELON_MODULES } from './shared-delon.module';
|
||||
import { SHARED_ZORRO_MODULES } from './shared-zorro.module';
|
||||
@@ -18,7 +19,7 @@ const THIRDMODULES: Array<Type<void>> = [];
|
||||
|
||||
// #region your components & directives
|
||||
|
||||
const COMPONENTS: Array<Type<void>> = [];
|
||||
const COMPONENTS: Array<Type<void>> = [KeyValueInputComponent];
|
||||
const DIRECTIVES: Array<Type<void>> = [TimezonePipe];
|
||||
|
||||
// #endregion
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"app": {
|
||||
"name": "TANCLOUD",
|
||||
"name": "HertzBeat",
|
||||
"description": "易用友好的高性能监控云"
|
||||
},
|
||||
"user": {
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 8.9 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 8.9 KiB |
@@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TanCloud</title>
|
||||
<title>HertzBeat</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
|
||||
Reference in New Issue
Block a user