Compare commits

..

47 Commits

Author SHA1 Message Date
huacheng
3d65fe3861 feat: Alarm and receiving Chinese and English support #huacheng 2022-04-10 18:22:05 +08:00
huacheng
f3bd9930f1 fix: 企业微信更正名称 #huacheng 2022-04-06 21:21:33 +08:00
huacheng
dc61dd066c fix: msgtype更正名称 #huacheng 2022-04-05 22:21:56 +08:00
huacheng
4ad7972956 fix: 代码名称优化 #huacheng 2022-04-05 22:11:24 +08:00
tomsun28
e99dd2e870 [script]feature:support win bat service (#65)
* [script]feature:support win bat service

* add sponsor
2022-04-04 20:55:09 +08:00
tomsun28
95c36fd9a3 [webapp,home]change tancloud brand to hertzbeat (#63) 2022-04-04 12:35:16 +08:00
tomsun28
2553c6f61e [warehouse]feature:make tdengine optional, not required (#62) 2022-04-04 11:45:41 +08:00
tomsun28
cc92f82472 [webapp]feature:http port follows ssl change (#61) 2022-04-04 11:02:12 +08:00
tomsun28
8dd2c1e47f [manager]feature:[api, website] support basic auth, digest auth (#60) 2022-04-04 09:15:03 +08:00
tomsun28
6a9d65ba5d [manager,collector]feature:api monitor support query params (#59) 2022-04-04 08:40:23 +08:00
tomsun28
3c48b4c71f [manager,webapp]feature:api monitor support http headers (#58) 2022-04-03 22:12:57 +08:00
tomsun28
636303021f [monitor]feature:param yml support key-value map (#57) 2022-04-03 21:35:56 +08:00
tomsun28
0cf66f32ff [manager,collector]feature 修改默认超时时间3000毫秒为6000毫秒 (#55) 2022-04-02 23:02:37 +08:00
tomsun28
fbf7ebd834 feature 检测网站SSL证书是否过期 (#50)
* [collector]feature 检测网站SSL证书是否过期

* [collector]fix cannot find symbol class BASE64Decoder
2022-04-02 21:22:16 +08:00
tomsun28
327f527082 [manager,collector]feature linux监控支持设置超时时间 (#49) 2022-04-02 17:57:25 +08:00
tomsun28
2f52ff5e63 [docs]新增服务器采集节点赞助 2022-04-01 18:00:24 +08:00
tomsun28
abe24914d3 [home]新增oracle监控帮助文档 2022-03-31 17:29:37 +08:00
tomsun28
491ca17106 [docs]补充sureness配置文档 避免误配导致权限异常 2022-03-30 20:44:00 +08:00
老姜bei
feef3e7054 [docs] 使用docker部署TDengine,开放tcp访问端口!16
* 使用docker部署TDengine,开放tcp访问端口
2022-03-30 04:53:32 +00:00
tomsun28
5c7bb4b14e [manager]oracle监控支持tablespace,连接数,qps,tps等指标 2022-03-26 21:29:08 +08:00
tomsun28
bb636c9bae [collector,manager]oracle使用ojdbc8驱动,更新采集指标 2022-03-24 21:54:39 +08:00
xgf
d871572438 [collector,manager]feature 支持oracle数据库监控类型-xgf !15
* [manager]
* [manager]恢复数据库连接
* [manager]恢复数据库连接
* Merge remote-tracking branch 'origin/feature#xgf' into feature#oracle
* [collector,manager]feature 支持oracle数据库监控类型
* Update README.md
* [manager]feature readme.rd 添加默认账号密码 提示
2022-03-23 06:46:15 +00:00
tomsun28
d169dac94d [collector]fix 采集任务超时监测线程处理异常 (#43) 2022-03-20 21:42:37 +08:00
tomsun28
cc22196d4a [docs]v1.0-beat6发布文档 2022-03-20 15:19:30 +08:00
tomsun28
820cb7a3e5 [manager,home]添加sqlserver关联文档,fix connection指标入库tdengine失败 (#41)
* [manager,home]添加sqlserver关联文档,fix connection指标入库tdengine失败

* [docs]文档更新
2022-03-20 13:27:13 +08:00
tomsun28
155bdaf462 [docs]文档官网更新 2022-03-20 08:45:37 +08:00
tomsun28
11981942d7 [web-app]避免歧义按钮,是否探测修改为测试连接 2022-03-20 07:52:11 +08:00
tomsun28
8473545d89 [script]版本1.0-beta.5修改为1.0-beta.6 2022-03-20 07:30:26 +08:00
tomsun28
eea9e601cf [collector]fix jdbc spi并发加载死锁 (#40) 2022-03-19 16:21:11 +08:00
xgf
711f0e070a [docs] readme 添加默认账号密码提示 !14
* Update README.md
* [manager]feature readme.rd 添加默认账号密码 提示
2022-03-19 04:46:46 +00:00
tomsun28
1f52ae4a88 [collector,manager]feature 支持microsoft sqlserver数据库监控类型 (#37) 2022-03-18 10:19:17 +08:00
tomsun28
a6a5f6abb4 [home]数据持久化挂载命令 2022-03-17 20:47:01 +08:00
tomsun28
56f2e826a9 [docs]指定mysql和tdengine版本,避免环境问题 2022-03-17 16:03:35 +08:00
tomsun28
ddb290bba3 [manager,collector]mariadb,postgresql支持timeout,fix jdbc解析异常 (#36)
* [manager,collector]fix jdbc解析异常,mariadb支持timeout

* [manager]postgresql支持timeout设置
2022-03-17 15:42:36 +08:00
tomsun28
f710795f0f [script, webapp]时间本地时区格式化 (#35) 2022-03-17 15:09:08 +08:00
会编程的王学长
88b03448e3 Merge pull request #34 from dromara/feature_add_mysql
feat: 标签扩展:新增mysql查询超时设置 #18
2022-03-17 14:57:24 +08:00
chenghua
63d03c7ac6 feat: 标签扩展:新增mysql查询超时默认秒数设置 #18 2022-03-17 14:46:03 +08:00
chenghua
223f36c6cb feat: 标签扩展:新增mysql查询超时设置 #18 2022-03-17 14:43:49 +08:00
会编程的王学长
bf31faa831 Merge pull request #32 from dromara/feature_add_mysql
feat: 代码优化 #I4U9BT
2022-03-17 11:06:51 +08:00
tomsun28
792d461844 [script]fix端口占用误判 2022-03-16 21:02:57 +08:00
tomsun28
63fe51b597 [home]ssh自定义文档更新 2022-03-16 14:56:19 +08:00
chenghua
eb65ee4206 feat: 代码优化 #I4U9BT 2022-03-16 13:53:13 +08:00
tomsun28
b5bc5d2975 [script,docs]docker-compose部署脚本迁到script目录,文档更新 2022-03-15 21:52:36 +08:00
tomsun28
4db3e04dd6 [manager,webapp]feature 监控列表支持过滤搜索 (#29) 2022-03-15 16:21:25 +08:00
tomsun28
540f4bcbf4 [manager,webapp]fix 页面全局监控搜索结果异常 (#28) 2022-03-15 15:00:22 +08:00
jx10086
9eb3b9842d [script]添加docker-compose部署方案 (#27)
* 添加docker-comps部署

* docker部署增加数据持久化

Co-authored-by: ytniu <root@ytniu.com>
2022-03-15 11:27:06 +08:00
tomsun28
790bcc6f16 [collector]fix 由于链接复用不佳造成创建过多链接监控异常 (#26) 2022-03-14 20:36:47 +08:00
137 changed files with 2682 additions and 431 deletions

View File

@@ -8,21 +8,22 @@
## HertzBeat 赫兹跳动
> 易用友好的高性能监控告警系统。
> 易用友好的监控告警系统。
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/web-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/ping-connect.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/port-available.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/database-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/os-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/custom-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/threshold.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/alert.svg)
**官网: [hertzbeat.com](https://hertzBeat.com) | [tancloud.cn](https://tancloud.cn)**
**官网: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
## 🎡 <font color="green">介绍</font>
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是由[Dromara](https://dromara.org)孵化,[TanCloud](https://tancloud.cn)开源的一个支持网站APIPING端口数据库等监控类型拥有易用友好的可视化操作界面的开源监控告警项目。
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是由[Dromara](https://dromara.org)孵化,[TanCloud](https://tancloud.cn)开源的一个支持网站APIPING端口数据库,操作系统等监控类型,拥有易用友好的可视化操作界面的开源监控告警项目。
> 我们也提供了对应的 **[SAAS版本监控云](https://console.tancloud.cn)**,中小团队和个人无需再为了监控自己的网站资源,而去部署一套繁琐的监控系统,**[登录即可免费开始](https://console.tancloud.cn)**。
> HertzBeat 支持[自定义监控](https://hertzbeat.com/docs/advanced/extend-point) ,只用通过配置YML文件我们就可以自定义需要的监控类型和指标来满足常见的个性化需求。
> HertzBeat 模块化,`manager, collector, scheduler, warehouse, alerter` 各个模块解耦合,方便理解与定制开发。
@@ -59,7 +60,7 @@
## 🐕 快速开始
- 如果您不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻 **[登录注册](https://console.tancloud.cn)** 免费使用。
- 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的[部署文档](https://hertzbeat.com/docs/start/quickstart)进行操作。
- 如果您是想将HertzBeat部署到内网环境搭建监控系统请参考下面的 [部署文档](https://hertzbeat.com/docs/start/quickstart) 进行操作。
### 🐵 依赖服务部署
@@ -67,7 +68,7 @@
##### 安装MYSQL
1. docker安装MYSQl
`docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql`
`docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7`
2. 创建名称为hertzbeat的数据库
3. 执行位于项目仓库/script/sql/目录下的数据库脚本 [schema.sql](https://gitee.com/dromara/hertzbeat/raw/master/script/sql/schema.sql)
@@ -75,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`
`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)
@@ -83,26 +84,32 @@
### 🍞 HertzBeat安装
> HertzBeat支持通过源码安装启动Docker容器运行和安装包方式安装部署。
##### Docker方式快速安装
##### 方式一:Docker方式快速安装
`docker run -d -p 1157:1157 -v /opt/application.yml:/opt/hertzbeat/config/application.yml --name hertzbeat tancloud/hertzbeat:[版本tag]`
详细步骤参考 [通过Docker方式安装HertzBeat](https://hertzbeat.com/docs/start/docker-deploy)
##### 通过安装包安装
##### 方式二:通过安装包安装
1. 下载您系统环境对应的安装包 [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
2. 配置HertzBeat的配置文件 hertzbeat/config/application.yml
3. 部署启动 `$ ./startup.sh `
详细步骤参考 [通过安装包安装HertzBeat](https://hertzbeat.com/docs/start/package-deploy)
##### 本地代码启动
##### 方式三:本地代码启动
1. 此为前后端分离项目本地代码调试需要分别启动后端工程manager和前端工程web-app
2. 后端:需要`maven3+``java8+`环境修改YML配置信息并启动manager服务
3. 前端:需要`nodejs npm angular-cli`环境待本地后端启动后在web-app目录下启动 `ng serve --open`
4. 浏览器访问 localhost:4200 即可开始
4. 浏览器访问 localhost:4200 即可开始,默认账号密码 admin/admin
详细步骤参考 [参与贡献之本地代码启动](CONTRIBUTING.md)
##### 方式四Docker-compose统一安装hertzbeat及其依赖服务
通过 [docker-compose部署脚本](script/docker-compose) 一次性把mysql数据库,tdengine数据库和hertzbeat安装部署。
详细步骤参考 [docker-compose安装](script/docker-compose/README.md)
**HAVE FUN**
## 💬 社区交流
@@ -131,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)

View File

@@ -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);

View File

@@ -12,20 +12,23 @@ 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列表
*/
@@ -34,8 +37,10 @@ public interface AlertDao extends JpaRepository<Alert, Long>, JpaSpecificationEx
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();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;
}
}
}

View File

@@ -103,6 +103,18 @@
<artifactId>sshd-core</artifactId>
<version>2.8.0</version>
</dependency>
<!-- sql server -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<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>

View File

@@ -121,15 +121,17 @@ public class CommonCache {
timeoutMap.put(key, new Long[]{currentTime, DEFAULT_CACHE_TIMEOUT});
} else if (cacheTime[0] + cacheTime[1] < currentTime) {
// 过期了 discard 关闭这个cache的资源
log.warn("[cache] clean the timeout cache, key {}", key);
timeoutMap.remove(key);
cacheMap.remove(key);
if (value instanceof CacheCloseable) {
log.warn("[cache] close the timeout cache, key {}", key);
((CacheCloseable)value).close();
}
}
});
} catch (Exception e) {
log.error("clean timeout cache error: {}.", e.getMessage(), e);
log.error("[cache] clean timeout cache error: {}.", e.getMessage(), e);
}
}
@@ -177,13 +179,14 @@ public class CommonCache {
return Optional.empty();
}
if (cacheTime[0] + cacheTime[1] < System.currentTimeMillis()) {
log.warn("[cache] is timeout, key {}.", key);
log.warn("[cache] is timeout, remove it, key {}.", key);
timeoutMap.remove(key);
cacheMap.remove(key);
return Optional.empty();
}
Object value = cacheMap.get(key);
if (value == null) {
log.error("[cache] value is null, remove it, key {}.", key);
cacheMap.remove(key);
timeoutMap.remove(key);
} else if (refreshCache) {

View File

@@ -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; }
};

View File

@@ -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();
}

View File

@@ -52,9 +52,19 @@ public class JdbcCommonCollect extends AbstractCollect {
}
JdbcProtocol jdbcProtocol = metrics.getJdbc();
String databaseUrl = constructDatabaseUrl(jdbcProtocol);
// 查询超时时间默认6000毫秒
int timeout = 6000;
try {
// 获取查询语句超时时间
if (jdbcProtocol.getTimeout() != null) {
timeout = Integer.parseInt(jdbcProtocol.getTimeout());
}
} catch (Exception e) {
log.warn(e.getMessage());
}
try {
Statement statement = getConnection(jdbcProtocol.getUsername(),
jdbcProtocol.getPassword(), databaseUrl);
jdbcProtocol.getPassword(), databaseUrl, timeout);
switch (jdbcProtocol.getQueryType()) {
case QUERY_TYPE_ONE_ROW:
queryOneRow(statement, jdbcProtocol.getSql(), metrics.getAliasFields(), builder, startTime);
@@ -95,7 +105,7 @@ public class JdbcCommonCollect extends AbstractCollect {
}
private Statement getConnection(String username, String password, String url) throws Exception {
private Statement getConnection(String username, String password, String url,Integer timeout) throws Exception {
CacheIdentifier identifier = CacheIdentifier.builder()
.ip(url)
.username(username).password(password).build();
@@ -106,7 +116,9 @@ public class JdbcCommonCollect extends AbstractCollect {
try {
statement = jdbcConnect.getConnection().createStatement();
// 设置查询超时时间10秒
statement.setQueryTimeout(10);
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
// 设置查询最大行数1000行
statement.setMaxRows(1000);
} catch (Exception e) {
@@ -130,7 +142,9 @@ public class JdbcCommonCollect extends AbstractCollect {
Connection connection = DriverManager.getConnection(url, username, password);
statement = connection.createStatement();
// 设置查询超时时间10秒
statement.setQueryTimeout(10);
int timeoutSecond = timeout / 1000;
timeoutSecond = timeoutSecond <= 0 ? 1 : timeoutSecond;
statement.setQueryTimeout(timeoutSecond);
// 设置查询最大行数1000行
statement.setMaxRows(1000);
JdbcConnect jdbcConnect = new JdbcConnect(connection);
@@ -190,7 +204,7 @@ public class JdbcCommonCollect extends AbstractCollect {
HashMap<String, String> values = new HashMap<>(columns.size());
while (resultSet.next()) {
if (resultSet.getString(1) != null) {
values.put(resultSet.getString(1).toLowerCase(), resultSet.getString(2));
values.put(resultSet.getString(1).toLowerCase().trim(), resultSet.getString(2));
}
}
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
@@ -267,6 +281,14 @@ public class JdbcCommonCollect extends AbstractCollect {
url = "jdbc:postgresql://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
break;
case "sqlserver":
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());

View File

@@ -0,0 +1,32 @@
package com.usthe.collector.collect.database;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 预加载jdbc驱动包 避免spi并发加载造成死锁
* @author tom
* @date 2022/3/19 15:39
*/
@Service
@Slf4j
@Order(value = 0)
public class JdbcSpiLoader implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("start load jdbc drivers");
try {
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);
}
log.info("end load jdbc drivers");
}
}

View File

@@ -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) {

View File

@@ -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()) {

View File

@@ -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) {

View File

@@ -32,7 +32,7 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
/**
* 指标组采集任务超时时间值
*/
private static final long DURATION_TIME = 120_000L;
private static final long DURATION_TIME = 240_000L;
/**
* 指标组采集任务优先级队列
*/
@@ -94,7 +94,7 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
Thread.currentThread().setName("metrics-task-monitor");
while (!Thread.currentThread().isInterrupted()) {
try {
// 检测每个指标组采集单元是否超时2分钟,超时则丢弃并返回异常
// 检测每个指标组采集单元是否超时4分钟,超时则丢弃并返回异常
long deadline = System.currentTimeMillis() - DURATION_TIME;
for (Map.Entry<String, MetricsTime> entry : metricsTimeoutMonitorMap.entrySet()) {
MetricsTime metricsTime = entry.getValue();
@@ -165,7 +165,7 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
metricsSet.forEach(metricItem -> {
MetricsCollect metricsCollect = new MetricsCollect(metricItem, timeout, this);
jobRequestQueue.addJob(metricsCollect);
metricsTimeoutMonitorMap.put(job.getId() + metrics.getName(),
metricsTimeoutMonitorMap.put(job.getId() + "-" + metrics.getName(),
new MetricsTime(System.currentTimeMillis(), metrics, timeout));
});
} else {
@@ -185,7 +185,7 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
metricsSet.forEach(metricItem -> {
MetricsCollect metricsCollect = new MetricsCollect(metricItem, timeout, this);
jobRequestQueue.addJob(metricsCollect);
metricsTimeoutMonitorMap.put(job.getId() + metrics.getName(),
metricsTimeoutMonitorMap.put(job.getId() + "-" + metrics.getName(),
new MetricsTime(System.currentTimeMillis(), metrics, timeout));
});
} else {

View File

@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -172,14 +173,23 @@ public class MetricsCollect implements Runnable, Comparable<MetricsCollect> {
if (metrics.getCalculates() == null) {
metrics.setCalculates(Collections.emptyList());
}
// eg: database_pages=Database pages 非常规映射
Map<String, String> fieldAliasMap = new HashMap<>(8);
Map<String, Expression> fieldExpressionMap = metrics.getCalculates()
.stream()
.map(cal -> {
int splitIndex = cal.indexOf("=");
String field = cal.substring(0, splitIndex);
String expressionStr = cal.substring(splitIndex + 1);
Expression expression = AviatorEvaluator.compile(expressionStr, true);
Expression expression = null;
try {
expression = AviatorEvaluator.compile(expressionStr, true);
} catch (Exception e) {
fieldAliasMap.put(field, expressionStr);
return null;
}
return new Object[]{field, expression}; })
.filter(Objects::nonNull)
.collect(Collectors.toMap(arr -> (String)arr[0], arr -> (Expression) arr[1]));
List<Metrics.Field> fields = metrics.getFields();
@@ -226,8 +236,13 @@ public class MetricsCollect implements Runnable, Comparable<MetricsCollect> {
}
} else {
// 不存在 则映射别名值
String aliasField = fieldAliasMap.get(realField);
if (aliasField != null) {
value = aliasFieldValueMap.get(aliasField);
} else {
value = aliasFieldValueMap.get(realField);
}
}
if (value == null) {
value = CommonConstants.NULL_VALUE;
}

View File

@@ -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();

View File

@@ -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;
}
}
}

View File

@@ -6,4 +6,5 @@ com.usthe.collector.dispatch.MetricsCollectorQueue,\
com.usthe.collector.dispatch.WorkerPool,\
com.usthe.collector.dispatch.entrance.internal.CollectJobService,\
com.usthe.collector.dispatch.export.MetricsDataExporter,\
com.usthe.collector.util.SpringContextHolder
com.usthe.collector.util.SpringContextHolder,\
com.usthe.collector.collect.database.JdbcSpiLoader

View File

@@ -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;

View File

@@ -28,7 +28,7 @@ public class Configmap {
private Object value;
/**
* 参数类型 0:数字 1:字符串 2:加密串
* 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
* number,string,secret
* 数字,非加密字符串,加密字符串
*/

View File

@@ -166,7 +166,7 @@ public class Job {
return null;
}
if (!metricsSet.remove(metrics)) {
log.error("Job {} appId {} app {} metrics {} remove empty error in priorMetrics.",
log.warn("Job {} appId {} app {} metrics {} remove empty error in priorMetrics.",
id, monitorId, app, metrics.getName());
}
if (metricsSet.isEmpty()) {

View File

@@ -35,6 +35,10 @@ public class JdbcProtocol {
* 数据库
*/
private String database;
/**
* 超时时间
*/
private String timeout;
/**
* 数据库类型 mysql oracle ...
*/

View File

@@ -29,7 +29,7 @@ public class SshProtocol {
/**
* 超时时间
*/
private String timeout = "3000";
private String timeout;
/**
* 用户名

View File

@@ -15,7 +15,6 @@ public class JsonOptionListAttributeConverter implements AttributeConverter<List
@Override
public String convertToDatabaseColumn(List<ParamDefine.Option> attribute) {
return GsonUtil.toJson(attribute);
}
@Override

View File

@@ -35,6 +35,9 @@ import static io.swagger.annotations.ApiModelProperty.AccessMode.READ_WRITE;
@ApiModel(description = "监控实体")
public class Monitor {
/**
* 主键ID
*/
@Id
@ApiModelProperty(value = "监控ID", example = "87584674384", accessMode = READ_ONLY, position = 0)
private Long id;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
/**

View File

@@ -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;

View File

@@ -0,0 +1,70 @@
---
title: HertzBeat赫兹节拍 v1.0.beta.6 发布Linux监控来啦
author: tom
author_title: tom
author_url: https://github.com/tomsun28
author_image_url: https://avatars.githubusercontent.com/u/24788200?s=400&v=4
tags: [opensource]
---
HertzBeat赫兹跳动是由Dromara孵化TanCloud开源的一个支持网站APIPING端口数据库操作系统全站等监控类型支持阈值告警告警通知(邮箱webhook钉钉企业微信飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
官网:hertzbeat.com | tancloud.cn
此升级版本包含了很多同学需要的Linux操作系统监控支持支持其CPU内存磁盘网络等指标重要的是同步支持了SSH自定义我们可以很方便的写脚本监控我们想要的Linux指标也新增了对主流的数据库SqlServer监控支持等更多功能欢迎使用。
版本特性:
1. feature 新增支持Linux操作系统监控类型(支持CPU内存磁盘网卡等监控指标) (#20)
2. feature 新增支持microsoft sqlserver数据库监控类型 (#37)
3. feature 添加docker-compose部署方案 (#27) 由 @jx10086 贡献 thanks
4. feature 监控列表支持状态过滤和字段搜索功能 (#29)
5. feature 新增mysql,postgresql等数据库查询超时时间设置 (#18) 由 @学习代码的小白 贡献
6. [纳管]修改为[监控]表述,[探测]修改为[测试]表述
7. feature add github build and translate action (#22)
8. feature 新增贡献指南,本地代码启动文档
9. docs 指定mysql和tdengine版本避免环境问题
BUG修复
1. fix 由于链接复用不佳造成创建过多链接监控异常 (#26)
2. fix 页面全局监控搜索结果异常 (#28) issue by @Suremotoo
3. 代码优化 #I4U9BT@学习代码的小白 贡献
4. fix 服务启动脚本偶现端口占用误判问题
5. 时间本地时区格式化 (#35)
6. fix 此版本引入问题jdbc解析异常 (#36)
7. fix jdbc并发注册加载时由于spi机制加载死锁问题 (#40)
欢迎在线试用 https://console.tancloud.cn.
-----------------------
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是由[Dromara](https://dromara.org)孵化,[TanCloud](https://tancloud.cn)开源的一个支持网站APIPING端口数据库操作系统等监控类型拥有易用友好的可视化操作界面的开源监控告警项目。
> 我们也提供了对应的 **[SAAS版本监控云](https://console.tancloud.cn)**,中小团队和个人无需再为了监控自己的网站资源,而去部署一套繁琐的监控系统,**[登录即可免费开始](https://console.tancloud.cn)**。
> HertzBeat 支持[自定义监控](https://hertzbeat.com/docs/advanced/extend-point) ,只用通过配置YML文件我们就可以自定义需要的监控类型和指标来满足常见的个性化需求。
> HertzBeat 模块化,`manager, collector, scheduler, warehouse, alerter` 各个模块解耦合,方便理解与定制开发。
> HertzBeat 支持更自由化的告警配置(计算表达式),支持告警通知,告警模版,邮件钉钉微信飞书等及时通知送达
> 欢迎登录 HertzBeat 的 [云环境TanCloud](https://console.tancloud.cn) 试用发现更多。
> 我们正在快速迭代中,欢迎参与加入一起共建项目开源生态。
> `HertzBeat`的多类型支持,易扩展,低耦合,希望能帮助开发者和中小团队快速搭建自有监控系统。
老铁们可以通过演示视频来直观了解功能: https://www.bilibili.com/video/BV1Vi4y1f7i8
##### 欢迎联系交流哦
**微信交流群**
加微信号 tan-cloud 或 扫描下面账号二维码拉进微信群。
<img alt="tan-cloud" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/help/tan-cloud-wechat.jpg" width="200"/>
**QQ交流群**
加QQ群号 718618151 或 扫描下面的群二维码进群, 验证信息: tancloud
<img alt="tan-cloud" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/help/qq-qr.jpg" width="200"/>
**仓库地址**
[Github](https://github.com/dromara/hertzbeat) https://github.com/dromara/hertzbeat
[Gitee](https://gitee.com/dromara/hertzbeat) https://gitee.com/dromara/hertzbeat
看到这里不妨给个Star哦灰常感谢弯腰!!

View File

@@ -29,14 +29,14 @@ HTTP协议支持我们自定义HTTP请求路径请求header请求参数
> 监控配置定义文件用于定义 *监控类型的名称(国际化), 请求参数映射, 指标信息, 采集协议配置信息*等。
样例自定义一个名称为example的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example.yml 位于 /define/app/example.yml
样例自定义一个名称为example_http的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example_http.yml 位于 /define/app/example_http.yml
```yaml
# 此监控类型所属类别service-应用服务监控 db-数据库监控 custom-自定义监控 os-操作系统监控
category: custom
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: example
app: example_http
name:
zh-CN: 模拟应用类型
en-US: EXAMPLE APP
@@ -157,12 +157,12 @@ metrics:
> 监控参数定义文件用于定义 *需要的输入参数字段结构定义(前端页面根据结构渲染输入参数框)*。
样例自定义一个名称为example的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example.yml 位于 //define/param/example.yml
样例自定义一个名称为example_http的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example_http.yml 位于 //define/param/example_http.yml
```yaml
# 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: example
app: example_http
# 强制固定必须参数 - host(ipv4,ipv6,域名)
param:
# field-字段名称标识符

View File

@@ -3,7 +3,7 @@ id: extend-jdbc
title: JDBC协议自定义监控
sidebar_label: JDBC协议自定义监控
---
> 从[自定义监控](extend-point)了解熟悉了怎么自定义类型指标协议等这里我们来详细介绍下用JDBC(目前支持mysql,mariadb,postgresql)自定义指标监控。
> 从[自定义监控](extend-point)了解熟悉了怎么自定义类型指标协议等这里我们来详细介绍下用JDBC(目前支持mysql,mariadb,postgresql,sqlserver)自定义指标监控。
> JDBC协议自定义监控可以让我们很方便的通过写SQL查询语句就能监控到我们想监控的指标
### JDBC协议采集流程
@@ -50,8 +50,8 @@ SQL响应数据
### 自定义步骤
配置自定义监控类型需新增配置两个YML文件
1. 用监控类型命名的监控配置定义文件 - 例如example.yml 需位于安装目录 /hertzbeat/define/app/ 下
2. 用监控类型命名的监控参数定义文件 - 例如example.yml 需位于安装目录 /hertzbeat/define/param/ 下
1. 用监控类型命名的监控配置定义文件 - 例如example_sql.yml 需位于安装目录 /hertzbeat/define/app/ 下
2. 用监控类型命名的监控参数定义文件 - 例如example_sql.yml 需位于安装目录 /hertzbeat/define/param/ 下
3. 重启hertzbeat系统我们就适配好了一个新的自定义监控类型。
-------
@@ -61,14 +61,14 @@ SQL响应数据
> 监控配置定义文件用于定义 *监控类型的名称(国际化), 请求参数映射, 指标信息, 采集协议配置信息*等。
样例自定义一个名称为example的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example.yml 位于 /define/app/example.yml
样例自定义一个名称为example_sql的自定义监控类型,其使用JDBC协议采集指标数据。
文件名称: example_sql.yml 位于 /define/app/example_sql.yml
```yaml
# 此监控类型所属类别service-应用服务监控 db-数据库监控 custom-自定义监控 os-操作系统监控
category: db
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: example
app: example_sql
name:
zh-CN: 模拟MYSQL应用类型
en-US: MYSQL EXAMPLE APP
@@ -215,11 +215,11 @@ metrics:
> 监控参数定义文件用于定义 *需要的输入参数字段结构定义(前端页面根据结构渲染输入参数框)*。
样例自定义一个名称为example的自定义监控类型其使用HTTP协议采集指标数据。
文件名称: example.yml 位于 /define/param/example.yml
样例自定义一个名称为example_sql的自定义监控类型,其使用JDBC协议采集指标数据。
文件名称: example_sql.yml 位于 /define/param/example_sql.yml
```yaml
app: example
app: example_sql
param:
- field: host
name: 主机Host

View File

@@ -4,7 +4,7 @@ title: 自定义监控
sidebar_label: 自定义监控
---
> HertzBeat拥有自定义监控能力您只需配置两个YML文件就能适配一款自定义的监控类型。
> 目前自定义监控支持[HTTP协议](extend-http)[JDBC](extend-jdbc)(mysql,mariadb,postgresql..)协议,后续会支持更多通用协议(ssh telnet wmi snmp)。
> 目前自定义监控支持[HTTP协议](extend-http)[JDBC协议](extend-jdbc)(mysql,mariadb,postgresql..)[SSH协议](extend-ssh),后续会支持更多通用协议(ssh telnet wmi snmp)。
### 自定义步骤

View File

@@ -0,0 +1,220 @@
---
id: extend-ssh
title: SSH协议自定义监控
sidebar_label: SSH协议自定义监控
---
> 从[自定义监控](extend-point)了解熟悉了怎么自定义类型指标协议等这里我们来详细介绍下用SSH协议自定义指标监控。
> SSH协议自定义监控可以让我们很方便的通过写sh命令脚本就能监控采集到我们想监控的Linux指标
### SSH协议采集流程
【**系统直连Linux**】->【**运行SHELL命令脚本语句**】->【**响应数据解析:oneRow, multiRow**】->【**指标数据提取**】
由流程可见我们自定义一个SSH协议的监控类型需要配置SSH请求参数配置获取哪些指标配置查询脚本语句。
### 数据解析方式
SHELL脚本查询回来的数据字段和我们需要的指标映射就能获取对应的指标数据目前映射解析方式有两种oneRow, multiRow能满足绝大部分指标需求。
#### **oneRow**
> 查询出一列数据, 通过查询返回结果集的字段值(一行一个值)与字段映射
例如:
需要查询Linux的指标 hostname-主机名称uptime-启动时间
主机名称原始查询命令:`hostname`
启动时间原始查询命令:`uptime | awk -F "," '{print $1}'`
则在hertzbeat对应的这两个指标的查询脚本为(用`;`将其连接到一起)
`hostname; uptime | awk -F "," '{print $1}'`
终端响应的数据为:
```
tombook
14:00:15 up 72 days
```
则最后采集到的指标数据一一映射为:
hostname值为 `tombook`
uptime值为 `14:00:15 up 72 days`
这里指标字段就能和响应数据一一映射为一行采集数据。
#### **multiRow**
> 查询多行数据, 通过查询返回结果集的列名称,和查询的指标字段映射
例如:
查询的Linux内存相关指标字段total-内存总量 used-已使用内存 free-空闲内存 buff-cache-缓存大小 available-可用内存
内存指标原始查询命令为:`free -m`, 控制台响应:
```shell
total used free shared buff/cache available
Mem: 7962 4065 333 1 3562 3593
Swap: 8191 33 8158
```
在heartbeat中multiRow格式解析需要响应数据列名称和指标值一一映射则对应的查询SHELL脚本为
`free -m | grep Mem | awk 'BEGIN{print "total used free buff_cache available"} {print $2,$3,$4,$6,$7}'`
控制台响应为:
```shell
total used free buff_cache available
7962 4066 331 3564 3592
```
这里指标字段就能和响应数据一一映射为采集数据。
### 自定义步骤
配置自定义监控类型需新增配置两个YML文件
1. 用监控类型命名的监控配置定义文件 - 例如example_linux.yml 需位于安装目录 /hertzbeat/define/app/ 下
2. 用监控类型命名的监控参数定义文件 - 例如example_linux.yml 需位于安装目录 /hertzbeat/define/param/ 下
3. 重启hertzbeat系统我们就适配好了一个新的自定义监控类型。
-------
下面详细介绍下这俩文件的配置用法,请注意看使用注释。
### 监控配置定义文件
> 监控配置定义文件用于定义 *监控类型的名称(国际化), 请求参数映射, 指标信息, 采集协议配置信息*等。
样例自定义一个名称为example_linux的自定义监控类型其使用SSH协议采集指标数据。
文件名称: example_linux.yml 位于 /define/app/example_linux.yml
```yaml
# 此监控类型所属类别service-应用服务监控 db-数据库监控 custom-自定义监控 os-操作系统监控
category: os
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: example_linux
name:
zh-CN: 模拟LINUX应用类型
en-US: LINUX EXAMPLE APP
# 参数映射map. 这些为输入参数变量,即可以用^_^host^_^的形式写到后面的配置中,系统自动变量值替换
# 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
# 指标组列表
metrics:
# 第一个监控指标组 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: basic
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
priority: 0
# 指标组中的具体监控指标
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: hostname
type: 1
instance: true
- field: version
type: 1
- field: uptime
type: 1
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
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
- name: cpu
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: info
type: 1
- field: cores
type: 0
unit: 核数
- field: interrupt
type: 0
unit: 个数
- field: load
type: 1
- field: context_switch
type: 0
unit: 个数
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
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
- name: memory
priority: 2
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: total
type: 0
unit: Mb
- field: used
type: 0
unit: Mb
- field: free
type: 0
unit: Mb
- field: buff_cache
type: 0
unit: Mb
- field: available
type: 0
unit: Mb
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
script: free -m | grep Mem | awk 'BEGIN{print "total used free buff_cache available"} {print $2,$3,$4,$6,$7}'
parseType: multiRow
```
### 监控参数定义文件
> 监控参数定义文件用于定义 *需要的输入参数字段结构定义(前端页面根据结构渲染输入参数框)*。
样例自定义一个名称为example_linux的自定义监控类型其使用SSH协议采集指标数据。
文件名称: example_linux.yml 位于 /define/param/example_linux.yml
```yaml
app: example_linux
param:
- field: host
name: 主机Host
type: host
required: true
- field: port
name: 端口
type: number
range: '[0,65535]'
required: true
defaultValue: 22
placeholder: '请输入端口'
- field: username
name: 用户名
type: text
limit: 20
required: true
- field: password
name: 密码
type: password
required: true
```

View File

@@ -1,65 +0,0 @@
---
id: contributing
title: 参与贡献
sidebar_label: 参与贡献
---
Contributing to Sureness
=======================================
Very welcome to Contribute this project, go further and better with sureness.
Firstly, thanks for your interest in contributing! I hope that this will be a pleasant first experience for you, and that you will return to continue contributing.
Components of Repository:
- [sureness's kernel code--sureness-core](https://github.com/usthe/sureness/tree/master/core)
- [sureness integration springboot sample(configuration file scheme)--sample-bootstrap](https://github.com/usthe/sureness/tree/master/sample-bootstrap)
- [sureness integration springboot sample(database scheme)-sample-tom](https://github.com/usthe/sureness/tree/master/sample-tom)
- [sample projects using sureness in each framework(javalin,ktor,quarkus)--samples](https://github.com/usthe/sureness/tree/master/samples)
## How to contribute?
Most of the contributions that we receive are code contributions, but you can
also contribute to the documentation or simply report solid bugs
for us to fix.
For new contributors, please take a look at issues or pull requests with a tag called below.
[Good first issue](https://github.com/usthe/sureness/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
[Help wanted](https://github.com/usthe/sureness/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
[Good first pull request](https://github.com/usthe/sureness/issues?q=label%3A%22good+first+pull+request%22+)
## Join discussion
[Github Discussion](https://github.com/usthe/sureness/discussions)
[Gitter Channel](https://gitter.im/usthe/sureness)
----
----
参与贡献
=======================================
非常欢迎参与项目贡献,我们致力于维护一个互相帮助的快乐社区。
仓库的组成部分:
- [sureness的核心代码--sureness-core](https://github.com/usthe/sureness/tree/master/core)
- [使用sureness集成springboot搭建权限项目(配置文件方案)--sample-bootstrap](https://github.com/usthe/sureness/tree/master/sample-bootstrap)
- [使用sureness集成springboot搭建权限项目(数据库方案)--sample-tom](https://github.com/usthe/sureness/tree/master/sample-tom)
- [各个框架使用sureness的样例项目(javalin,ktor,quarkus)--samples](https://github.com/usthe/sureness/tree/master/samples)
## 如何贡献?
我们不仅仅接收代码的贡献提交您也可以通过提交文档的更新或者BUG的报告来参与社区贡献。
如果是新的贡献者请首先了解参考如下样例的提交Issues,提交Pull Requests如果工作。
[Good first issue](https://github.com/usthe/sureness/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
[Help wanted](https://github.com/usthe/sureness/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
[Good first pull request](https://github.com/usthe/sureness/issues?q=label%3A%22good+first+pull+request%22+)
## 加入交流
[Github Discussion](https://github.com/usthe/sureness/discussions)
[Gitter Channel](https://gitter.im/usthe/sureness)
QQ交流群390083213
微信公众号sureness

View File

@@ -18,7 +18,7 @@ sidebar_label: 帮助入门
### 数据库监控
[MYSQL数据库监控](mysql) &emsp;&emsp;&emsp;&emsp; [MariaDB数据库监控](mariadb) &emsp;&emsp;&emsp;&emsp; [PostgreSQL数据库监控](postgresql)
[MYSQL数据库监控](mysql) &emsp;&emsp;&emsp;&emsp; [MariaDB数据库监控](mariadb) &emsp;&emsp;&emsp;&emsp; [PostgreSQL数据库监控](postgresql) &emsp;&emsp;&emsp;&emsp; [SqlServer数据库监控](sqlserver) &emsp;&emsp;&emsp;&emsp; [Oracle数据库监控](oracle)
### 操作系统监控

View File

@@ -12,6 +12,11 @@ sidebar_label: 常见问题
2. ** 网站API等监控反馈statusCode:403或401但对端服务本身无需认证浏览器直接访问是OK **
> 请排查是否是被防火墙拦截如宝塔等默认设置了对请求header中`User-Agent=Apache-HttpClient`的拦截,若被拦截请删除此拦截规则。(v1.0.beat5版本已将user-agent模拟成浏览器此问题不存在)
3. 安装包部署的hertzbeat下ping连通性监控异常
安装包安装部署的hertzbeat,对ping连通性监控不可用但本地直接ping是可用的。
> 安装包部署需要配置java虚拟机root权限启动hertzbeat从而使用ICMP若未启用root权限则是判断telnet对端7号端口是否开通
> docker安装默认启用无此问题
### Docker部署常见问题
1. **MYSQL,TDENGINE和HertzBeat都Docker部署在同一主机上HertzBeat使用localhost或127.0.0.1连接数据库失败**

View File

@@ -13,6 +13,7 @@ sidebar_label: MariaDB数据库
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(eg: https://, http://)。 |
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 数据库对外提供的端口默认为3306。 |
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间单位ms毫秒默认3000毫秒。 |
| 数据库名称 | 数据库实例名称,可选。 |
| 用户名 | 数据库连接用户名,可选 |
| 密码 | 数据库连接密码,可选 |

View File

@@ -13,6 +13,7 @@ sidebar_label: MYSQL数据库
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(eg: https://, http://)。 |
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 数据库对外提供的端口默认为3306。 |
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间单位ms毫秒默认3000毫秒。 |
| 数据库名称 | 数据库实例名称,可选。 |
| 用户名 | 数据库连接用户名,可选 |
| 密码 | 数据库连接密码,可选 |

62
home/docs/help/oracle.md Normal file
View File

@@ -0,0 +1,62 @@
---
id: oracle
title: 监控ORACLE数据库监控
sidebar_label: ORACLE数据库
---
> 对ORACLE数据库的通用性能指标进行采集监控。
### 配置参数
| 参数名称 | 参数帮助描述 |
| ----------- | ----------- |
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(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 兆字节数量 |

View File

@@ -13,6 +13,7 @@ sidebar_label: PostgreSQL数据库
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(eg: https://, http://)。 |
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 数据库对外提供的端口默认为5432。 |
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间单位ms毫秒默认3000毫秒。 |
| 数据库名称 | 数据库实例名称,可选。 |
| 用户名 | 数据库连接用户名,可选 |
| 密码 | 数据库连接密码,可选 |

View File

@@ -0,0 +1,57 @@
---
id: sqlserver
title: 监控SqlServer数据库监控
sidebar_label: SqlServer数据库
---
> 对SqlServer数据库的通用性能指标进行采集监控。支持SqlServer 2017+。
### 配置参数
| 参数名称 | 参数帮助描述 |
| ----------- | ----------- |
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(eg: https://, http://)。 |
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 数据库对外提供的端口默认为1433。 |
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间单位ms毫秒默认3000毫秒。 |
| 数据库名称 | 数据库实例名称,可选。 |
| 用户名 | 数据库连接用户名,可选 |
| 密码 | 数据库连接密码,可选 |
| URL | 数据库连接URL可选若配置则URL里面的数据库名称用户名密码等参数会覆盖上面配置的参数 |
| 采集间隔 | 监控周期性采集数据间隔时间单位秒可设置的最小间隔为10秒 |
| 是否探测 | 新增监控前是否先探测检查监控可用性,探测成功才会继续新增修改操作 |
| 描述备注 | 更多标识和描述此监控的备注信息,用户可以在这里备注信息 |
### 采集指标
#### 指标集合basic
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| machine_name | 无 | 运行服务器实例的 Windows 计算机名称 |
| server_name | 无 | 与Windows实例关联的服务器和实例信息SQL Server |
| version | 无 | 实例的版本SQL Server格式为"major.minor.build.revision" |
| edition | 无 | 已安装的 实例的产品SQL Server版本 |
| start_time | 无 | 数据库启动时间 |
#### 指标集合performance_counters
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| database_pages | 无 | Database pages, 已获得的页面数(缓冲池) |
| target_pages | 无 | Target pages, 缓冲池必须的理想页面数 |
| page_life_expectancy | s,秒 | Page life expectancy, 数据页在缓冲池中驻留的时间,这个时间一般会大于 300 |
| buffer_cache_hit_ratio | % | Buffer cache hit ratio, 数据库缓冲池高速缓冲命中率,被请求的数据在缓冲池中被找到的概率,一般会大于 80% 才算正常,否则可能是缓冲池容量太小 |
| checkpoint_pages_sec | 无 | Checkpoint pages/sec, 检查点每秒写入磁盘的脏页个数,如果数据过高,证明缺少内存容量 |
| page_reads_sec | 无 | Page reads/sec, 缓存池中每秒读的页数 |
| page_writes_sec | 无 | Page writes/sec, 缓存池中每秒写的页数 |
#### 指标集合connection
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| user_connection | 无 | 已连接的会话数 |

View File

@@ -5,12 +5,13 @@ sidebar_label: 介绍
slug: /
---
> 易用友好的高性能监控告警系统。
> 易用友好的监控告警系统。
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/web-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/ping-connect.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/port-available.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/database-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/os-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/custom-monitor.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/threshold.svg)
![tan-cloud](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/badge/alert.svg)
@@ -26,7 +27,7 @@ slug: /
## 🎡 <font color="green">介绍</font>
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是由[Dromara](https://dromara.org)孵化,[TanCloud](https://tancloud.cn)开源的一个支持网站APIPING端口数据库等监控类型拥有易用友好的可视化操作界面的开源监控告警项目。
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是由[Dromara](https://dromara.org)孵化,[TanCloud](https://tancloud.cn)开源的一个支持网站APIPING端口数据库,操作系统等监控类型,拥有易用友好的可视化操作界面的开源监控告警项目。
> 当然,我们也提供了对应的[SAAS云监控版本](https://console.tancloud.cn),中小团队和个人无需再为了监控自己的网站资源,而去部署一套繁琐的监控系统,[登录即可免费开始](https://console.tancloud.cn)监控之旅。
> HertzBeat 支持自定义监控只用通过配置YML文件我们就可以自定义需要的监控类型和指标来满足常见的个性化需求。
> HertzBeat 模块化,`manager, collector, scheduler, warehouse, alerter` 各个模块解耦合,方便理解与定制开发。

View File

@@ -0,0 +1,68 @@
---
id: contributing
title: 参与贡献
sidebar_label: 参与贡献
---
参与贡献
=======================================
非常欢迎参与项目贡献,我们致力于维护一个互相帮助的快乐社区。
### 模块
- **[manager](https://github.com/dromara/hertzbeat/tree/master/manager)** 提供监控管理,系统管理基础服务
> 提供对监控的管理,监控应用配置的管理,系统用户租户后台管理等。
- **[collector](https://github.com/dromara/hertzbeat/tree/master/collector)** 提供监控数据采集服务
> 使用通用协议远程采集获取对端指标数据。
- **[scheduler](https://github.com/dromara/hertzbeat/tree/master/scheduler)** 提供监控任务调度服务
> 采集任务管理,一次性任务和周期性任务的调度分发。
- **[warehouse](https://github.com/dromara/hertzbeat/tree/master/warehouse)** 提供监控数据仓储服务
> 采集指标结果数据管理,数据落盘,查询,计算统计。
- **[alerter](https://github.com/dromara/hertzbeat/tree/master/alerter)** 提供告警服务
> 告警计算触发,监控状态联动,告警配置,告警通知。
- **[web-app](https://github.com/dromara/hertzbeat/tree/master/web-app)** 提供可视化控制台页面
> 监控告警系统可视化控制台前端
![hertzBeat](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/hertzbeat-stru.svg)
## 如何贡献?
我们不仅仅接收代码的贡献提交您也可以通过提交文档的更新或者BUG的报告来参与社区贡献。
如果是新的贡献者请首先了解参考仓库提交Issues,提交Pull Requests如何工作。
https://github.com/dromara/hertzbeat/issues
https://github.com/dromara/hertzbeat/pulls
https://gitee.com/dromara/hertzbeat/issues
https://gitee.com/dromara/hertzbeat/pulls
## 本地代码工程启动
此为前后端分离项目,本地代码启动需将后端 [manager](https://github.com/dromara/hertzbeat/tree/master/manager) 和前端 [web-app](https://github.com/dromara/hertzbeat/tree/master/web-app) 分别启动生效。
### 后端启动
1. 部署启动依赖服务`MYSQL``TDengine`数据库
2. 需要`maven3+``java8+`环境
3. 修改配置文件的依赖服务地址等信息-`manager/src/main/resources/application.yml`
4. 启动`manager`服务 `manager/src/main/java/com/usthe/manager/Manager.java`
### 前端启动
1. 需要nodejs npm环境
下载地址https://nodejs.org/en/download
2. 安装yarn `npm install -g yarn`
3. 在前端工程目录web-app下执行 `yarn install`
4. 全局安装angular-cli `npm install -g @angular/cli@12 --registry=https://registry.npm.taobao.org`
5. 待本地后端启动后在web-app目录下启动本地前端 `ng serve --open`
6. 浏览器访问 localhost:4200 即可开始
## 加入交流
[Github Discussion](https://github.com/dromara/hertzbeat/discussions)
加微信号 tan-cloud 拉您进微信交流群
加QQ群号 718618151 进QQ交流群, 验证信息: tancloud
微信公众号tancloudtech
[Dromara社区网站](https://dromara.org/)
[HertzBeat用户网站](https://support.qq.com/products/379369)

View File

@@ -12,7 +12,8 @@ sidebar_label: 赞助
![wechat-alipay](https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/pay.png)
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com)赞助服务器采集节点
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
感谢[天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) 赞助服务器采集节点

View File

@@ -44,9 +44,55 @@ sidebar_label: Docker方式部署
若需要新增删除修改账户或密码,可以通过配置 `sureness.yml` 实现,若无此需求可忽略此步骤
在主机目录下创建sureness.ymleg:/opt/sureness.yml
配置文件内容参考 项目仓库[/script/sureness.yml](https://gitee.com/dromara/hertzbeat/blob/master/script/sureness.yml)
修改sureness.yml的如下部分参数[注意⚠sureness配置的其它默认参数需保留]
```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
@@ -82,7 +128,7 @@ sidebar_label: Docker方式部署
- tancloud/hertzbeat:[版本tag] : 使用拉取的HertzBeat官方发布的应用镜像来启动容器,TAG可查看[官方镜像仓库](https://hub.docker.com/r/tancloud/hertzbeat/tags)
7. 开始探索HertzBeat
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警,默认账户密码 admin/admin。
**HAVE FUN**

View File

@@ -17,14 +17,18 @@ MYSQL是一款值得信赖的关系型数据库HertzBeat使用其存储监控
```
2. Docker安装MYSQl
```
$ docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest
$ docker run -d --name mysql -p 3306:3306 -v /opt/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
526aa188da767ae94b244226a2b2eec2b5f17dd8eff594533d9ec0cd0f3a1ccd
```
`-v /opt/data:/var/lib/mysql` 为mysql数据目录本地持久化挂载需将`/opt/data`替换为实际本地存在的目录
使用```$ docker ps```查看数据库是否启动成功
### SQL脚本执行
1. 进入MYSQL或使用客户端连接MYSQL服务
`mysql -uroot -p123456`
2. 创建名称为hertzbeat的数据库
`create database hertzbeat;`
3. 执行位于项目仓库/script/sql/目录下的数据库建表初始化脚本 [schema.sql](https://gitee.com/dromara/hertzbeat/raw/master/script/sql/schema.sql)
`mysql -uroot -p123456 < schema.sql`
4. 查看hertzbeat数据库是否成功建表

View File

@@ -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
# 用户账户信息
@@ -76,7 +76,7 @@ sidebar_label: 安装包方式部署
$ ./startup.sh
```
6. 开始探索HertzBeat
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警,默认账户密码 admin/admin。
**HAVE FUN**

View File

@@ -15,7 +15,7 @@ sidebar_label: 快速开始
##### 安装MYSQL
1. docker安装MYSQl
`docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql`
`docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7`
2. 创建名称为hertzbeat的数据库
3. 执行位于项目仓库/script/sql/目录下的数据库脚本 [schema.sql](https://gitee.com/dromara/hertzbeat/raw/master/script/sql/schema.sql)
@@ -23,7 +23,7 @@ sidebar_label: 快速开始
##### 安装TDengine
1. docker安装TDengine
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine`
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
2. 创建名称为hertzbeat的数据库
详细步骤参考 [依赖服务TDengine安装初始化](tdengine-init.md)
@@ -31,16 +31,30 @@ sidebar_label: 快速开始
### 🍞 HertzBeat安装
> HertzBeat支持通过源码安装启动Docker容器运行和安装包方式安装部署。
#### Docker方式快速安装
#### 方式一:Docker方式快速安装
`docker run -d -p 1157:1157 -v /opt/application.yml:/opt/hertzbeat/config/application.yml --name hertzbeat tancloud/hertzbeat:[版本tag]`
详细步骤参考 [通过Docker方式安装HertzBeat](docker-deploy.md)
#### 通过安装包安装
#### 方式二:通过安装包安装
1. 下载您系统环境对应的安装包 [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
2. 配置HertzBeat的配置文件 hertzbeat/config/application.yml
3. 部署启动 `$ ./startup.sh `
详细步骤参考 [通过安装包安装HertzBeat](package-deploy.md)
#### 方式三:本地代码启动
1. 此为前后端分离项目本地代码调试需要分别启动后端工程manager和前端工程web-app
2. 后端:需要`maven3+``java8+`环境修改YML配置信息并启动manager服务
3. 前端:需要`nodejs npm angular-cli`环境待本地后端启动后在web-app目录下启动 `ng serve --open`
4. 浏览器访问 localhost:4200 即可开始,默认账户密码 admin/admin
详细步骤参考 [参与贡献之本地代码启动](../others/contributing)
#### 方式四Docker-Compose统一安装hertzbeat及其依赖服务
通过 [docker-compose部署脚本](https://gitee.com/dromara/hertzbeat/tree/master/script/docker-compose) 一次性把mysql数据库,tdengine数据库和hertzbeat安装部署。
详细步骤参考 [docker-compose安装](https://gitee.com/dromara/hertzbeat/tree/master/script/docker-compose/README.md)
**HAVE FUN**

View File

@@ -18,9 +18,10 @@ TDengine是一款国产的开源物联网时序型数据库我们使用其替
```
2. Docker安装TDengine
```
$ docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine
$ docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp -v /opt/taosdata:/var/lib/taos --name tdengine tdengine/tdengine:2.4.0.12
526aa188da767ae94b244226a2b2eec2b5f17dd8eff594533d9ec0cd0f3a1ccd
```
`-v /opt/taosdata:/var/lib/taos` 为tdengine数据目录本地持久化挂载需将`/opt/taosdata`替换为实际本地存在的目录
使用```$ docker ps```查看数据库是否启动成功
### 创建数据库实例

View File

@@ -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',

View File

@@ -32,6 +32,13 @@
"items": [
"advanced/extend-jdbc"
]
},
{
"type": "category",
"label": "SSH协议",
"items": [
"advanced/extend-ssh"
]
}
]
},
@@ -57,7 +64,9 @@
"items": [
"help/mysql",
"help/mariadb",
"help/postgresql"
"help/postgresql",
"help/sqlserver",
"help/oracle"
]
},
{
@@ -97,7 +106,8 @@
"others/design",
"others/sponsor",
"others/private",
"others/resource"
"others/resource",
"others/contributing"
]
}
]

View File

@@ -36,7 +36,7 @@ export const features = [{
custom: <a href={'/docs/advanced/extend-point'}><strong>自定义监控</strong></a>,
br: <br/>
}}>
{'HertzBeat目前支持对网站APIPING连通性端口可用性SiteMap全站MYSQL数据库等的监控不久我们将兼容 prometheus 协议,提供更多的监控类型和性能指标。{br}' +
{'HertzBeat目前支持对网站APIPING连通性端口可用性SiteMap全站数据库,操作系统等的监控,快速迭代提供更多的监控类型和性能指标。{br}' +
'我们提供了更自由化的阈值告警配置支持邮箱短信webhook钉钉企业微信飞书机器人等告警通知。{br}' +
'不同团队的监控需求千变万化,我们提供{custom}仅需配置YML就能快速接入监控系统。'
}

View File

@@ -28,12 +28,13 @@ function Home() {
<h1 className="hero__title">
<img style={{width: '500px', marginTop: '100px'}} src={cdnTransfer('img/hertzbeat-brand.svg')} alt={'#'}/>
</h1>
<p className="hero__subtitle"><Translate>易用友好的高性能监控告警系统</Translate></p>
<p className="hero__subtitle"><Translate>易用友好的监控告警系统</Translate></p>
<div className={styles.social}>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/web-monitor.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/ping-connect.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/port-available.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/database-monitor.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/os-monitor.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/custom-monitor.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/threshold.svg')} alt={''}/></a>
<a href="https://console.tancloud.cn"><img src={cdnTransfer('img/badge/alert.svg')} alt={''}/></a>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="55" height="20" role="img" aria-label="操作系统"><title>操作系统</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="55" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#4c1"/><rect x="0" width="55" height="20" fill="#4c1"/><rect width="55" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="275" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="450">操作系统</text><text x="275" y="140" transform="scale(.1)" fill="#fff" textLength="450">操作系统</text></g></svg>

After

Width:  |  Height:  |  Size: 929 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

View 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

View File

@@ -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);
}
}
// 告警落库
// 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
//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("[邮箱告警] errorException information={}",e.getMessage());
} catch (Exception e) {
log.error("[Email Alert] ExceptionException information={}", e.getMessage());
}
}
private List<NoticeReceiver> matchReceiverByNoticeRules(Alert alert) {
// todo 使用缓存
// todo use cache 使用缓存
return noticeConfigService.getReceiverFilterRule(alert);
}

View File

@@ -38,6 +38,8 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@RequestMapping(path = "/monitors", produces = {APPLICATION_JSON_VALUE})
public class MonitorsController {
private static final byte ALL_MONITOR_STATUS = 9;
@Autowired
private MonitorService monitorService;
@@ -48,6 +50,7 @@ public class MonitorsController {
@ApiParam(value = "监控类型", example = "linux") @RequestParam(required = false) final String app,
@ApiParam(value = "监控名称,模糊查询", example = "linux-127.0.0.1") @RequestParam(required = false) final String name,
@ApiParam(value = "监控Host模糊查询", example = "127.0.0.1") @RequestParam(required = false) final String host,
@ApiParam(value = "监控状态 0:未监控,1:可用,2:不可用,3:不可达,4:挂起,9:全部状态", example = "1") @RequestParam(required = false) final Byte status,
@ApiParam(value = "排序字段默认id", example = "name") @RequestParam(defaultValue = "id") final String sort,
@ApiParam(value = "排序方式asc:升序desc:降序", example = "desc") @RequestParam(defaultValue = "desc") final String order,
@ApiParam(value = "列表当前分页", example = "0") @RequestParam(defaultValue = "0") int pageIndex,
@@ -66,6 +69,10 @@ public class MonitorsController {
Predicate predicateApp = criteriaBuilder.equal(root.get("app"), app);
andList.add(predicateApp);
}
if (status != null && status >= 0 && status < ALL_MONITOR_STATUS) {
Predicate predicateStatus = criteriaBuilder.equal(root.get("status"), status);
andList.add(predicateStatus);
}
Predicate[] andPredicates = new Predicate[andList.size()];
Predicate andPredicate = criteriaBuilder.and(andList.toArray(andPredicates));
@@ -79,9 +86,17 @@ public class MonitorsController {
orList.add(predicateName);
}
Predicate[] orPredicates = new Predicate[orList.size()];
Predicate orPredicate = criteriaBuilder.and(orList.toArray(orPredicates));
Predicate orPredicate = criteriaBuilder.or(orList.toArray(orPredicates));
if (andPredicate.getExpressions().isEmpty() && orPredicate.getExpressions().isEmpty()) {
return query.where().getRestriction();
} else if (andPredicate.getExpressions().isEmpty()) {
return query.where(orPredicate).getRestriction();
} else if (orPredicate.getExpressions().isEmpty()) {
return query.where(andPredicate).getRestriction();
} else {
return query.where(andPredicate,orPredicate).getRestriction();
}
};
// 分页是必须的
Sort sortExp = Sort.by(new Sort.Order(Sort.Direction.fromString(order), sort));

View File

@@ -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();

View File

@@ -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));

View File

@@ -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")

View File

@@ -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";
/**
* 消息类型

View File

@@ -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);
}

View File

@@ -15,6 +15,7 @@ import java.util.Set;
/**
* 监控管理服务
*
* @author tomsun28
* @date 2021/11/14 11:28
*/
@@ -23,6 +24,7 @@ public interface MonitorService {
/**
* 监控可用性探测
*
* @param monitor 监控实体信息
* @param params 参数信息
* @throws MonitorDetectException 探测失败抛出
@@ -31,6 +33,7 @@ public interface MonitorService {
/**
* 新增监控
*
* @param monitor 监控实体
* @param params 参数信息
* @throws RuntimeException 新增过程异常抛出
@@ -39,6 +42,7 @@ public interface MonitorService {
/**
* 校验请求数据参数正确性
*
* @param monitorDto monitorDto
* @param isModify 是否是修改监控
* @throws IllegalArgumentException 校验参数错误抛出
@@ -47,6 +51,7 @@ public interface MonitorService {
/**
* 修改更新监控
*
* @param monitor 监控实体
* @param params 参数信息
* @throws RuntimeException 修改过程中异常抛出
@@ -55,6 +60,7 @@ public interface MonitorService {
/**
* 删除监控
*
* @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,6 +85,7 @@ public interface MonitorService {
/**
* 动态条件查询
*
* @param specification 查询条件
* @param pageRequest 分页参数
* @return 查询结果
@@ -85,38 +94,46 @@ public interface MonitorService {
/**
* 根据监控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 监控列表
*/

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -27,8 +27,8 @@ spring:
on-profile: prod
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: admin
password: admin
username: root
password: 123456
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false
platform: mysql
hikari:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -16,6 +16,8 @@ configmap:
type: 2
- key: database
type: 1
- key: timeout
type: 0
- key: url
type: 1
# 指标组列表
@@ -61,6 +63,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
@@ -102,6 +105,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
@@ -134,6 +138,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql

View File

@@ -16,6 +16,8 @@ configmap:
type: 2
- key: database
type: 1
- key: timeout
type: 0
- key: url
type: 1
# 指标组列表
@@ -61,6 +63,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
@@ -102,6 +105,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
@@ -134,6 +138,7 @@ metrics:
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql

View 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^_^

View File

@@ -18,6 +18,8 @@ configmap:
type: 1
- key: url
type: 1
- key: timeout
type: 0
# 指标组列表
metrics:
- name: basic
@@ -45,6 +47,7 @@ metrics:
host: ^_^host^_^
# 端口
port: ^_^port^_^
timeout: ^_^timeout^_^
platform: postgresql
username: ^_^username^_^
password: ^_^password^_^
@@ -87,6 +90,7 @@ metrics:
host: ^_^host^_^
# 端口
port: ^_^port^_^
timeout: ^_^timeout^_^
platform: postgresql
username: ^_^username^_^
password: ^_^password^_^
@@ -110,6 +114,7 @@ metrics:
host: ^_^host^_^
# 端口
port: ^_^port^_^
timeout: ^_^timeout^_^
platform: postgresql
username: ^_^username^_^
password: ^_^password^_^

View File

@@ -0,0 +1,136 @@
category: db
app: sqlserver
name:
zh-CN: SqlServer数据库
en-US: SqlServer 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: machine_name
type: 1
instance: true
- field: server_name
type: 1
- field: version
type: 1
- field: edition
type: 1
- field: start_time
type: 1
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: sqlserver
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: oneRow
# sql
sql: SELECT SERVERPROPERTY('MachineName') AS machine_name, SERVERPROPERTY('ServerName') AS server_name, SERVERPROPERTY('ProductVersion') AS version, SERVERPROPERTY('Edition') AS edition, sqlserver_start_time AS start_time FROM sys.dm_os_sys_info;
url: ^_^url^_^
- name: performance_counters
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: database_pages
type: 0
- field: target_pages
type: 0
- field: page_life_expectancy
type: 0
- field: buffer_cache_hit_ratio
type: 0
- field: checkpoint_pages_sec
type: 0
- field: page_reads_sec
type: 0
- field: page_writes_sec
type: 0
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- Database pages
- Target pages
- Page life expectancy
- Buffer cache hit ratio
- Checkpoint pages/sec
- Page reads/sec
- Page writes/sec
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- database_pages=Database pages
- target_pages=Target pages
- page_life_expectancy=Page life expectancy
- buffer_cache_hit_ratio=Buffer cache hit ratio
- checkpoint_pages_sec=Checkpoint pages/sec
- page_reads_sec=Page reads/sec
- page_writes_sec=Page writes/sec
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: sqlserver
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
sql: select counter_name, cntr_value from sys.dm_os_performance_counters where object_name = 'SQLServer:Buffer Manager';
url: ^_^url^_^
- name: connection
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: user_connection
type: 0
unit: 连接数
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: sqlserver
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: oneRow
# sql
sql: SELECT cntr_value as user_connection FROM sys.dm_os_performance_counters WHERE object_name = 'SQLServer:General Statistics' AND counter_name = 'User Connections';
url: ^_^url^_^

View File

@@ -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

View File

@@ -49,3 +49,9 @@ param:
value: PUT
- label: DELETE请求
value: DELETE
- field: headers
name: 请求Headers
type: key-value
required: false
keyAlias: Header Name
valueAlias: Header Value

View File

@@ -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

View File

@@ -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

View File

@@ -9,8 +9,14 @@ param:
type: number
range: '[0,65535]'
required: true
defaultValue: 80
defaultValue: 3306
placeholder: '请输入端口'
- field: timeout
name: 查询超时时间
type: number
required: false
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
type: text

View File

@@ -9,8 +9,14 @@ param:
type: number
range: '[0,65535]'
required: true
defaultValue: 80
defaultValue: 3306
placeholder: '请输入端口'
- field: timeout
name: 查询超时时间
type: number
required: false
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
type: text

View 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

View File

@@ -17,4 +17,4 @@ param:
range: '[0,100000]'
required: true
placeholder: '请输入超时时间,单位毫秒'
defaultValue: 3000
defaultValue: 6000

View File

@@ -24,4 +24,4 @@ param:
range: '[0,100000]'
required: true
placeholder: '请输入超时时间,单位毫秒'
defaultValue: 3000
defaultValue: 6000

View File

@@ -11,6 +11,12 @@ param:
required: true
defaultValue: 5432
placeholder: '请输入端口'
- field: timeout
name: 查询超时时间
type: number
required: false
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
type: text

View File

@@ -0,0 +1,36 @@
app: sqlserver
param:
- field: host
name: 主机Host
type: host
required: true
- field: port
name: 端口
type: number
range: '[0,65535]'
required: true
defaultValue: 1433
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

View File

@@ -24,4 +24,4 @@ param:
range: '[0,100000]'
required: true
placeholder: '请输入超时时间,单位毫秒'
defaultValue: 3000
defaultValue: 6000

View File

@@ -29,3 +29,23 @@ param:
# 当type为boolean时,前端用switch展示开关
type: boolean
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

View File

@@ -27,8 +27,8 @@ spring:
on-profile: prod
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: admin
password: admin
username: root
password: 123456
url: jdbc:mysql://localhost:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false
platform: mysql
hikari:

View File

@@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd
http://maven.apache.org/ASSEMBLY/2.0.0 ">
<!--必填,会追加到打包文件名称的末尾-->
<id>1.0-beta.5</id>
<id>1.0-beta.6</id>
<!--打包类型,可以设置多种类型,打包的时候不同的类型都会打包打出来-->
<formats>
<format>tar</format>

View 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

View File

@@ -7,7 +7,7 @@ APPLICATION="${project.artifactId}"
APPLICATION_JAR="${project.build.finalName}.jar"
# 通过项目名称查找到PI然后kill -9 pid
PID=$(ps -ef | grep "${APPLICATION_JAR}" | grep -v grep | awk '{ print $2 }')
PID=$(ps -ef | grep java | grep "${APPLICATION_JAR}" | grep -v grep | awk '{ print $2 }')
if [[ -z "$PID" ]]
then
echo ${APPLICATION} is already stopped

View 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

View File

@@ -22,7 +22,7 @@ CONF_DIR=$DEPLOY_DIR/config
# 应用的端口号
SERVER_PORT=1157
PIDS=`ps -f | grep java | grep "$CONF_DIR" |awk '{print $2}'`
PIDS=`ps -ef | grep java | grep "$CONF_DIR" | awk '{print $2}'`
if [ "$1" = "status" ]; then
if [ -n "$PIDS" ]; then
echo "The $SERVER_NAME is running...!"
@@ -41,11 +41,21 @@ if [ -n "$PIDS" ]; then
fi
if [ -n "$SERVER_PORT" ]; then
SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PORT | wc -l`
# linux 下查询端口是否占用
SERVER_PORT_COUNT=`netstat -tln | grep :$SERVER_PORT | wc -l`
if [ $SERVER_PORT_COUNT -gt 0 ]; then
echo "ERROR: The $SERVER_NAME port $SERVER_PORT already used!"
echo "ERROR: netstat the $SERVER_NAME port $SERVER_PORT already used!"
exit 1
fi
# mac 下查询端口是否占用
LSOF_AVA=`command -v lsof | wc -l`
if [ $LSOF_AVA -gt 0 ]; then
SERVER_PORT_COUNT=`lsof -i:$SERVER_PORT | wc -l`
if [ $SERVER_PORT_COUNT -gt 0 ]; then
echo "ERROR: lsof the $SERVER_NAME port $SERVER_PORT already used!"
exit 1
fi
fi
fi
# 项目日志输出绝对路径
@@ -56,11 +66,10 @@ if [ ! -d $LOGS_DIR ]; then
fi
# JVM Configuration
JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Duser.timezone=Asia/Shanghai"
JAVA_MEM_OPTS=" -server -Xms256m -Xmx1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
# 加载外部log文件的配置
LOG_IMPL_FILE=logback-spring.xml
LOGGING_CONFIG=""

View File

@@ -0,0 +1,52 @@
## docker-compose部署方案
- 如果不想部署而是直接使用我们提供SAAS监控云-[TanCloud探云](https://console.tancloud.cn),即刻 **[登录注册](https://console.tancloud.cn)** 免费使用。
- 如果想自己本地快速部署的话,可以参考下面进行操作。
##### 安装Docker & Docker-compose
1. 下载安装 docker 环境 & docker-compose 环境
请参考 [Docker官网文档](https://docs.docker.com/get-docker/), [Compose安装](https://docs.docker.com/compose/install/)
```
$ docker -v
Docker version 20.10.12, build e91ed57
```
##### docker compose部署heartbeat及其依赖服务
1. 下载hertzbeat-docker-compose安装部署脚本文件
脚本文件位于代码仓库下`script/docker-compose` 链接 [script/docker-compose](https://gitee.com/dromara/hertzbeat/tree/master/script/docker-compose)
2. 进入部署脚本 docker-compose 目录, 执行
`docker-compose up -d`
3. 进入tdengine创建hertzbeat数据库
`$ docker exec -it tdengine /bin/bash
root@tdengine-server:~/TDengine-server-2.4.0.4#`
创建名称为hertzbeat的数据库 进入容器后,执行 taos shell 客户端程序。
`root@tdengine-server:~/TDengine-server-2.4.0.4# taos
Welcome to the TDengine shell from Linux, Client Version:2.4.0.4
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
taos>`
执行创建数据库命令
`taos> show databases;`
`taos> CREATE DATABASE hertzbeat KEEP 90 DAYS 10 BLOCKS 6 UPDATE 1;`
##### 重启应用
`docker-compose restart hertzbeat`
##### 开始探索HertzBeat
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警。
---
怎么样是不是很简单,只要几分钟就可以部署完成,赶紧试试吧!

View File

@@ -0,0 +1,70 @@
server:
port: 1157
spring:
application:
name: ${HOSTNAME:@hertzbeat@}${PID}
profiles:
active: prod
mvc:
static-path-pattern: /console/**
resources:
static-locations:
- classpath:/dist/
- classpath:../dist/
jackson:
default-property-inclusion: NON_EMPTY
sureness:
auths:
- digest
- basic
- jwt
---
spring:
config:
activate:
on-profile: prod
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://mysql:3306/hertzbeat?useUnicode=true&characterEncoding=utf-8&useSSL=false
platform: mysql
hikari:
max-lifetime: 120000
jpa:
database: mysql
mail:
# 请注意邮件服务器地址qq邮箱为 smtp.qq.com qq企业邮箱为 smtp.exmail.qq.com
host: smtp.qq.com
username: example@qq.com
# 请注意此非邮箱账户密码 此需填写邮箱授权码
password: xxqzvuqbnqvbbdac
port: 465
default-encoding: UTF-8
properties:
mail:
smtp:
socketFactoryClass: javax.net.ssl.SSLSocketFactory
ssl:
enable: true
thymeleaf:
prefix: classpath:/templates/
check-template-location: true
cache: true
suffix: .html
#encoding: UTF-8
#content-type: text/html
mode: LEGACYHTML5
warehouse:
store:
td-engine:
enabled: true
driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
url: jdbc:TAOS-RS://tdengine:6041/hertzbeat
username: root
password: taosdata

Some files were not shown because too many files have changed in this diff Show More