Compare commits

..

1 Commits

Author SHA1 Message Date
tomsun28
83071d60cf [collector]fix jdbc spi并发加载死锁 2022-03-19 16:19:00 +08:00
130 changed files with 853 additions and 3094 deletions

6
.gitignore vendored
View File

@@ -37,10 +37,4 @@ nbdist/
### VS Code ###
.vscode/
# dependencies
node_modules
.docusaurus
yarn.lock
# debug env
application-dev.yml

View File

@@ -6,9 +6,9 @@
[comment]: <> (<img alt="sureness" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="300">)
## HertzBeat 赫兹跳动 | [English Documentation](README_EN.md)
## 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)
@@ -35,7 +35,7 @@
----
[![tancloud](tancloud.gif)](https://www.bilibili.com/video/BV1DY4y1i7ts)
[![tancloud](tancloud.gif)](https://www.bilibili.com/video/BV1Vi4y1f7i8)
----
@@ -93,7 +93,6 @@
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 `
4. 浏览器访问 localhost:1157 即可开始,默认账号密码 admin/admin
详细步骤参考 [通过安装包安装HertzBeat](https://hertzbeat.com/docs/start/package-deploy)
@@ -139,8 +138,7 @@ HertzBeat赫兹跳动为 [Dromara开源社区](https://dromara.org/) 孵化项
##### 赞助
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
感谢[天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) 赞助服务器采集节点
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com)赞助服务器采集节点
## 🛡️ License
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)

View File

@@ -1,148 +0,0 @@
<p align="center">
<a href="https://hertzbeat.com">
<img alt="hertzbeat" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="260">
</a>
</p>
[comment]: <> (<img alt="sureness" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/hertzbeat-brand.svg" width="300">)
## HertzBeat | [中文文档](README.md)
> Friendly cloud monitoring system.
![tan-cloud](https://img.shields.io/badge/web-monitor-4EB1BA)
![tan-cloud](https://img.shields.io/badge/api-monitor-lightgrey)
![tan-cloud](https://img.shields.io/badge/ping-connect-brightgreen)
![tan-cloud](https://img.shields.io/badge/port-available-green)
![tan-cloud](https://img.shields.io/badge/database-monitor-yellowgreen)
![tan-cloud](https://img.shields.io/badge/os-monitor-yellow)
![tan-cloud](https://img.shields.io/badge/custom-monitor-orange)
![tan-cloud](https://img.shields.io/badge/threshold-red)
![tan-cloud](https://img.shields.io/badge/alert-bule)
**Home: [hertzbeat.com](https://hertzbeat.com) | [tancloud.cn](https://tancloud.cn)**
## 🎡 <font color="green">Introduction</font>
> [HertzBeat](https://github.com/dromara/hertzbeat) is an opensource monitoring and alarm project incubated by [Dromara](https://dromara.org) and open sourced by [TanCloud](https://tancloud.cn), which supports Website, API, PING, Port, Database, OS Monitor etc.
> We also provide **[Monitoring Cloud For Saas](https://console.tancloud.cn)**, people no longer need to deploy a cumbersome monitoring system in order to monitor their website resources. **[Sign in to get started for free](https://console.tancloud.cn)**.
> HertzBeat supports more liberal threshold alarm configuration (calculation expression), supports alarm notification, alarm template, email, DingDing, WeChat FeiShu and WebHook.
> Most important is HertzBeat supports [Custom Monitoring](https://hertzbeat.com/docs/advanced/extend-point), just by configuring the YML file, we can customize the monitoring types and metrics what we need.
> HertzBeat is modular, `manager, collector, scheduler, warehouse, alerter` modules are decoupled for easy understanding and custom development.
> Welcome to HertzBeat's [Cloud Environment TanCloud](https://console.tancloud.cn) to try and discover more.
> Welcome to join us to build hertzbeat together.
> `HertzBeat`'s multi-type support, easy expansion, low coupling, hope to help developers and micro teams to quickly build their own monitoring system.
----
[![tancloud](tancloud.gif)](https://www.bilibili.com/video/BV1DY4y1i7ts)
----
## 🥐 Architecture
- **[manager](https://github.com/dromara/hertzbeat/tree/master/manager)** Provide monitoring management, system management basic services.
> Provides monitoring management, monitoring configuration management, system user management, etc.
- **[collector](https://github.com/dromara/hertzbeat/tree/master/collector)** Provide metrics data collection services.
> Use common protocols to remotely collect and obtain peer-to-peer metrics data.
- **[scheduler](https://github.com/dromara/hertzbeat/tree/master/scheduler)** Provide monitoring task scheduling service.
> Collection task management, scheduling and distribution of one-time tasks and periodic tasks.
- **[warehouse](https://github.com/dromara/hertzbeat/tree/master/warehouse)** Provide monitoring data warehousing services.
> Metrics data management, data query, calculation and statistics.
- **[alerter](https://github.com/dromara/hertzbeat/tree/master/alerter)** Provide alert service.
> Alarm calculation trigger, monitoring status linkage, alarm configuration, and alarm notification.
- **[web-app](https://github.com/dromara/hertzbeat/tree/master/web-app)** Provide web ui.
> Angular Web UI.
![hertzBeat](home/static/img/docs/hertzbeat-stru-en.svg)
## 🐕 Quick Start
- If you dont want to deploy but use it directly, we provide [SAAS Monitoring Cloud-TanCloud](https://console.tancloud.cn), **[Log In And Register For Free](https://console.tancloud.cn) **.
- If you want to deploy HertzBeat local, please refer to the following [Deployment Documentation](https://hertzbeat.com/docs/start/quickstart) for operation.
### 🐵 Dependency Service Deployment
> HertzBeat depends at least on relational database [MYSQL5+](https://www.mysql.com/) and time series database [TDengine2+](https://www.taosdata.com/getting-started)
##### Install MYSQL
1. Install mysql with docker
`docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7`
2. Create database names `hertzbeat`
3. Run the database sql script [schema.sql](https://gitee.com/dromara/hertzbeat/raw/master/script/sql/schema.sql) located in the project repository `/script/sql/` directory.
For detailed steps, refer to [MYSQL Installation And Initialization](https://hertzbeat.com/docs/start/mysql-init)
##### Install TDengine
1. Install TDengine with docker
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
2. Create database names `hertzbeat`
For detailed steps, refer to [TDengine Installation And Initialization](https://hertzbeat.com/docs/start/tdengine-init).
### 🍞 Install HertzBeat
> HertzBeat supports installation through source code, docker or package.
##### 1Install quickly via docker
`docker run -d -p 1157:1157 -v /opt/application.yml:/opt/hertzbeat/config/application.yml --name hertzbeat tancloud/hertzbeat:[版本tag]`
Detailed steps refer to [Install HertzBeat via Docker](https://hertzbeat.com/docs/start/docker-deploy)
##### 2Install via package
1. Download the installation package [GITEE Release](https://gitee.com/dromara/hertzbeat/releases) [GITHUB Release](https://github.com/dromara/hertzbeat/releases)
2. Configure the HertzBeat configuration yml file `hertzbeat/config/application.yml`
3. Run shell `$ ./startup.sh `
4. Access `localhost:1157` to start, default account: `admin/admin`
Detailed steps refer to [Install HertzBeat via package](https://hertzbeat.com/docs/start/package-deploy)
##### 3Start via source code
1. Local source code debugging needs to start the back-end project manager and the front-end project web-app.
2. Backendneed `maven3+`, `java8+`, start the manager service.
3. Webneed `nodejs npm angular-cli` environment, Run `ng serve --open` in `web-app` directory after backend startup.
4. Access `localhost:4200` to start, default account: `admin/admin`
Detailed steps refer to [CONTRIBUTING](CONTRIBUTING.md)
##### 4Install All(mysql+tdengine+hertzbeat) via Docker-compose
Install and deploy the mysql database, tdengine database and hertzbeat at one time through [docker-compose deployment script](script/docker-compose).
Detailed steps refer to [docker-compose install](script/docker-compose/README.md)
**HAVE FUN**
## 💬 Join discussion
HertzBeat is an incubation project of [Dromara Open Source Community](https://dromara.org/).
##### WeChat Group
Add WeChat account `tan-cloud` or scan the QR code below to pull you into the WeChat group.
<img alt="tan-cloud" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/help/tan-cloud-wechat.jpg" width="200"/>
##### QQ Group
QQ group number `718618151` or scan the group QR code below, verify code: `tancloud`
<img alt="tan-cloud" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat@gh-pages/img/docs/help/qq-qr.jpg" width="200"/>
##### Github Discussion
Welcome to Discuss in [Github Discussion](https://github.com/dromara/hertzbeat/discussions)
##### Public WeChat
<img alt="tan-cloud" src="https://cdn.jsdelivr.net/gh/dromara/hertzbeat/home/static/img/wechat.png" width="400"/>
##### Sponsor
Thanks [吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) sponsored server node.
Thanks [天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) sponsored server node.
## 🛡️ License
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)

View File

@@ -110,7 +110,7 @@ public class CalculateAlarm {
} else {
// 其他异常
alertBuilder.target(CommonConstants.AVAILABLE)
.content("监控可用性告警: " + metricsData.getCode().name() + " : " + metricsData.getMsg());
.content("监控紧急可用性告警: " + metricsData.getCode().name());
triggeredMonitorStateAlertMap.put(monitorId, metricsData.getCode());
dataQueue.addAlertData(alertBuilder.build());
}

View File

@@ -109,12 +109,6 @@
<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

@@ -17,9 +17,7 @@ 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;
/**
@@ -77,18 +75,7 @@ public class CommonHttpClient {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
@Override
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();
}
}
}
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
@Override
public X509Certificate[] getAcceptedIssuers() { return null; }
};
@@ -108,8 +95,8 @@ public class CommonHttpClient {
.setConnectTimeout(CONNECT_TIMEOUT)
// 数据传输最大响应间隔时间
.setSocketTimeout(SOCKET_TIMEOUT)
// 遇到301 302自动重定向跳转
.setRedirectsEnabled(true)
// 遇到301 302自动重定向跳转
.setRedirectsEnabled(false)
.build();
// 连接池
connectionManager = new PoolingHttpClientConnectionManager(registry);

View File

@@ -2,9 +2,6 @@ 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
@@ -19,14 +16,6 @@ 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,8 +52,8 @@ public class JdbcCommonCollect extends AbstractCollect {
}
JdbcProtocol jdbcProtocol = metrics.getJdbc();
String databaseUrl = constructDatabaseUrl(jdbcProtocol);
// 查询超时时间默认6000毫秒
int timeout = 6000;
// 查询超时时间默认3000毫秒
int timeout = 3000;
try {
// 获取查询语句超时时间
if (jdbcProtocol.getTimeout() != null) {
@@ -285,10 +285,6 @@ public class JdbcCommonCollect extends AbstractCollect {
url = "jdbc:sqlserver://" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ ";" + (jdbcProtocol.getDatabase() == null ? "" : "DatabaseName=" + jdbcProtocol.getDatabase());
break;
case "oracle":
url = "jdbc:oracle:thin:@" + jdbcProtocol.getHost() + ":" + jdbcProtocol.getPort()
+ "/" + (jdbcProtocol.getDatabase() == null ? "" : jdbcProtocol.getDatabase());
break;
default:
throw new IllegalArgumentException("Not support database platform: " + jdbcProtocol.getPlatform());

View File

@@ -23,7 +23,6 @@ public class JdbcSpiLoader implements CommandLineRunner {
Class.forName("com.mysql.cj.jdbc.Driver");
Class.forName("org.postgresql.Driver");
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Exception e) {
log.error("load jdbc error: {}", e.getMessage(), e);
}

View File

@@ -7,7 +7,6 @@ import com.google.gson.JsonParser;
import com.usthe.collector.collect.AbstractCollect;
import com.usthe.collector.collect.common.http.CommonHttpClient;
import com.usthe.collector.dispatch.DispatchConstants;
import com.usthe.collector.util.CollectUtil;
import com.usthe.collector.util.CollectorConstants;
import com.usthe.collector.util.JsonPathParser;
import com.usthe.common.entity.job.Metrics;
@@ -101,7 +100,7 @@ public class HttpCollectImpl extends AbstractCollect {
String parseType = metrics.getHttp().getParseType();
try {
if (DispatchConstants.PARSE_DEFAULT.equals(parseType)) {
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
parseResponseByDefault(resp, metrics.getAliasFields(), builder, responseTime);
} else if (DispatchConstants.PARSE_JSON_PATH.equals(parseType)) {
parseResponseByJsonPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
} else if (DispatchConstants.PARSE_PROMETHEUS.equals(parseType)) {
@@ -109,11 +108,11 @@ public class HttpCollectImpl extends AbstractCollect {
} else if (DispatchConstants.PARSE_XML_PATH.equals(parseType)) {
parseResponseByXmlPath(resp, metrics.getAliasFields(), metrics.getHttp(), builder);
} else if (DispatchConstants.PARSE_WEBSITE.equals(parseType)){
parseResponseByWebsite(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
parseResponseByWebsite(resp, metrics.getAliasFields(), builder, responseTime);
} else if (DispatchConstants.PARSE_SITE_MAP.equals(parseType)) {
parseResponseBySiteMap(resp, metrics.getAliasFields(), builder);
} else {
parseResponseByDefault(resp, metrics.getAliasFields(), metrics.getHttp(), builder, responseTime);
parseResponseByDefault(resp, metrics.getAliasFields(), builder, responseTime);
}
} catch (Exception e) {
log.info("parse error: {}.", e.getMessage(), e);
@@ -170,16 +169,13 @@ public class HttpCollectImpl extends AbstractCollect {
}
}
private void parseResponseByWebsite(String resp, List<String> aliasFields, HttpProtocol http,
private void parseResponseByWebsite(String resp, List<String> aliasFields,
CollectRep.MetricsData.Builder builder, Long responseTime) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
// 网站关键词数量监测
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
// todo resp 网站关键监测
for (String alias : aliasFields) {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
@@ -281,7 +277,6 @@ public class HttpCollectImpl extends AbstractCollect {
private void parseResponseByJsonPath(String resp, List<String> aliasFields, HttpProtocol http,
CollectRep.MetricsData.Builder builder, Long responseTime) {
List<Map<String, Object>> results = JsonPathParser.parseContentWithJsonPath(resp, http.getParseScript());
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
for (Map<String, Object> stringMap : results) {
CollectRep.ValueRow.Builder valueRowBuilder = CollectRep.ValueRow.newBuilder();
for (String alias : aliasFields) {
@@ -291,8 +286,6 @@ public class HttpCollectImpl extends AbstractCollect {
} else {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}
@@ -307,10 +300,9 @@ public class HttpCollectImpl extends AbstractCollect {
}
private void parseResponseByDefault(String resp, List<String> aliasFields, HttpProtocol http,
private void parseResponseByDefault(String resp, List<String> aliasFields,
CollectRep.MetricsData.Builder builder, Long responseTime) {
JsonElement element = JsonParser.parseString(resp);
int keywordNum = CollectUtil.countMatchKeyword(resp, http.getKeyword());
if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
for (JsonElement jsonElement : array) {
@@ -325,8 +317,6 @@ public class HttpCollectImpl extends AbstractCollect {
} else {
if (CollectorConstants.RESPONSE_TIME.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(responseTime.toString());
} else if (CollectorConstants.KEYWORD.equalsIgnoreCase(alias)) {
valueRowBuilder.addColumns(Integer.toString(keywordNum));
} else {
valueRowBuilder.addColumns(CommonConstants.NULL_VALUE);
}

View File

@@ -37,8 +37,8 @@ public class IcmpCollectImpl extends AbstractCollect {
return;
}
IcmpProtocol icmp = metrics.getIcmp();
// 超时时间默认6000毫秒
int timeout = 6000;
// 超时时间默认300毫秒
int timeout = 300;
try {
timeout = Integer.parseInt(icmp.getTimeout());
} catch (Exception e) {

View File

@@ -5,7 +5,6 @@ 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;
@@ -20,7 +19,6 @@ 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;
@@ -58,8 +56,8 @@ public class SshCollectImpl extends AbstractCollect {
return;
}
SshProtocol sshProtocol = metrics.getSsh();
// 超时时间默认6000毫秒
int timeout = 6000;
// 超时时间默认300毫秒
int timeout = 3000;
try {
timeout = Integer.parseInt(sshProtocol.getTimeout());
} catch (Exception e) {
@@ -183,13 +181,6 @@ 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();
// 超时时间默认6000毫秒
int timeout = 6000;
// 超时时间默认300毫秒
int timeout = 300;
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 = 240_000L;
private static final long DURATION_TIME = 120_000L;
/**
* 指标组采集任务优先级队列
*/
@@ -94,7 +94,7 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
Thread.currentThread().setName("metrics-task-monitor");
while (!Thread.currentThread().isInterrupted()) {
try {
// 检测每个指标组采集单元是否超时4分钟,超时则丢弃并返回异常
// 检测每个指标组采集单元是否超时2分钟,超时则丢弃并返回异常
long deadline = System.currentTimeMillis() - DURATION_TIME;
for (Map.Entry<String, MetricsTime> entry : metricsTimeoutMonitorMap.entrySet()) {
MetricsTime metricsTime = entry.getValue();
@@ -105,13 +105,9 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
.setId(timerJob.getJob().getMonitorId())
.setApp(timerJob.getJob().getApp())
.setMetrics(metricsTime.getMetrics().getName())
.setPriority(metricsTime.getMetrics().getPriority())
.setTime(System.currentTimeMillis())
.setCode(CollectRep.Code.TIMEOUT).setMsg("collect timeout").build();
log.error("[Collect Timeout]: \n{}", metricsData);
if (metricsData.getPriority() == 0) {
dispatchCollectData(metricsTime.timeout, metricsTime.getMetrics(), metricsData);
}
dispatchCollectData(metricsTime.timeout, metricsTime.getMetrics(), metricsData);
metricsTimeoutMonitorMap.remove(entry.getKey());
}
}
@@ -169,8 +165,8 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
metricsSet.forEach(metricItem -> {
MetricsCollect metricsCollect = new MetricsCollect(metricItem, timeout, this);
jobRequestQueue.addJob(metricsCollect);
metricsTimeoutMonitorMap.put(job.getId() + "-" + metricItem.getName(),
new MetricsTime(System.currentTimeMillis(), metricItem, timeout));
metricsTimeoutMonitorMap.put(job.getId() + metrics.getName(),
new MetricsTime(System.currentTimeMillis(), metrics, timeout));
});
} else {
// 当前执行级别的指标组列表未全执行完成,
@@ -189,8 +185,8 @@ public class CommonDispatcher implements MetricsTaskDispatch, CollectDataDispatc
metricsSet.forEach(metricItem -> {
MetricsCollect metricsCollect = new MetricsCollect(metricItem, timeout, this);
jobRequestQueue.addJob(metricsCollect);
metricsTimeoutMonitorMap.put(job.getId() + "-" + metricItem.getName(),
new MetricsTime(System.currentTimeMillis(), metricItem, timeout));
metricsTimeoutMonitorMap.put(job.getId() + metrics.getName(),
new MetricsTime(System.currentTimeMillis(), metrics, timeout));
});
} else {
// 当前执行级别的指标组列表未全执行完成,

View File

@@ -34,10 +34,6 @@ import java.util.stream.Collectors;
@Slf4j
@Data
public class MetricsCollect implements Runnable, Comparable<MetricsCollect> {
/**
* 调度告警阈值时间 100ms
*/
private static final long WARN_DISPATCH_TIME = 100;
/**
* 监控ID
*/
@@ -247,10 +243,6 @@ public class MetricsCollect implements Runnable, Comparable<MetricsCollect> {
value = aliasFieldValueMap.get(realField);
}
}
// 处理可能带单位的指标数值 比如 34%, 34Mb并将数值小数点限制到4位
if (CommonConstants.TYPE_NUMBER == field.getType()) {
value = CommonUtil.parseDoubleStr(value, field.getUnit());
}
if (value == null) {
value = CommonConstants.NULL_VALUE;
}
@@ -275,15 +267,11 @@ public class MetricsCollect implements Runnable, Comparable<MetricsCollect> {
private CollectRep.MetricsData validateResponse(CollectRep.MetricsData.Builder builder) {
long endTime = System.currentTimeMillis();
builder.setTime(endTime);
long runningTime = endTime - startTime;
long allTime = endTime - newTime;
if (startTime - newTime >= WARN_DISPATCH_TIME) {
log.warn("[Collector Dispatch Warn, Dispatch Use {}ms.", startTime - newTime);
}
log.debug("[Collect]: newTime: {}, startTime: {}, spendTime: {}.", newTime, startTime, endTime - startTime);
if (builder.getCode() != CollectRep.Code.SUCCESS) {
log.info("[Collect Failed, Run {}ms, All {}ms] Reason: {}", runningTime, allTime, builder.getMsg());
log.info("[Collect Fail] Reason: {}", builder.getMsg());
} else {
log.info("[Collect Success, Run {}ms, All {}ms].", runningTime, allTime);
log.info("[Collect Success].");
}
return builder.build();
}

View File

@@ -12,7 +12,6 @@ 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;
@@ -85,26 +84,6 @@ 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

@@ -1,35 +0,0 @@
package com.usthe.collector.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 采集器工具类
* @author tom
* @date 2022/4/6 09:35
*/
public class CollectUtil {
/**
* 关键字匹配计数
* @param content 内容
* @param keyword 关键字
* @return 匹配次数
*/
public static int countMatchKeyword(String content, String keyword) {
if (content == null || "".equals(content) || keyword == null || "".equals(keyword.trim())) {
return 0;
}
try {
Pattern pattern = Pattern.compile(keyword);
Matcher matcher = pattern.matcher(content);
int count = 0;
while (matcher.find()) {
count++;
}
return count;
} catch (Exception e) {
return 0;
}
}
}

View File

@@ -9,8 +9,6 @@ public interface CollectorConstants {
String RESPONSE_TIME = "responseTime";
String KEYWORD = "keyword";
String STATUS_CODE = "statusCode";
String ERROR_MSG = "errorMsg";

View File

@@ -1,48 +0,0 @@
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

@@ -4,7 +4,6 @@ import org.apache.commons.net.telnet.TelnetClient;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.ConnectException;
import static org.junit.jupiter.api.Assertions.*;
@@ -21,7 +20,7 @@ class TelnetCollectImplTest {
telnetClient = new TelnetClient("vt200");
telnetClient.setConnectTimeout(5000);
TelnetClient finalTelnetClient = telnetClient;
assertThrows(ConnectException.class,() -> finalTelnetClient.connect("127.0.0.1",0));
assertDoesNotThrow(() -> finalTelnetClient.connect("baidu.com",80));
telnetClient.disconnect();
} catch (IOException e) {
e.printStackTrace();

View File

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

View File

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

View File

@@ -49,6 +49,7 @@ public class HttpProtocol {
* http请求携带的请求体
*/
private String payload;
/**
* 认证信息
*/
@@ -65,10 +66,6 @@ public class HttpProtocol {
* 数据解析脚本 当解析方式为 jsonPath or xmlPath时存在
*/
private String parseScript;
/**
* 内容关键字
*/
private String keyword;
/**
* 认证信息

View File

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

View File

@@ -59,15 +59,15 @@ public class Param {
* 参数值
*/
@ApiModelProperty(value = "参数值", example = "8080", accessMode = READ_WRITE, position = 3)
@Length(max = 8126)
@Length(max = 255)
private String value;
/**
* 参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串
* 参数类型 0:数字 1:字符串 2:加密串
*/
@ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串 3:map映射的json串", accessMode = READ_WRITE, position = 4)
@ApiModelProperty(value = "参数类型 0:数字 1:字符串 2:加密串", accessMode = READ_WRITE, position = 4)
@Min(0)
@Max(3)
@Max(2)
private byte type;
/**

View File

@@ -110,47 +110,29 @@ 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;
/**
* 是否是高级隐藏参数 true-是 false-否
*/
@ApiModelProperty(value = "是否是高级隐藏参数 true-是 false-否", example = "true", accessMode = READ_WRITE, position = 11)
private boolean hide = false;
/**
* 此条记录创建者
*/
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11)
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 9)
private String creator;
/**
* 此条记录最新修改者
*/
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12)
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 10)
private String modifier;
/**
* 记录创建时间
*/
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13)
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 11)
@Column(insertable = false, updatable = false)
private LocalDateTime gmtCreate;
/**
* 记录最新修改时间
*/
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14)
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 12)
@Column(insertable = false, updatable = false)
private LocalDateTime gmtUpdate;

View File

@@ -2,8 +2,6 @@ package com.usthe.common.util;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -17,7 +15,7 @@ public class CommonUtil {
private static final Pattern EMAIL_PATTERN = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
private static final Pattern PHONE_PATTERN = Pattern.compile("^(((13[0-9])|(14[0-9])|(15[0-9])|(16[0-9])|(19[0-9])|(18[0-9])|(17[0-9]))+\\d{8})?$");
private static final Pattern PHONE_PATTERN = Pattern.compile("^(((13[0-9])|(15[0-9])|(18[0-9])|(17[0-9]))+\\d{8})?$");
private static final int PHONE_LENGTH = 11;
@@ -38,30 +36,6 @@ public class CommonUtil {
}
}
/**
* 将字符串str,此字符串可能带单位,转换为double数字类型
* 将数值小数点限制到4位
* @param str string
* @param unit 字符串单位
* @return string格式的 double 数字 小数点最大到4位
*/
public static String parseDoubleStr(String str, String unit) {
if (str == null || "".equals(str)) {
return null;
}
try {
if (unit != null && str.endsWith(unit)) {
str = str.substring(0, str.length() - unit.length());
}
BigDecimal bigDecimal = new BigDecimal(str);
double value = bigDecimal.setScale(4, RoundingMode.HALF_UP).doubleValue();
return String.valueOf(value);
} catch (Exception e) {
log.debug(e.getMessage(), e);
return null;
}
}
/**
* 邮箱格式校验
* @param email 邮箱

View File

@@ -1,40 +0,0 @@
package com.usthe.common.util;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author tom
* @date 2022/4/7 17:18
*/
class CommonUtilTest {
@Test
void testParseDoubleStr() {
assertEquals("9.3454",CommonUtil.parseDoubleStr("9.345435345", null));
assertEquals("9.3454",CommonUtil.parseDoubleStr("9.345435345%", "%"));
assertEquals("10.0",CommonUtil.parseDoubleStr("10%", "%"));
assertEquals("588.0",CommonUtil.parseDoubleStr("588Mb", "Mb"));
}
@Test
void validateEmail() {
assertTrue(CommonUtil.validateEmail("tom@usthe.com"));
assertTrue(CommonUtil.validateEmail("demo@qq.com"));
assertFalse(CommonUtil.validateEmail("tom.usthe.com"));
}
@Test
void validatePhoneNum() {
assertTrue(CommonUtil.validatePhoneNum("19234554432"));
assertTrue(CommonUtil.validatePhoneNum("13234554432"));
assertTrue(CommonUtil.validatePhoneNum("14234554432"));
assertTrue(CommonUtil.validatePhoneNum("16234554432"));
assertFalse(CommonUtil.validatePhoneNum("12234554432"));
assertFalse(CommonUtil.validatePhoneNum("11234554432"));
assertFalse(CommonUtil.validatePhoneNum("35234554432"));
assertFalse(CommonUtil.validatePhoneNum("46234554432"));
}
}

View File

@@ -1,70 +0,0 @@
---
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

@@ -1,92 +0,0 @@
---
title: HertzBeat入GVP啦并 v1.0.beta.7 发布,易用友好的云监控系统
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孵化的支持网站APIPING端口数据库全站操作系统等监控类型支持阈值告警告警通知(邮箱webhook钉钉企业微信飞书机器人),拥有易用友好的可视化操作界面的开源监控告警项目。
很高兴Hertzbeat被评定为GVP - Gitee最有价值开源项目
![截屏2022-04-08 09.14.44.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8899bc4e836943dba2ec9efeec4ff629~tplv-k3u1fbpfcp-watermark.image?)
老哥们帮忙在Gitee STAR起来https://gitee.com/dromara/hertzbeat
官网:hertzbeat.com | tancloud.cn
然后来说说最新的版本这个版本看这么多feature其实简单来说主要是这几个
支持了ORACLE数据库的监控包括ORACLE的基本信息表空间连接数TPSQPS等指标
支持了LINUX的CPU利用率内存利用率磁盘占用相关指标使LINUX监控贴合实际业务
还有前端参数支持了KEY-VALUE以后我们就可以在页面上配置HTTP Headers等类似参数了还有就是参数配置那优化改版把非常用告警参数隐藏起来了稍微好看些然后支持了windows下bat启动脚本更多的就是稳定性的提升和一些其它的小修复小需求啦
版本特性:
1. feature 支持oracle数据库监控类型-xgf 由 @gf-8 贡献 thanks
2. feature oracle监控支持tablespace,连接数,qps,tps等指标
3. feature linux监控支持设置超时时间 (#49)
4. feature 检测网站SSL证书是否过期 (#50) 由 @weihongbin 提出 thanks
5. feature 页面配置参数支持KEY-VALUE数组(#57)
6. feature API和网站监控支持页面配置Headers和Params (#58)(#59)
7. feature API和网站监控支持页面配置 basic auth, digest auth (#60)
8. feature http 端口跟随SSL是否启用变更443或80 (#61)
9. feature 修改默认超时时间3000毫秒为6000毫秒 (#55)
10. feature:make tdengine optional, not required (#62)
11. feature:support win bat service (#65)
12. feature:support hide advanced params define (#68)
13. feature:enable auto redirect when 301 302 http code (#69)
14. feature:only collect available metrics when detect (#70)
15. feature:[website api]monitor support keyword match (#72)
16. feature:support linux cpu usage,memory usage,disk free (#76)
BUG修复
1. 添加sqlserver关联文档fix connection指标入库tdengine失败 (#41)
2. 使用docker部署TDengine开放tcp访问端口!16 由 @老姜bei 贡献 thanks
3. 补充sureness配置文档 避免误配导致权限异常
4. bugfix:monitors always timeout alert (#67)
5. code format and optimization 由 @学习代码的小白 贡献 thanks
6. bugfix: remove oracle field - database_type due 11g not support 由 @syongaaa 贡献 thanks
7. bugfix:fix linux interface metrics no instance (#75)
欢迎在线试用 https://console.tancloud.cn.
-----------------------
> [HertzBeat赫兹跳动](https://github.com/dromara/hertzbeat) 是一个支持网站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/BV1DY4y1i7ts
欢迎在线试用 [https://console.tancloud.cn](https://gitee.com/link?target=https%3A%2F%2Fconsole.tancloud.cn)
优化后的参数输入界面:
![输入图片说明](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c4b07908ba5a4b50a094a02dde6a38f3~tplv-k3u1fbpfcp-zoom-1.image "截屏2022-04-07 21.32.52.png")
Linux新增指标:
![输入图片说明](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/92828224f8cd4cac84245aa4217b29e7~tplv-k3u1fbpfcp-zoom-1.image "截屏2022-04-07 17.50.22.png")
ORACLE监控:
哦豁oracle环境不在了之前没有截图先脑补一张
**仓库地址**
[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

@@ -3,7 +3,7 @@ id: extend-jdbc
title: JDBC协议自定义监控
sidebar_label: JDBC协议自定义监控
---
> 从[自定义监控](extend-point)了解熟悉了怎么自定义类型指标协议等这里我们来详细介绍下用JDBC(目前支持mysql,mariadb,postgresql,sqlserver)自定义指标监控。
> 从[自定义监控](extend-point)了解熟悉了怎么自定义类型指标协议等这里我们来详细介绍下用JDBC(目前支持mysql,mariadb,postgresql)自定义指标监控。
> JDBC协议自定义监控可以让我们很方便的通过写SQL查询语句就能监控到我们想监控的指标
### JDBC协议采集流程

View File

@@ -18,7 +18,7 @@ sidebar_label: 帮助入门
### 数据库监控
[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)
[MYSQL数据库监控](mysql) &emsp;&emsp;&emsp;&emsp; [MariaDB数据库监控](mariadb) &emsp;&emsp;&emsp;&emsp; [PostgreSQL数据库监控](postgresql)
### 操作系统监控

View File

@@ -38,7 +38,6 @@ sidebar_label: Linux操作系统
| interrupt | 个数 | CPU中断数量 |
| load | 无 | CPU最近1/5/15分钟的平均负载 |
| context_switch | 个数 | 当前上下文切换数量 |
| usage | % | CPU使用率 |
#### 指标集合memory
@@ -50,7 +49,6 @@ sidebar_label: Linux操作系统
| free | Mb | 空闲内存容量 |
| buff_cache | Mb | 缓存占用内存 |
| available | Mb | 剩余可用内存容 |
| usage | % | 内存使用率 |
#### 指标集合disk
@@ -70,12 +68,3 @@ sidebar_label: Linux操作系统
| receive_bytes | byte | 入站数据流量(bytes) |
| transmit_bytes | byte | 出站数据流量(bytes) |
#### 指标集合disk_free
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| filesystem | 无 | 文件系统的名称 |
| used | Mb | 已使用磁盘大小 |
| available | Mb | 可用磁盘大小 |
| usage | % | 使用率 |
| mounted | 无 | 挂载点目录 |

View File

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

View File

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

View File

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

View File

@@ -1,57 +0,0 @@
---
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,7 +5,7 @@ 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)

View File

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

View File

@@ -43,56 +43,10 @@ sidebar_label: Docker方式部署
HertzBeat默认内置三个用户账户,分别为 admin/admin tom/tom@123 lili/lili
若需要新增删除修改账户或密码,可以通过配置 `sureness.yml` 实现,若无此需求可忽略此步骤
在主机目录下创建sureness.ymleg:/opt/sureness.yml
配置文件内容参考 项目仓库[/script/sureness.yml](https://gitee.com/dromara/hertzbeat/blob/master/script/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
@@ -128,7 +82,7 @@ sidebar_label: Docker方式部署
- tancloud/hertzbeat:[版本tag] : 使用拉取的HertzBeat官方发布的应用镜像来启动容器,TAG可查看[官方镜像仓库](https://hub.docker.com/r/tancloud/hertzbeat/tags)
7. 开始探索HertzBeat
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警,默认账户密码 admin/admin。
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警
**HAVE FUN**
@@ -147,4 +101,4 @@ sidebar_label: Docker方式部署
3. **日志报错TDengine连接或插入SQL失败**
> 一:排查配置的数据库账户密码是否正确,数据库是否创建
> 二若是安装包安装的TDengine2.3+除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter
> 二若是安装包安装的TDengine2.3+除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter

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进行监控告警,默认账户密码 admin/admin。
浏览器访问 http://ip:1157/console 开始使用HertzBeat进行监控告警
**HAVE FUN**
@@ -90,4 +90,4 @@ sidebar_label: 安装包方式部署
2. **日志报错TDengine连接或插入SQL失败**
> 一:排查配置的数据库账户密码是否正确,数据库是否创建
> 二若是安装包安装的TDengine2.3+除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter
> 二若是安装包安装的TDengine2.3+除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter

View File

@@ -47,7 +47,7 @@ sidebar_label: 快速开始
1. 此为前后端分离项目本地代码调试需要分别启动后端工程manager和前端工程web-app
2. 后端:需要`maven3+``java8+`环境修改YML配置信息并启动manager服务
3. 前端:需要`nodejs npm angular-cli`环境待本地后端启动后在web-app目录下启动 `ng serve --open`
4. 浏览器访问 localhost:4200 即可开始,默认账户密码 admin/admin
4. 浏览器访问 localhost:4200 即可开始
详细步骤参考 [参与贡献之本地代码启动](../others/contributing)

View File

@@ -18,11 +18,10 @@ TDengine是一款国产的开源物联网时序型数据库我们使用其替
```
2. Docker安装TDengine
```
$ docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp -v /opt/taosdata:/var/lib/taos --name tdengine -e TZ=Asia/Shanghai tdengine/tdengine:2.4.0.12
$ 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`替换为实际本地存在的目录
`-e TZ="Asia/Shanghai"` 为tdengine设置时区这里可选设置对应的时区
`-v /opt/taosdata:/var/lib/taos` 为tdengine数据目录本地持久化挂载需将`/opt/taosdata`替换为实际本地存在的目录
使用```$ docker ps```查看数据库是否启动成功
### 创建数据库实例
@@ -52,4 +51,4 @@ TDengine是一款国产的开源物联网时序型数据库我们使用其替
```
**注意⚠若是安装包安装的TDengine2.3+版本**
> 除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter
> 除了启动server外还需执行 `systemctl start taosadapter` 启动 adapter

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: 'HertzBeat',
tagline: '易用友好的云监控系统',
title: 'TANCLOUD探云',
tagline: '易用友好的高性能监控云',
url: 'https://hertzbeat.com',
baseUrl: '/',
onBrokenLinks: 'throw',

View File

@@ -64,9 +64,7 @@
"items": [
"help/mysql",
"help/mariadb",
"help/postgresql",
"help/sqlserver",
"help/oracle"
"help/postgresql"
]
},
{

View File

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

View File

@@ -28,13 +28,12 @@ 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>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -1,4 +0,0 @@
<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>

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -31,7 +31,6 @@ import java.util.List;
/**
* 告警信息入库分发
*
* @author tom
* @date 2021/12/10 12:58
*/
@@ -108,9 +107,9 @@ public class DispatchAlarm {
}
} else {
// 若是恢复告警 需对监控状态进行恢复
if (alert.getStatus() == CommonConstants.ALERT_STATUS_CODE_RESTORED) {
monitorService.updateMonitorStatus(alert.getMonitorId(), CommonConstants.AVAILABLE_CODE);
}
if (alert.getStatus() == CommonConstants.ALERT_STATUS_CODE_RESTORED) {
monitorService.updateMonitorStatus(alert.getMonitorId(), CommonConstants.AVAILABLE_CODE);
}
}
// 告警落库
alertService.addAlert(alert);
@@ -123,37 +122,22 @@ public class DispatchAlarm {
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;
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;
}
}
}
/**
* 通过飞书发送告警信息
*
* @param receiver 接收人
* @param alert 告警信息
* @param alert 告警信息
*/
private void sendFlyBookAlert(NoticeReceiver receiver, Alert alert) {
FlyBookWebHookDto flyBookWebHookDto = new FlyBookWebHookDto();
@@ -200,9 +184,8 @@ public class DispatchAlarm {
/**
* 通过钉钉机器人发送告警信息
*
* @param receiver 通知配置信息
* @param alert 告警信息
* @param receiver 通知配置信息
* @param alert 告警信息
*/
private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) {
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
@@ -234,9 +217,8 @@ public class DispatchAlarm {
/**
* 通过企业微信发送告警信息
*
* @param receiver 通知配置信息
* @param alert 告警信息
* @param receiver 通知配置信息
* @param alert 告警信息
*/
private void sendWeWorkRobotAlert(NoticeReceiver receiver, Alert alert) {
WeWorkWebHookDto weWorkWebHookDTO = new WeWorkWebHookDto();
@@ -249,7 +231,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");
}
@@ -291,23 +273,23 @@ 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
messageHelper.setFrom(emailFromUser);
//设定收件人Email
messageHelper.setTo(receiver.getEmail());
messageHelper.setTo(receiver.getEmail());
messageHelper.setSentDate(new Date());
//构建邮件模版
String process = mailService.buildAlertHtmlTemplate(alert);
//设置邮件内容模版
messageHelper.setText(process, true);
messageHelper.setText(process,true);
javaMailSender.send(mimeMessage);
} catch (Exception e) {
log.error("[邮箱告警] errorException information={}", e.getMessage());
}catch (Exception e){
log.error("[邮箱告警] errorException information={}",e.getMessage());
}
}

View File

@@ -7,7 +7,6 @@ import lombok.NoArgsConstructor;
/**
* 企业微信机器人请求消息体
*
* @author 花城
* @version 1.0
* @date 2022/2/21 6:55 下午
@@ -19,14 +18,7 @@ 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

@@ -79,10 +79,6 @@ public class MonitorServiceImpl implements MonitorService {
List<Configmap> configmaps = params.stream().map(param ->
new Configmap(param.getField(), param.getValue(), param.getType())).collect(Collectors.toList());
appDefine.setConfigmap(configmaps);
// 探测可用性只需要采集优先级为0的可用性指标集合
List<Metrics> availableMetrics = appDefine.getMetrics().stream()
.filter(item -> item.getPriority() == 0).collect(Collectors.toList());
appDefine.setMetrics(availableMetrics);
List<CollectRep.MetricsData> collectRep = collectJobService.collectSyncJobData(appDefine);
// 判断探测结果 失败则抛出探测异常
if (collectRep == null || collectRep.isEmpty()) {
@@ -240,9 +236,6 @@ 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.");

View File

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

View File

@@ -4,8 +4,8 @@ category: custom
app: example
name:
zh-CN: 模拟应用类型
en-US: EXAMPLE
# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串, 3-map映射的json串
en-US: EXAMPLE APP
# 参数映射map. type是参数类型: 0-number数字, 1-string明文字符串, 2-secret加密字符串
# 强制固定必须参数 - host
configmap:
- key: host
@@ -16,8 +16,6 @@ configmap:
type: 1
- key: password
type: 2
- key: headers
type: 3
# 指标组列表
metrics:
# 第一个监控指标组 cpu
@@ -71,7 +69,7 @@ metrics:
ssl: false
# 请求头内容
headers:
^_^headers^_^: ^_^headers^_^
apiVersion: v1
# 请求参数内容
params:
param1: param1

View File

@@ -26,14 +26,6 @@ configmap:
type: 1
- key: payload
type: 1
- key: authType
type: 1
- key: headers
type: 3
- key: params
type: 3
- key: keyword
type: 1
# 指标组列表
metrics:
# 第一个监控指标组 cpu
@@ -48,9 +40,6 @@ metrics:
- field: responseTime
type: 0
unit: ms
- field: keyword
type: 0
unit: 次数
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# 当protocol为http协议时具体的采集配置
@@ -69,19 +58,12 @@ metrics:
# 请求头内容
headers:
content-type: ^_^contentType^_^
^_^headers^_^: ^_^headers^_^
# 请求参数内容
params:
^_^params^_^: ^_^params^_^
# 认证
authorization:
# 认证方式: Basic Auth, Digest Auth, Bearer Token
type: ^_^authType^_^
type: Basic Auth
basicAuthUsername: ^_^username^_^
basicAuthPassword: ^_^password^_^
digestAuthUsername: ^_^username^_^
digestAuthPassword: ^_^password^_^
# 响应数据解析方式: default-系统规则,jsonPath-jsonPath脚本,website-网站可用性指标监控
# todo xmlPath-xmlPath脚本,prometheus-Prometheus数据规则
parseType: website
keyword: ^_^keyword^_^
parseType: website

View File

@@ -2,7 +2,7 @@ category: service
app: fullsite
name:
zh-CN: 全站监控
en-US: SITE MAP
en-US: FULL WEBSITE MONITOR
configmap:
- key: host
type: 1

View File

@@ -16,8 +16,6 @@ configmap:
type: 1
- key: password
type: 2
- key: timeout
type: 0
# 指标组列表
metrics:
# 第一个监控指标组 basic
@@ -46,7 +44,6 @@ 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
@@ -68,26 +65,6 @@ metrics:
- field: context_switch
type: 0
unit: 个数
- field: usage
type: 0
unit: '%'
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- info
- cores
- interrupt
- load
- context_switch
- idle
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- info=info
- cores=cores
- interrupt=interrupt
- load=load
- context_switch=context_switch
- usage=100-idle
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
@@ -98,8 +75,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}';vmstat 1 1 | awk 'NR==3{print $15}'"
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
@@ -121,25 +97,6 @@ metrics:
- field: available
type: 0
unit: Mb
- field: usage
type: 0
unit: '%'
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- total
- used
- free
- buff_cache
- available
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- total=total
- used=used
- free=free
- buff_cache=buff_cache
- available=available
- usage=(used / total) * 100
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
@@ -150,7 +107,6 @@ 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
@@ -183,7 +139,6 @@ 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
@@ -193,7 +148,6 @@ metrics:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: interface_name
type: 1
instance: true
- field: receive_bytes
type: 0
unit: byte
@@ -210,38 +164,5 @@ 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
- name: disk_free
priority: 5
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: filesystem
type: 1
- field: used
type: 0
unit: Mb
- field: available
type: 0
unit: Mb
- field: usage
type: 0
unit: '%'
- field: mounted
type: 1
instance: true
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: df -m | tail -n +2 | awk 'BEGIN{ print "filesystem used available usage mounted"} {print $1,$3,$4,$5,$6}'
parseType: multiRow

View File

@@ -1,178 +0,0 @@
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: hostname
type: 1
- field: instance_name
type: 1
- field: startup_time
type: 1
- field: status
type: 1
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- VERSION
- HOST_NAME
- INSTANCE_NAME
- STARTUP_TIME
- STATUS
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- database_version=VERSION
- 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

@@ -115,7 +115,7 @@ metrics:
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: user_connection
- field: connection
type: 0
unit: 连接数
protocol: jdbc
@@ -132,5 +132,5 @@ metrics:
# 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';
sql: SELECT cntr_value as connection FROM sys.dm_os_performance_counters WHERE object_name = 'SQLServer:General Statistics' AND counter_name = 'User Connections';
url: ^_^url^_^

View File

@@ -0,0 +1,25 @@
category: service
app: telnet
name:
zh-CN: TELNET端口可用性
en-US: PORT TELNET
configmap:
- key: host
type: 1
- key: port
type: 0
- key: timeout
type: 0
metrics:
- name: summary
priority: 0
fields:
- field: responseTime
type: 0
unit: ms
protocol: telnet
# 当protocol为telnet协议时具体的采集配置
telnet:
host: ^_^host^_^
port: ^_^port^_^
timeout: ^_^timeout^_^

View File

@@ -2,7 +2,7 @@ category: service
app: website
name:
zh-CN: 网站监测
en-US: WEBSITE
en-US: WEBSITE MONITOR
configmap:
- key: host
type: 1
@@ -12,18 +12,10 @@ configmap:
type: 1
- key: ssl
type: 1
- key: authType
type: 1
- key: username
type: 1
- key: password
type: 2
- key: keyword
type: 1
# 指标组列表
metrics:
# 第一个监控指标组 cpu
# 注意:内置监控指标有 (responseTime - 响应时间, keyword - 关键字数量)
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: summary
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
@@ -34,9 +26,6 @@ metrics:
- field: responseTime
type: 0
unit: ms
- field: keyword
type: 0
unit: 次数
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: http
# 当protocol为http协议时具体的采集配置
@@ -51,14 +40,6 @@ 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
keyword: ^_^keyword^_^
parseType: website

View File

@@ -26,12 +26,10 @@ param:
# 当type为text时,用limit表示字符串限制大小
limit: 20
required: false
hide: true
- field: password
name: 密码
type: password
required: false
hide: true
- field: ssl
name: 启动SSL
# 当type为boolean时,前端用switch展示开关
@@ -50,10 +48,4 @@ param:
- label: PUT请求
value: PUT
- label: DELETE请求
value: DELETE
- field: headers
name: 请求Headers
type: key-value
required: false
keyAlias: Header Name
valueAlias: Header Value
value: DELETE

View File

@@ -17,6 +17,13 @@ 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
@@ -31,67 +38,28 @@ 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: headers
name: 请求Headers
type: key-value
required: false
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
placeholder: '请求BODY资源类型'
required: false
hide: true
- field: payload
name: 请求BODY
type: textarea
placeholder: 'POST PUT请求时有效'
required: false
hide: true
- field: authType
name: 认证方式
type: radio
required: false
hide: true
# 当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
hide: true
- field: password
name: 密码
type: password
required: false
hide: true
- field: keyword
name: 关键字
- field: contentType
name: Content-Type
type: text
placeholder: '请求BODY资源类型'
required: false
- field: payload
name: 请求BODY
type: textarea
placeholder: 'POST PUT请求时有效'
required: false
hide: true

View File

@@ -11,12 +11,6 @@ param:
required: true
defaultValue: 22
placeholder: '请输入端口'
- field: timeout
name: 超时时间
type: number
required: false
defaultValue: 6000
placeholder: '超时时间'
- field: username
name: 用户名
type: text
@@ -25,4 +19,4 @@ param:
- field: password
name: 密码
type: password
required: false
required: true

View File

@@ -15,9 +15,8 @@ param:
name: 查询超时时间
type: number
required: false
defaultValue: 6000
defaultValue: 3000
placeholder: '查询超时时间'
hide: true
- field: database
name: 数据库名称
type: text
@@ -34,5 +33,4 @@ param:
- field: url
name: URL
type: text
required: false
hide: true
required: false

View File

@@ -15,8 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
hide: true
defaultValue: 6000
defaultValue: 3000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
@@ -34,5 +33,4 @@ param:
- field: url
name: URL
type: text
required: false
hide: true
required: false

View File

@@ -1,38 +0,0 @@
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
hide: true
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
hide: true

View File

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

View File

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

View File

@@ -15,8 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
hide: true
defaultValue: 6000
defaultValue: 3000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
@@ -34,5 +33,4 @@ param:
- field: url
name: URL
type: text
required: false
hide: true
required: false

View File

@@ -15,8 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
hide: true
defaultValue: 6000
defaultValue: 3000
placeholder: '查询超时时间'
- field: database
name: 数据库名称
@@ -34,5 +33,4 @@ param:
- field: url
name: URL
type: text
required: false
hide: true
required: false

View File

@@ -0,0 +1,27 @@
# 监控应用类型名称(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: telnet
# 强制固定必须参数 - host(ipv4,ipv6,域名)
param:
# field-字段名称标识符
- field: host
# name-参数字段显示名称
name: 主机Host
# type-字段类型,样式(大部分映射input标签type属性)
type: host
# 是否是必输项 true-必填 false-可选
required: true
- field: port
name: 端口
type: number
# 当type为number时,用range表示范围
range: '[0,65535]'
required: true
defaultValue: 80
- field: timeout
name: Telnet超时时间
type: number
# 当type为number时,用range表示范围
range: '[0,100000]'
required: true
placeholder: '请输入超时时间,单位毫秒'
defaultValue: 3000

View File

@@ -28,32 +28,4 @@ param:
name: 启用HTTPS
# 当type为boolean时,前端用switch展示开关
type: boolean
required: true
- field: authType
name: 认证方式
type: radio
required: false
hide: true
# 当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
hide: true
- field: password
name: 密码
type: password
required: false
hide: true
- field: keyword
name: 关键字
type: text
required: false
hide: true
required: true

View File

@@ -27,8 +27,8 @@ spring:
on-profile: prod
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
username: admin
password: admin
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.7</id>
<id>1.0-beta.5</id>
<!--打包类型,可以设置多种类型,打包的时候不同的类型都会打包打出来-->
<formats>
<format>tar</format>

View File

@@ -28,7 +28,9 @@ if [ ! -d $LOGS_DIR ]; then
fi
# JVM Configuration
JAVA_MEM_OPTS=" -server -XX:SurvivorRatio=6 -XX:+UseParallelGC "
JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true "
JAVA_MEM_OPTS=" -server -Xms256m -Xmx1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
# 加载外部log文件的配置
LOG_IMPL_FILE=logback-spring.xml
@@ -39,4 +41,4 @@ then
fi
CONFIG_FILES=" -Dlogging.path=$LOGS_DIR $LOGGING_CONFIG -Dspring.config.location=$CONF_DIR/ "
echo -e "Starting the $SERVER_NAME ..."
java $JAVA_MEM_OPTS $CONFIG_FILES -jar $DEPLOY_DIR/$JAR_NAME --spring.profiles.active=prod
java $JAVA_OPTS $JAVA_MEM_OPTS $CONFIG_FILES -jar $DEPLOY_DIR/$JAR_NAME --spring.profiles.active=prod

View File

@@ -1,23 +0,0 @@
@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

@@ -1,56 +0,0 @@
@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= -Duser.timezone=Asia/Shanghai
set JAVA_MEM_OPTS= -server -XX:SurvivorRatio=6 -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

@@ -66,9 +66,9 @@ if [ ! -d $LOGS_DIR ]; then
fi
# JVM Configuration
JAVA_OPTS=" -Duser.timezone=Asia/Shanghai"
JAVA_OPTS=" -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Duser.timezone=Asia/Shanghai"
JAVA_MEM_OPTS=" -server -XX:SurvivorRatio=6 -XX:+UseParallelGC "
JAVA_MEM_OPTS=" -server -Xms256m -Xmx1024m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
# 加载外部log文件的配置
LOG_IMPL_FILE=logback-spring.xml

View File

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

View File

@@ -34,7 +34,7 @@ CREATE TABLE param
id bigint not null auto_increment comment '参数ID',
monitor_id bigint not null comment '监控ID',
field varchar(100) not null comment '参数标识符',
value varchar(8126) comment '参数值,最大字符长度8126',
value varchar(255) comment '参数值,最大字符长度255',
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
gmt_create timestamp default current_timestamp comment 'create time',
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',

View File

@@ -36,10 +36,10 @@ excludedResource:
# eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account:
- appId: admin
credential: admin
credential: admin@123.
role: [role1,role2]
- appId: tom
credential: tom
credential: tom@123.
role: [role1,role2,role3]
- appId: lili
# 注意 Digest认证不支持加盐加密的密码账户

View File

@@ -14,7 +14,7 @@ services:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
MYSQL_ROOT_PASSWORD: 1234
volumes:
- ./dbdata/mysqldata:/var/lib/mysql/
- ./conf/sql:/docker-entrypoint-initdb.d/
@@ -35,7 +35,7 @@ services:
- heartzbeat
hertzbeat:
image: "tancloud/hertzbeat:1.0-beta.7"
image: "tancloud/hertzbeat:1.0-beta.5"
container_name: hertzbeat
hostname: hertzbeat
restart: always

View File

@@ -2,7 +2,7 @@ FROM openjdk:8-alpine
MAINTAINER tomsun28 "tomsun28@outlook.com"
ADD hertzbeat-1.0-beta.7.tar /opt/
ADD hertzbeat-1.0-beta.5.tar /opt/
RUN apk add --no-cache tzdata

View File

@@ -34,7 +34,7 @@ CREATE TABLE param
id bigint not null auto_increment comment '参数ID',
monitor_id bigint not null comment '监控ID',
field varchar(100) not null comment '参数标识符',
value varchar(8126) comment '参数值,最大字符长度8126',
value varchar(255) comment '参数值,最大字符长度255',
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
gmt_create timestamp default current_timestamp comment 'create time',
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',

View File

@@ -23,7 +23,7 @@ excludedResource:
- /**/*.ttf===get
- /**/*.png===get
- /**/*.gif===get
- /**/*.png===*
- /**/*.png===*
# swagger ui 资源
- /swagger-resources/**===get
- /v2/api-docs===get

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 MiB

After

Width:  |  Height:  |  Size: 30 MiB

View File

@@ -61,11 +61,11 @@ public class TdEngineDataStorage implements DisposableBean {
log.error("init error, please config Warehouse TdEngine props in application.yml");
throw new IllegalArgumentException("please config Warehouse TdEngine props");
}
boolean success = initTdEngineDatasource(properties.getStore().getTdEngine());
startStorageData(success);
initTdEngineDatasource(properties.getStore().getTdEngine());
startStorageData();
}
private boolean initTdEngineDatasource(WarehouseProperties.StoreProperties.TdEngineProperties tdEngineProperties) {
private void initTdEngineDatasource(WarehouseProperties.StoreProperties.TdEngineProperties tdEngineProperties) {
HikariConfig config = new HikariConfig();
// jdbc properties
config.setJdbcUrl(tdEngineProperties.getUrl());
@@ -84,28 +84,16 @@ public class TdEngineDataStorage implements DisposableBean {
config.setIdleTimeout(0);
//validation query
config.setConnectionTestQuery("select server_status()");
try {
this.hikariDataSource = new HikariDataSource(config);
} catch (Exception e) {
log.error("\n\t------------------WARN WARN WARN------------------\n" +
"\t---------------Init TdEngine Failed---------------\n" +
"\t---------------Init TdEngine Failed---------------\n" +
"\t--------------Please Config Tdengine--------------\n" +
"\t----------Can Not Use Metric History Now----------\n" +
"\t----------Can Not Use Metric History Now----------\n" +
"\t----------Can Not Use Metric History Now----------\n");
return false;
}
return true;
this.hikariDataSource = new HikariDataSource(config);
}
private void startStorageData(boolean consume) {
private void startStorageData() {
Runnable runnable = () -> {
Thread.currentThread().setName("warehouse-tdEngine-data-storage");
while (!Thread.currentThread().isInterrupted()) {
try {
CollectRep.MetricsData metricsData = dataExporter.pollPersistentStorageMetricsData();
if (consume && metricsData != null) {
if (metricsData != null) {
saveData(metricsData);
}
} catch (InterruptedException e) {
@@ -195,7 +183,6 @@ public class TdEngineDataStorage implements DisposableBean {
String createTableSql = String.format(CREATE_SUPER_TABLE_SQL, superTable, fieldSqlBuilder);
try {
assert statement != null;
log.info("[tdengine-data]: create {} use sql: {}.", superTable, createTableSql);
statement.execute(createTableSql);
statement.execute(insertDataSql);
} catch (Exception createTableException) {
@@ -244,12 +231,6 @@ public class TdEngineDataStorage implements DisposableBean {
Connection connection = null;
Map<String, List<Value>> instanceValuesMap = new HashMap<>(8);
try {
if (hikariDataSource == null) {
log.error("\n\t---------------TdEngine Init Failed---------------\n" +
"\t--------------Please Config Tdengine--------------\n" +
"\t----------Can Not Use Metric History Now----------\n");
return instanceValuesMap;
}
connection = hikariDataSource.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(selectSql);

View File

@@ -71,9 +71,9 @@ import { environment } from '@env/environment';
<setting-drawer *ngIf="showSettingDrawer"></setting-drawer>
<theme-btn
[types]="[
{ key: 'default', text: 'app.theme.default' | i18n },
{ key: 'dark', text: 'app.theme.dark' | i18n },
{ key: 'compact', text: 'app.theme.compact' | i18n }
{ key: 'default', text: '浅色主题' },
{ key: 'dark', text: '深色主题' },
{ key: 'compact', text: '紧凑主题' }
]"
></theme-btn>
`

View File

@@ -1,6 +1,4 @@
import { ChangeDetectionStrategy, Component, HostListener, Inject } from '@angular/core';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN } from '@delon/theme';
import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
@@ -16,19 +14,15 @@ import { NzModalService } from 'ng-zorro-antd/modal';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class HeaderClearStorageComponent {
constructor(
private modalSrv: NzModalService,
private messageSrv: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {}
constructor(private modalSrv: NzModalService, private messageSrv: NzMessageService) {}
@HostListener('click')
_click(): void {
this.modalSrv.confirm({
nzTitle: this.i18nSvc.fanyi('common.confirm.clear-cache'),
nzTitle: '请确认是否清理缓存?',
nzOnOk: () => {
localStorage.clear();
this.messageSrv.success(this.i18nSvc.fanyi('common.notify.clear-success'));
this.messageSrv.success('清理成功!');
}
});
}

View File

@@ -26,11 +26,11 @@ import { AlertService } from '../../../service/alert.service';
export class HeaderNotifyComponent implements OnInit {
data: NoticeItem[] = [
{
title: this.i18nSvc.fanyi('dashboard.alerts.title-no'),
title: '近期未处理告警',
list: [],
emptyText: this.i18nSvc.fanyi('dashboard.alerts.no'),
emptyText: '暂无未处理告警',
emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
clearText: this.i18nSvc.fanyi('dashboard.alerts.enter')
clearText: '进入告警中心'
}
];
count = 0;
@@ -69,10 +69,10 @@ export class HeaderNotifyComponent implements OnInit {
let item = {
id: alert.id,
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png',
title: `${alert.monitorName}--${this.i18nSvc.fanyi(`alert.priority.${alert.priority}`)}`,
title: `监控-${alert.monitorName}-发出${this.i18nSvc.fanyi(`alert.priority.${alert.priority}`)}`,
datetime: alert.gmtCreate,
color: 'blue',
type: this.i18nSvc.fanyi('dashboard.alerts.title-no')
type: '近期未处理告警'
};
this.data[0].list.push(item);
});

View File

@@ -40,8 +40,8 @@ import { MonitorService } from '../../../service/monitor.service';
<nz-autocomplete nzBackfill="false" nzDefaultActiveFirstOption #auto>
<nz-auto-option *ngFor="let option of options" [nzValue]="option.id" [nzLabel]="option.name">
<a [routerLink]="['/monitors/' + option.id]">
{{ 'monitor.name' | i18n }} : {{ option.name }}
<span style="left:50% ; position: absolute;">{{ 'monitor.host' | i18n }} : {{ option.host }}</span>
监控名称: {{ option.name }}
<span style="left:50% ; position: absolute;">监控Host: {{ option.host }}</span>
<span style="right: 10px; position: absolute;"><i nz-icon nzType="arrow-right" nzTheme="outline"></i></span>
</a>
</nz-auto-option>

View File

@@ -6,15 +6,15 @@
<img class="logo" src="./assets/logo.svg" alt="" />
<span class="title">HertzBeat</span>
</div>
<div class="desc">{{ 'app.passport.desc' | i18n }}</div>
<div class="desc">TanCloud-易用友好的高性能监控云服务</div>
</div>
<router-outlet></router-outlet>
<global-footer [links]="links">
Copyright
<i nz-icon nzType="copyright" nzTheme="outline"></i>
2022
<a href="https://tancloud.cn" target="_blank">TanCloud tancloud.cn | </a>
<a href="https://hertzbeat.com" target="_blank">HertzBeat hertzbeat.com</a>
2021
<a href="https://tancloud.cn" target="_blank">探云 tancloud.cn | </a>
<a href="https://hertzbeat.com" target="_blank">赫兹跳动 hertzbeat.com</a>
</global-footer>
</div>
</div>

View File

@@ -1,7 +1,5 @@
import { Component, Inject, OnInit } from '@angular/core';
import { I18NService } from '@core';
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { ALAIN_I18N_TOKEN } from '@delon/theme';
@Component({
selector: 'layout-passport',
@@ -11,12 +9,12 @@ import { ALAIN_I18N_TOKEN } from '@delon/theme';
export class LayoutPassportComponent implements OnInit {
links = [
{
title: this.i18nSvc.fanyi('app.passport.welcome'),
title: '欢迎使用TanCloud探云-监控云服务-tancloud.cn',
href: 'https://tancloud.cn'
}
];
constructor(@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService, @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService) {}
constructor(@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
ngOnInit(): void {
this.tokenService.clear();

View File

@@ -9,9 +9,4 @@ export class ParamDefine {
limit: number | undefined;
//'[{"label":"GET请求","value":"GET"},{"label":"PUT请求","value":"PUT"}]'
options!: any[];
// 当type为key-value时有效,表示别名描述
keyAlias!: string;
valueAlias!: string;
// 此参数是否隐藏 即默认不显示, 在高级设置区显示
hide: boolean = false;
}

View File

@@ -3,12 +3,12 @@
<nz-breadcrumb-item>
<a [routerLink]="['/']">
<i nz-icon nzType="home"></i>
<span>{{ 'menu.dashboard' | i18n }}</span>
<span>仪表盘</span>
</a>
</nz-breadcrumb-item>
<nz-breadcrumb-item>
<i nz-icon nzType="alert"></i>
<span>{{ 'menu.alert.center' | i18n }}</span>
<span>告警中心</span>
</nz-breadcrumb-item>
</nz-breadcrumb>
<nz-divider></nz-divider>
@@ -16,28 +16,26 @@
<div>
<button nz-button nzType="primary" (click)="onDeleteAlerts()">
<i nz-icon nzType="delete" nzTheme="outline"></i>
{{ 'alert.center.delete' | i18n }}
删除告警
</button>
<button nz-button nzType="primary" (click)="onMarkReadAlerts()">
<i nz-icon nzType="down-circle" nzTheme="outline"></i>
{{ 'alert.center.deal' | i18n }}
标记已处理
</button>
<button nz-button nzType="primary" (click)="onMarkUnReadAlerts()">
<i nz-icon nzType="up-circle" nzTheme="outline"></i>
{{ 'alert.center.no-deal' | i18n }}
标记未处理
</button>
<button nz-button nzType="primary" (click)="sync()" nz-tooltip [nzTooltipTitle]="'common.refresh' | i18n">
<button nz-button nzType="primary" (click)="sync()" nz-tooltip nzTooltipTitle="刷新">
<i nz-icon nzType="sync" nzTheme="outline"></i>
</button>
<button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="onFilterSearchAlerts()">
{{ 'common.search' | i18n }}
</button>
<button style="margin-right: 25px; float: right" nz-button nzType="primary" (click)="onFilterSearchAlerts()"> 搜索 </button>
<input
style="margin-right: 5px; float: right; width: 150px; border-radius: 9px; text-align: center"
nz-input
type="text"
[placeholder]="'alert.center.search' | i18n"
placeholder="搜索告警内容"
nzSize="default"
(keyup.enter)="onFilterSearchAlerts()"
[(ngModel)]="filterContent"
@@ -45,24 +43,23 @@
<nz-select
style="margin-right: 10px; float: right; width: 120px"
nzAllowClear
[nzPlaceHolder]="'alert.center.filter-status' | i18n"
[nzPlaceHolder]="'告警状态过滤'"
[(ngModel)]="filterStatus"
>
<nz-option [nzLabel]="'alert.status.all' | i18n" nzValue="9"></nz-option>
<nz-option [nzLabel]="'alert.status.0' | i18n" nzValue="0"></nz-option>
<nz-option [nzLabel]="'alert.status.2' | i18n" nzValue="2"></nz-option>
<nz-option [nzLabel]="'alert.status.3' | i18n" nzValue="3"></nz-option>
<nz-option nzLabel="全部状态" nzValue="9"></nz-option>
<nz-option nzLabel="未处理" nzValue="0"></nz-option>
<nz-option nzLabel="已处理" nzValue="3"></nz-option>
</nz-select>
<nz-select
style="margin-right: 10px; float: right; width: 120px"
nzAllowClear
[nzPlaceHolder]="'alert.center.filter-priority' | i18n"
[nzPlaceHolder]="'告警级别过滤'"
[(ngModel)]="filterPriority"
>
<nz-option [nzLabel]="'alert.priority.all' | i18n" nzValue="9"></nz-option>
<nz-option [nzLabel]="'alert.priority.2' | i18n" nzValue="2"></nz-option>
<nz-option [nzLabel]="'alert.priority.1' | i18n" nzValue="1"></nz-option>
<nz-option [nzLabel]="'alert.priority.0' | i18n" nzValue="0"></nz-option>
<nz-option nzLabel="全部级别" nzValue="9"></nz-option>
<nz-option nzLabel="警告级别" nzValue="2"></nz-option>
<nz-option nzLabel="严重级别" nzValue="1"></nz-option>
<nz-option nzLabel="紧急级别" nzValue="0"></nz-option>
</nz-select>
</div>
@@ -84,13 +81,13 @@
<thead>
<tr>
<th nzAlign="center" nzLeft nzWidth="4%" [(nzChecked)]="checkedAll" (nzCheckedChange)="onAllChecked($event)"></th>
<th nzAlign="center" nzLeft>{{ 'alert.center.target' | i18n }}</th>
<th nzAlign="center">{{ 'alert.center.monitor' | i18n }}</th>
<th nzAlign="center">{{ 'alert.center.priority' | i18n }}</th>
<th nzAlign="center">{{ 'alert.center.content' | i18n }}</th>
<th nzAlign="center">{{ 'alert.center.status' | i18n }}</th>
<th nzAlign="center">{{ 'alert.center.time' | i18n }}</th>
<th nzAlign="center">{{ 'common.edit' | i18n }}</th>
<th nzAlign="center" nzLeft>告警指标</th>
<th nzAlign="center">所属监控</th>
<th nzAlign="center">级别</th>
<th nzAlign="center">告警内容</th>
<th nzAlign="center">状态</th>
<th nzAlign="center">告警时间</th>
<th nzAlign="center">操作</th>
</tr>
</thead>
<tbody>
@@ -105,36 +102,30 @@
<td nzAlign="center">
<nz-tag *ngIf="data.priority == 0" nzColor="red">
<i nz-icon nzType="bell" nzTheme="outline"></i>
<span>{{ 'alert.priority.0' | i18n }}</span>
<span>紧急告警</span>
</nz-tag>
<nz-tag *ngIf="data.priority == 1" nzColor="orange">
<i nz-icon nzType="bell" nzTheme="outline"></i>
<span>{{ 'alert.priority.1' | i18n }}</span>
<span>严重告警</span>
</nz-tag>
<nz-tag *ngIf="data.priority == 2" nzColor="yellow">
<i nz-icon nzType="bell" nzTheme="outline"></i>
<span>{{ 'alert.priority.2' | i18n }}</span>
<span>警告告警</span>
</nz-tag>
</td>
<td nzAlign="center">{{ data.content }}</td>
<td nzAlign="center">
{{ 'alert.status.' + data.status | i18n }}
{{ data.status === 0 ? '未处理' : '已处理' }}
</td>
<td nzAlign="center">{{ data.gmtCreate | date: 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center">
<button nz-button nzType="primary" (click)="onDeleteOneAlert(data.id)" nz-tooltip [nzTooltipTitle]="'alert.center.delete' | i18n">
<button nz-button nzType="primary" (click)="onDeleteOneAlert(data.id)" nz-tooltip nzTooltipTitle="删除告警">
<i nz-icon nzType="delete" nzTheme="outline"></i>
</button>
<button nz-button nzType="primary" (click)="onMarkReadOneAlert(data.id)" nz-tooltip [nzTooltipTitle]="'alert.center.deal' | i18n">
<button nz-button nzType="primary" (click)="onMarkReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记已处理">
<i nz-icon nzType="down-circle" nzTheme="outline"></i>
</button>
<button
nz-button
nzType="primary"
(click)="onMarkUnReadOneAlert(data.id)"
nz-tooltip
[nzTooltipTitle]="'alert.center.no-deal' | i18n"
>
<button nz-button nzType="primary" (click)="onMarkUnReadOneAlert(data.id)" nz-tooltip nzTooltipTitle="标记未处理">
<i nz-icon nzType="up-circle" nzTheme="outline"></i>
</button>
</td>
@@ -142,4 +133,4 @@
</tbody>
</nz-table>
<ng-template #rangeTemplate> {{ 'common.total' | i18n }} {{ total }} </ng-template>
<ng-template #rangeTemplate> 总量 {{ total }} </ng-template>

View File

@@ -1,6 +1,4 @@
import { Component, Inject, OnInit } from '@angular/core';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN } from '@delon/theme';
import { Component, OnInit } from '@angular/core';
import { NzModalService } from 'ng-zorro-antd/modal';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { NzTableQueryParams } from 'ng-zorro-antd/table';
@@ -14,12 +12,7 @@ import { AlertService } from '../../../service/alert.service';
styles: []
})
export class AlertCenterComponent implements OnInit {
constructor(
private notifySvc: NzNotificationService,
private modal: NzModalService,
private alertSvc: AlertService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService
) {}
constructor(private notifySvc: NzNotificationService, private modal: NzModalService, private alertSvc: AlertService) {}
pageIndex: number = 1;
pageSize: number = 8;
@@ -94,13 +87,13 @@ export class AlertCenterComponent implements OnInit {
onDeleteAlerts() {
if (this.checkedAlertIds == null || this.checkedAlertIds.size === 0) {
this.notifySvc.warning(this.i18nSvc.fanyi('alert.center.notify.no-delete'), '');
this.notifySvc.warning('未选中任何待删除项!', '');
return;
}
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('alert.center.confirm.delete-batch'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否批量删除!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.deleteAlerts(this.checkedAlertIds)
@@ -109,13 +102,13 @@ export class AlertCenterComponent implements OnInit {
onMarkReadAlerts() {
if (this.checkedAlertIds == null || this.checkedAlertIds.size === 0) {
this.notifySvc.warning(this.i18nSvc.fanyi('alert.center.notify.no-mark'), '');
this.notifySvc.warning('未选中任何待标记项!', '');
return;
}
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('alert.center.confirm.mark-done-batch'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否批量标记已处理!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.updateAlertsStatus(this.checkedAlertIds, 3)
@@ -123,13 +116,13 @@ export class AlertCenterComponent implements OnInit {
}
onMarkUnReadAlerts() {
if (this.checkedAlertIds == null || this.checkedAlertIds.size === 0) {
this.notifySvc.warning(this.i18nSvc.fanyi('alert.center.notify.no-mark'), '');
this.notifySvc.warning('未选中任何待标记项!', '');
return;
}
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('alert.center.confirm.mark-no-batch'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否批量标记未处理!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.updateAlertsStatus(this.checkedAlertIds, 0)
@@ -140,9 +133,9 @@ export class AlertCenterComponent implements OnInit {
let alerts = new Set<number>();
alerts.add(alertId);
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('common.confirm.delete'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否删除!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.deleteAlerts(alerts)
@@ -153,9 +146,9 @@ export class AlertCenterComponent implements OnInit {
let alerts = new Set<number>();
alerts.add(alertId);
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('alert.center.confirm.mark-done'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否标记已处理!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.updateAlertsStatus(alerts, 3)
@@ -166,9 +159,9 @@ export class AlertCenterComponent implements OnInit {
let alerts = new Set<number>();
alerts.add(alertId);
this.modal.confirm({
nzTitle: this.i18nSvc.fanyi('alert.center.confirm.mark-no'),
nzOkText: this.i18nSvc.fanyi('common.button.ok'),
nzCancelText: this.i18nSvc.fanyi('common.button.cancel'),
nzTitle: '请确认是否标记未处理!',
nzOkText: '确定',
nzCancelText: '取消',
nzOkDanger: true,
nzOkType: 'primary',
nzOnOk: () => this.updateAlertsStatus(alerts, 0)
@@ -181,17 +174,17 @@ export class AlertCenterComponent implements OnInit {
message => {
deleteAlerts$.unsubscribe();
if (message.code === 0) {
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.delete-success'), '');
this.notifySvc.success('删除成功!', '');
this.loadAlertsTable();
} else {
this.tableLoading = false;
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.delete-fail'), message.msg);
this.notifySvc.error('删除失败!', message.msg);
}
},
error => {
this.tableLoading = false;
deleteAlerts$.unsubscribe();
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.delete-fail'), error.msg);
this.notifySvc.error('删除失败!', error.msg);
}
);
}
@@ -202,17 +195,17 @@ export class AlertCenterComponent implements OnInit {
message => {
markAlertsStatus$.unsubscribe();
if (message.code === 0) {
this.notifySvc.success(this.i18nSvc.fanyi('common.notify.mark-success'), '');
this.notifySvc.success('标记成功!', '');
this.loadAlertsTable();
} else {
this.tableLoading = false;
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.mark-fail'), message.msg);
this.notifySvc.error('标记失败!', message.msg);
}
},
error => {
this.tableLoading = false;
markAlertsStatus$.unsubscribe();
this.notifySvc.error(this.i18nSvc.fanyi('common.notify.mark-fail'), error.msg);
this.notifySvc.error('标记失败!', error.msg);
}
);
}

View File

@@ -3,14 +3,14 @@
<nz-breadcrumb-item>
<a [routerLink]="['/']">
<i nz-icon nzType="home"></i>
<span>{{ 'menu.dashboard' | i18n }}</span>
<span>仪表盘</span>
</a>
</nz-breadcrumb-item>
<nz-breadcrumb-item>
<i nz-icon nzType="alert"></i>
<span>{{ 'menu.alert.dispatch' | i18n }}</span>
<span>告警通知配置</span>
<a href="https://tancloud.cn/docs/help/alert_email" target="_blank" style="float: right; margin-right: 5%">
<span>{{ 'common.button.help' | i18n }}&nbsp;</span>
<span>帮助&nbsp;</span>
<i nz-icon nzType="question-circle" nzTheme="outline"></i>
</a>
</nz-breadcrumb-item>
@@ -18,12 +18,12 @@
<nz-divider></nz-divider>
<nz-tabset nzSize="large">
<nz-tab [nzTitle]="'alert.notice.receiver' | i18n">
<nz-tab nzTitle="告警接收人">
<button nz-button nzType="primary" (click)="onNewNoticeReceiver()">
<i nz-icon nzType="appstore-add" nzTheme="outline"></i>
{{ 'alert.notice.receiver.new' | i18n }}
新增接收人
</button>
<button nz-button nzType="primary" (click)="syncReceiver()" nz-tooltip [nzTooltipTitle]="'common.refresh' | i18n">
<button nz-button nzType="primary" (click)="syncReceiver()" nz-tooltip nzTooltipTitle="刷新">
<i nz-icon nzType="sync" nzTheme="outline"></i>
</button>
<nz-table
@@ -35,11 +35,11 @@
>
<thead>
<tr>
<th nzAlign="center" nzWidth="10%">{{ 'alert.notice.receiver.people' | i18n }}</th>
<th nzAlign="center" nzWidth="20%">{{ 'alert.notice.receiver.type' | i18n }}</th>
<th nzAlign="center" nzWidth="20%">{{ 'alert.notice.receiver.setting' | i18n }}</th>
<th nzAlign="center" nzWidth="20%">{{ 'common.edit-time' | i18n }}</th>
<th nzAlign="center" nzWidth="30%">{{ 'common.edit' | i18n }}</th>
<th nzAlign="center" nzWidth="10%">接收人</th>
<th nzAlign="center" nzWidth="20%">通知方式</th>
<th nzAlign="center" nzWidth="20%">配置</th>
<th nzAlign="center" nzWidth="20%">最新修改时间</th>
<th nzAlign="center" nzWidth="30%">操作</th>
</tr>
</thead>
<tbody>
@@ -50,11 +50,11 @@
<td nzAlign="center">
<nz-tag *ngIf="data.type == 0" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.sms' | i18n }}</span>
<span>短信</span>
</nz-tag>
<nz-tag *ngIf="data.type == 1" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.email' | i18n }}</span>
<span>邮件</span>
</nz-tag>
<nz-tag *ngIf="data.type == 2" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
@@ -62,19 +62,19 @@
</nz-tag>
<nz-tag *ngIf="data.type == 3" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.wechat' | i18n }}</span>
<span>微信公众号</span>
</nz-tag>
<nz-tag *ngIf="data.type == 4" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.wework' | i18n }}</span>
<span>企业微信机器人</span>
</nz-tag>
<nz-tag *ngIf="data.type == 5" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.ding' | i18n }}</span>
<span>钉钉机器人</span>
</nz-tag>
<nz-tag *ngIf="data.type == 6" nzColor="orange">
<i nz-icon nzType="notification" nzTheme="outline"></i>
<span>{{ 'alert.notice.type.fei-shu' | i18n }}</span>
<span>飞书机器人</span>
</nz-tag>
</td>
<td nzAlign="center">
@@ -88,22 +88,10 @@
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | date: 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center">
<button
nz-button
nzType="primary"
(click)="onEditOneNoticeReceiver(data)"
nz-tooltip
[nzTooltipTitle]="'alert.notice.receiver.edit' | i18n"
>
<button nz-button nzType="primary" (click)="onEditOneNoticeReceiver(data)" nz-tooltip nzTooltipTitle="修改接收人">
<i nz-icon nzType="edit" nzTheme="outline"></i>
</button>
<button
nz-button
nzType="primary"
(click)="onDeleteOneNoticeReceiver(data.id)"
nz-tooltip
[nzTooltipTitle]="'alert.notice.receiver.delete' | i18n"
>
<button nz-button nzType="primary" (click)="onDeleteOneNoticeReceiver(data.id)" nz-tooltip nzTooltipTitle="删除接收人">
<i nz-icon nzType="delete" nzTheme="outline"></i>
</button>
</td>
@@ -111,12 +99,12 @@
</tbody>
</nz-table>
</nz-tab>
<nz-tab [nzTitle]="'alert.notice.rule' | i18n">
<nz-tab nzTitle="告警通知策略">
<button nz-button nzType="primary" (click)="onNewNoticeRule()">
<i nz-icon nzType="appstore-add" nzTheme="outline"></i>
{{ 'alert.notice.rule.new' | i18n }}
新增通知策略
</button>
<button nz-button nzType="primary" (click)="syncRule()" nz-tooltip [nzTooltipTitle]="'common.refresh' | i18n">
<button nz-button nzType="primary" (click)="syncRule()" nz-tooltip nzTooltipTitle="刷新">
<i nz-icon nzType="sync" nzTheme="outline"></i>
</button>
<nz-table
@@ -128,12 +116,12 @@
>
<thead>
<tr>
<th nzAlign="center" nzWidth="15%">{{ 'alert.notice.rule.name' | i18n }}</th>
<th nzAlign="center" nzWidth="12%">{{ 'alert.notice.receiver.people' | i18n }}</th>
<th nzAlign="center" nzWidth="12%">{{ 'alert.notice.rule.all' | i18n }}</th>
<th nzAlign="center" nzWidth="15%">{{ 'alert.notice.rule.enable' | i18n }}</th>
<th nzAlign="center" nzWidth="15%">{{ 'common.edit-time' | i18n }}</th>
<th nzAlign="center" nzWidth="25%">{{ 'common.edit' | i18n }}</th>
<th nzAlign="center" nzWidth="15%">策略名称</th>
<th nzAlign="center" nzWidth="12%">接收人</th>
<th nzAlign="center" nzWidth="12%">转发所有</th>
<th nzAlign="center" nzWidth="15%">是否启用</th>
<th nzAlign="center" nzWidth="15%">最新修改时间</th>
<th nzAlign="center" nzWidth="25%">操作</th>
</tr>
</thead>
<tbody>
@@ -146,38 +134,26 @@
</td>
<td nzAlign="center">
<nz-tag *ngIf="data.filterAll" nzColor="green">
<span>{{ 'common.yes' | i18n }}</span>
<span></span>
</nz-tag>
<nz-tag *ngIf="!data.filterAll" nzColor="orange">
<span>{{ 'common.no' | i18n }}</span>
<span></span>
</nz-tag>
</td>
<td nzAlign="center">
<nz-tag *ngIf="data.enable" nzColor="green">
<span>{{ 'common.enable' | i18n }}</span>
<span>开启</span>
</nz-tag>
<nz-tag *ngIf="!data.enable" nzColor="orange">
<span>{{ 'common.disable' | i18n }}</span>
<span>关闭</span>
</nz-tag>
</td>
<td nzAlign="center">{{ (data.gmtUpdate ? data.gmtUpdate : data.gmtCreate) | date: 'YYYY-MM-dd HH:mm:ss' }}</td>
<td nzAlign="center">
<button
nz-button
nzType="primary"
(click)="onEditOneNoticeRule(data)"
nz-tooltip
[nzTooltipTitle]="'alert.notice.rule.edit' | i18n"
>
<button nz-button nzType="primary" (click)="onEditOneNoticeRule(data)" nz-tooltip nzTooltipTitle="修改告警策略">
<i nz-icon nzType="edit" nzTheme="outline"></i>
</button>
<button
nz-button
nzType="primary"
(click)="onDeleteOneNoticeRule(data.id)"
nz-tooltip
[nzTooltipTitle]="'alert.notice.rule.delete' | i18n"
>
<button nz-button nzType="primary" (click)="onDeleteOneNoticeRule(data.id)" nz-tooltip nzTooltipTitle="删除告警策略">
<i nz-icon nzType="delete" nzTheme="outline"></i>
</button>
</td>
@@ -190,7 +166,7 @@
<!-- 新增或修改通知接收人弹出框 -->
<nz-modal
[(nzVisible)]="isManageReceiverModalVisible"
[nzTitle]="isManageReceiverModalAdd ? ('alert.notice.receiver.new' | i18n) : ('alert.notice.receiver.edit' | i18n)"
[nzTitle]="isManageReceiverModalAdd ? '新增接收人' : '修改接收人'"
(nzOnCancel)="onManageReceiverModalCancel()"
(nzOnOk)="onManageReceiverModalOk()"
nzMaskClosable="false"
@@ -200,27 +176,27 @@
<div *nzModalContent class="-inner-content">
<form nz-form #receiverForm="ngForm">
<nz-form-item>
<nz-form-label [nzSpan]="7" nzFor="name" nzRequired="true">{{ 'alert.notice.receiver.people.name' | i18n }}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="name" nzRequired="true">接收人名称</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.name" nz-input required name="name" type="text" id="name" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="type">{{ 'alert.notice.receiver.type' | i18n }} </nz-form-label>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="type">通知方式 </nz-form-label>
<nz-form-control nzSpan="12" [nzErrorTip]="'validation.required' | i18n">
<nz-select [(ngModel)]="receiver.type" nzPlaceHolder="Choose" required name="type" id="type">
<nz-option [nzValue]="0" nzDisabled [nzLabel]="'alert.notice.type.sms' | i18n"></nz-option>
<nz-option [nzValue]="1" [nzLabel]="'alert.notice.type.email' | i18n"></nz-option>
<nz-option [nzValue]="0" nzDisabled nzLabel="短信"></nz-option>
<nz-option [nzValue]="1" nzLabel="邮箱"></nz-option>
<nz-option [nzValue]="2" nzLabel="WebHook"></nz-option>
<nz-option [nzValue]="3" nzDisabled [nzLabel]="'alert.notice.type.wechat' | i18n"></nz-option>
<nz-option [nzValue]="4" [nzLabel]="'alert.notice.type.wework' | i18n"></nz-option>
<nz-option [nzValue]="5" [nzLabel]="'alert.notice.type.ding' | i18n"></nz-option>
<nz-option [nzValue]="6" [nzLabel]="'alert.notice.type.fei-shu' | i18n"></nz-option>
<nz-option [nzValue]="3" nzDisabled nzLabel="微信公众号"></nz-option>
<nz-option [nzValue]="4" nzLabel="企业微信机器人"></nz-option>
<nz-option [nzValue]="5" nzLabel="钉钉机器人"></nz-option>
<nz-option [nzValue]="6" nzLabel="飞书机器人"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 0">
<nz-form-label [nzSpan]="7" nzFor="phone" [nzRequired]="receiver.type === 0">{{ 'alert.notice.type.phone' | i18n }}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="phone" [nzRequired]="receiver.type === 0">手机号</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.phone.invalid' | i18n">
<input
[(ngModel)]="receiver.phone"
@@ -234,45 +210,37 @@
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 1">
<nz-form-label [nzSpan]="7" nzFor="email" [nzRequired]="receiver.type === 1">{{ 'alert.notice.type.email' | i18n }}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="email" [nzRequired]="receiver.type === 1">邮箱</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.email.invalid' | i18n">
<input [(ngModel)]="receiver.email" nz-input [required]="receiver.type === 1" email name="email" type="email" id="email" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 2">
<nz-form-label [nzSpan]="7" nzFor="hookUrl" [nzRequired]="receiver.type === 2">{{ 'alert.notice.type.url' | i18n }}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="hookUrl" [nzRequired]="receiver.type === 2">URL地址</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.hookUrl" nz-input [required]="receiver.type === 2" name="hookUrl" type="url" id="hookUrl" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 3">
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 3">{{
'alert.notice.type.wechat-id' | i18n
}}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 3">微信OPENID</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.wechatId" nz-input [required]="receiver.type === 3" name="wechatId" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 4">
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 4">{{
'alert.notice.type.wework-key' | i18n
}}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 4">企业微信机器人KEY</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.wechatId" nz-input [required]="receiver.type === 4" name="wechatId" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 5">
<nz-form-label [nzSpan]="7" nzFor="accessToken" [nzRequired]="receiver.type === 5">{{
'alert.notice.type.access-token' | i18n
}}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="accessToken" [nzRequired]="receiver.type === 5">机器人ACCESS_TOKEN</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.accessToken" nz-input [required]="receiver.type === 5" name="accessToken" type="text" />
</nz-form-control>
</nz-form-item>
<nz-form-item *ngIf="receiver.type === 6">
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 6">{{
'alert.notice.type.fei-shu-key' | i18n
}}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="wechatId" [nzRequired]="receiver.type === 6">飞书机器人KEY</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="receiver.wechatId" nz-input [required]="receiver.type === 6" name="wechatId" type="text" />
</nz-form-control>
@@ -284,7 +252,7 @@
<!-- 新增或修改通知策略弹出框 -->
<nz-modal
[(nzVisible)]="isManageRuleModalVisible"
[nzTitle]="isManageRuleModalAdd ? ('alert.notice.rule.new' | i18n) : ('alert.notice.rule.edit' | i18n)"
[nzTitle]="isManageRuleModalAdd ? '新增策略' : '修改策略'"
(nzOnCancel)="onManageRuleModalCancel()"
(nzOnOk)="onManageRuleModalOk()"
nzMaskClosable="false"
@@ -294,19 +262,19 @@
<div *nzModalContent class="-inner-content">
<form nz-form #ruleForm="ngForm">
<nz-form-item>
<nz-form-label [nzSpan]="7" nzFor="rule_name" nzRequired="true">{{ 'alert.notice.rule.name' | i18n }}</nz-form-label>
<nz-form-label [nzSpan]="7" nzFor="rule_name" nzRequired="true">策略名称</nz-form-label>
<nz-form-control [nzSpan]="8" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="rule.name" nz-input required name="rule_name" type="text" id="rule_name" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="filterAll">{{ 'alert.notice.rule.all' | i18n }}</nz-form-label>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="filterAll">转发所有</nz-form-label>
<nz-form-control nzSpan="8">
<nz-switch [(ngModel)]="rule.filterAll" disabled name="filterAll" id="filterAll"></nz-switch>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="receiver">{{ 'alert.notice.receiver.people' | i18n }}</nz-form-label>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="receiver">接收人</nz-form-label>
<nz-form-control nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
<nz-select
[(ngModel)]="rule.receiverId"
@@ -323,7 +291,7 @@
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="enable">{{ 'alert.notice.rule.enable' | i18n }}</nz-form-label>
<nz-form-label nzSpan="7" nzRequired="true" nzFor="enable">是否启用</nz-form-label>
<nz-form-control nzSpan="8">
<nz-switch [(ngModel)]="rule.enable" name="enable" id="enable"></nz-switch>
</nz-form-control>

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