Compare commits

..

11 Commits

Author SHA1 Message Date
tomsun28
0df234483d [monitor]feature:param yml support key-value map 2022-04-03 21:29:14 +08:00
tomsun28
0cf66f32ff [manager,collector]feature 修改默认超时时间3000毫秒为6000毫秒 (#55) 2022-04-02 23:02:37 +08:00
tomsun28
fbf7ebd834 feature 检测网站SSL证书是否过期 (#50)
* [collector]feature 检测网站SSL证书是否过期

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

View File

@@ -76,7 +76,7 @@
##### 安装TDengine
1. docker安装TDengine
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
`docker run -d -p 6030-6049:6030-6049 -p 6030-6049:6030-6049/tcp -p 6030-6049:6030-6049/udp --name tdengine tdengine/tdengine:2.4.0.12`
2. 创建名称为hertzbeat的数据库
详细步骤参考 [依赖服务TDengine安装初始化](https://hertzbeat.com/docs/start/tdengine-init)
@@ -138,7 +138,8 @@ HertzBeat赫兹跳动为 [Dromara开源社区](https://dromara.org/) 孵化项
##### 赞助
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com)赞助服务器采集节点
感谢[吉实信息(构建全新的微波+光交易网络)](https://www.flarespeed.com) 赞助服务器采集节点
感谢[天上云计算(全新智慧上云)](https://www.tsyvps.com/aff/BZBEGYLX) 赞助服务器采集节点
## 🛡️ License
[`Apache License, Version 2.0`](https://www.apache.org/licenses/LICENSE-2.0.html)

View File

@@ -109,12 +109,11 @@
<artifactId>mssql-jdbc</artifactId>
<version>10.2.0.jre8</version>
</dependency>
<!-- oracle -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.5.0.0</version>
</dependency>
</dependencies>

View File

@@ -17,7 +17,9 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
@@ -75,7 +77,18 @@ public class CommonHttpClient {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
// 判断服务器证书有效期时间
Date now = new Date();
if (x509Certificates != null && x509Certificates.length > 0) {
for (X509Certificate certificate : x509Certificates) {
Date deadline = certificate.getNotAfter();
if (deadline != null && now.after(deadline)) {
throw new CertificateExpiredException();
}
}
}
}
@Override
public X509Certificate[] getAcceptedIssuers() { return null; }
};

View File

@@ -2,6 +2,9 @@ package com.usthe.collector.collect.common.ssh;
import lombok.extern.slf4j.Slf4j;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
import org.apache.sshd.common.PropertyResolverUtils;
import org.apache.sshd.core.CoreModuleProperties;
/**
* ssh公共client
@@ -16,6 +19,14 @@ public class CommonSshClient {
static {
sshClient = SshClient.setUpDefaultClient();
// 接受所有服务端公钥校验会打印warn日志 Server at {} presented unverified {} key: {}
AcceptAllServerKeyVerifier verifier = AcceptAllServerKeyVerifier.INSTANCE;
sshClient.setServerKeyVerifier(verifier);
// 设置链接保活心跳10000毫秒一次, 客户端等待保活心跳超时响应时间3000毫秒
PropertyResolverUtils.updateProperty(
sshClient, CoreModuleProperties.HEARTBEAT_INTERVAL.getName(), 10000);
PropertyResolverUtils.updateProperty(
sshClient, CoreModuleProperties.HEARTBEAT_REPLY_WAIT.getName(), 3000);
sshClient.start();
}

View File

@@ -52,8 +52,8 @@ public class JdbcCommonCollect extends AbstractCollect {
}
JdbcProtocol jdbcProtocol = metrics.getJdbc();
String databaseUrl = constructDatabaseUrl(jdbcProtocol);
// 查询超时时间默认3000毫秒
int timeout = 3000;
// 查询超时时间默认6000毫秒
int timeout = 6000;
try {
// 获取查询语句超时时间
if (jdbcProtocol.getTimeout() != null) {

View File

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

View File

@@ -5,6 +5,7 @@ import com.usthe.collector.collect.common.cache.CacheIdentifier;
import com.usthe.collector.collect.common.cache.CommonCache;
import com.usthe.collector.collect.common.ssh.CommonSshClient;
import com.usthe.collector.util.CollectorConstants;
import com.usthe.collector.util.KeyPairUtil;
import com.usthe.common.entity.job.Metrics;
import com.usthe.common.entity.job.protocol.SshProtocol;
import com.usthe.common.entity.message.CollectRep;
@@ -19,6 +20,7 @@ import org.springframework.util.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -56,8 +58,8 @@ public class SshCollectImpl extends AbstractCollect {
return;
}
SshProtocol sshProtocol = metrics.getSsh();
// 超时时间默认300毫秒
int timeout = 3000;
// 超时时间默认6000毫秒
int timeout = 6000;
try {
timeout = Integer.parseInt(sshProtocol.getTimeout());
} catch (Exception e) {
@@ -181,6 +183,13 @@ public class SshCollectImpl extends AbstractCollect {
.verify(timeout, TimeUnit.MILLISECONDS).getSession();
if (StringUtils.hasText(sshProtocol.getPassword())) {
clientSession.addPasswordIdentity(sshProtocol.getPassword());
} else if (StringUtils.hasText(sshProtocol.getPublicKey())) {
KeyPair keyPair = KeyPairUtil.getKeyPairFromPublicKey(sshProtocol.getPublicKey());
if (keyPair != null) {
clientSession.addPublicKeyIdentity(keyPair);
}
} else {
throw new IllegalArgumentException("需填写账户登陆密码或公钥");
}
// 进行认证
if (!clientSession.auth().verify(timeout, TimeUnit.MILLISECONDS).isSuccess()) {

View File

@@ -38,8 +38,8 @@ public class TelnetCollectImpl extends AbstractCollect {
}
TelnetProtocol telnet = metrics.getTelnet();
// 超时时间默认300毫秒
int timeout = 300;
// 超时时间默认6000毫秒
int timeout = 6000;
try {
timeout = Integer.parseInt(telnet.getTimeout());
} catch (Exception e) {

View File

@@ -12,6 +12,7 @@ import com.usthe.common.entity.job.Job;
import com.usthe.common.entity.job.Metrics;
import com.usthe.common.util.AesUtil;
import com.usthe.common.util.CommonConstants;
import com.usthe.common.util.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
@@ -84,6 +85,26 @@ public class WheelTimerTask implements TimerTask {
while (iterator.hasNext()) {
Map.Entry<String, JsonElement> entry = iterator.next();
JsonElement element = entry.getValue();
String key = entry.getKey();
// 替换KEY-VALUE情况的属性 比如http headers params
if (key != null && key.startsWith("^_^") && key.endsWith("^_^")) {
key = key.replaceAll("\\^_\\^", "");
Configmap param = configmap.get(key);
if (param.getType() == (byte) 3) {
String jsonValue = (String) param.getValue();
Map<String, String> map = GsonUtil.fromJson(jsonValue, Map.class);
if (map != null) {
map.forEach((name, value) -> {
if (name != null && !"".equals(name.trim())) {
jsonObject.addProperty(name, value);
}
});
}
}
iterator.remove();
continue;
}
// 替换正常的VALUE值
if (element.isJsonPrimitive()) {
// 判断是否含有特殊字符 替换
String value = element.getAsString();

View File

@@ -0,0 +1,48 @@
package com.usthe.collector.util;
import lombok.extern.slf4j.Slf4j;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
* 密钥工具类
* @author tom
* @date 2022/4/2 17:04
*/
@Slf4j
public class KeyPairUtil {
private static KeyFactory keyFactory;
static {
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
/**
* 获取密钥对
*/
public static KeyPair getKeyPairFromPublicKey(String publicKeyStr) {
try {
if (publicKeyStr == null || "".equals(publicKeyStr)) {
return null;
}
// todo fix 公钥解析
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return new KeyPair(publicKey, null);
} catch (Exception e) {
log.info("[keyPair] parse failed, {}." + e.getMessage());
return null;
}
}
}

View File

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

View File

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

View File

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

View File

@@ -110,29 +110,41 @@ public class ParamDefine {
@Convert(converter = JsonOptionListAttributeConverter.class)
private List<Option> options;
/**
* 当type为key-value时有效,表示key的别名描述
*/
@ApiModelProperty(value = "当type为key-value时有效,表示key的别名描述", example = "Name", accessMode = READ_WRITE, position = 9)
private String keyAlias;
/**
* 当type为key-value时有效,表示value的别名描述
*/
@ApiModelProperty(value = "当type为key-value时有效,表示value的别名描述", example = "Value", accessMode = READ_WRITE, position = 10)
private String valueAlias;
/**
* 此条记录创建者
*/
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 9)
@ApiModelProperty(value = "此条记录创建者", example = "tom", accessMode = READ_ONLY, position = 11)
private String creator;
/**
* 此条记录最新修改者
*/
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 10)
@ApiModelProperty(value = "此条记录最新修改者", example = "tom", accessMode = READ_ONLY, position = 12)
private String modifier;
/**
* 记录创建时间
*/
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 11)
@ApiModelProperty(value = "记录创建时间(毫秒时间戳)", example = "1612198922000", accessMode = READ_ONLY, position = 13)
@Column(insertable = false, updatable = false)
private LocalDateTime gmtCreate;
/**
* 记录最新修改时间
*/
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 12)
@ApiModelProperty(value = "记录最新修改时间(毫秒时间戳)", example = "1612198444000", accessMode = READ_ONLY, position = 14)
@Column(insertable = false, updatable = false)
private LocalDateTime gmtUpdate;

View File

@@ -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)
[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)
### 操作系统监控

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

@@ -0,0 +1,62 @@
---
id: oracle
title: 监控ORACLE数据库监控
sidebar_label: ORACLE数据库
---
> 对ORACLE数据库的通用性能指标进行采集监控。
### 配置参数
| 参数名称 | 参数帮助描述 |
| ----------- | ----------- |
| 监控Host | 被监控的对端IPV4IPV6或域名。注意⚠不带协议头(eg: https://, http://)。 |
| 监控名称 | 标识此监控的名称,名称需要保证唯一性。 |
| 端口 | 数据库对外提供的端口默认为1521。 |
| 查询超时时间 | 设置SQL查询未响应数据时的超时时间单位ms毫秒默认3000毫秒。 |
| 数据库名称 | 数据库实例名称,可选。 |
| 用户名 | 数据库连接用户名,可选 |
| 密码 | 数据库连接密码,可选 |
| URL | 数据库连接URL可选若配置则URL里面的数据库名称用户名密码等参数会覆盖上面配置的参数 |
| 采集间隔 | 监控周期性采集数据间隔时间单位秒可设置的最小间隔为10秒 |
| 是否探测 | 新增监控前是否先探测检查监控可用性,探测成功才会继续新增修改操作 |
| 描述备注 | 更多标识和描述此监控的备注信息,用户可以在这里备注信息 |
### 采集指标
#### 指标集合basic
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| database_version | 无 | 数据库版本 |
| database_type | 无 | 数据库类型 |
| hostname | 无 | 主机名称 |
| instance_name | 无 | 数据库实例名称 |
| startup_time | 无 | 数据库启动时间 |
| status | 无 | 数据库状态 |
#### 指标集合tablespace
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| file_id | 无 | 文件ID |
| file_name | 无 | 文件名称 |
| tablespace_name | 无 | 所属表空间名称 |
| status | 无 | 状态 |
| bytes | MB | 大小 |
| blocks | 无 | 区块数量 |
#### 指标集合user_connect
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| username | 无 | 用户名 |
| counts | 个数 | 当前连接数量 |
#### 指标集合performance
| 指标名称 | 指标单位 | 指标帮助描述 |
| ----------- | ----------- | ----------- |
| qps | QPS | I/O Requests per Second 每秒IO请求数量 |
| tps | TPS | User Transaction Per Sec 每秒用户事物处理数量 |
| mbps | MBPS | I/O Megabytes per Second 每秒 I/O 兆字节数量 |

View File

@@ -44,9 +44,55 @@ sidebar_label: Docker方式部署
若需要新增删除修改账户或密码,可以通过配置 `sureness.yml` 实现,若无此需求可忽略此步骤
在主机目录下创建sureness.ymleg:/opt/sureness.yml
配置文件内容参考 项目仓库[/script/sureness.yml](https://gitee.com/dromara/hertzbeat/blob/master/script/sureness.yml)
修改sureness.yml的如下部分参数[注意⚠sureness配置的其它默认参数需保留]
```yaml
resourceRole:
- /account/auth/refresh===post===[role1,role2,role3,role4]
excludedResource:
- /account/auth/**===*
- /===get
- /i18n/**===get
- /apps/hierarchy===get
- /console/**===get
- /**/*.html===get
- /**/*.js===get
- /**/*.css===get
- /**/*.ico===get
- /**/*.ttf===get
- /**/*.png===get
- /**/*.gif===get
- /**/*.png===*
- /swagger-resources/**===get
- /v2/api-docs===get
- /v3/api-docs===get
# 用户账户信息
# 下面有 admin tom lili 三个账户
# eg: admin 拥有[role1,role2]角色,密码为admin
# eg: tom 拥有[role1,role2,role3],密码为tom@123
# eg: lili 拥有[role1,role2],明文密码为lili, 加盐密码为1A676730B0C7F54654B0E09184448289
account:
- appId: admin
credential: admin
role: [role1,role2]
- appId: tom
credential: tom@123
role: [role1,role2,role3]
- appId: lili
# 注意 Digest认证不支持加盐加密的密码账户
# 加盐加密的密码,通过 MD5(password+salt)计算
# 此账户的原始密码为 lili
credential: 1A676730B0C7F54654B0E09184448289
salt: 123
role: [role1,role2]
```
修改sureness.yml的如下**部分参数****[注意⚠sureness配置的其它默认参数需保留]**
```yaml
# 用户账户信息
# 下面有 admin tom lili 三个账户
# eg: admin 拥有[role1,role2]角色,密码为admin

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
# 用户账户信息

View File

@@ -65,7 +65,8 @@
"help/mysql",
"help/mariadb",
"help/postgresql",
"help/sqlserver"
"help/sqlserver",
"help/oracle"
]
},
{

View File

@@ -236,6 +236,9 @@ public class MonitorServiceImpl implements MonitorService {
case "checkbox":
// todo checkbox校验
break;
case "key-value":
// todo key-value校验
break;
// todo 更多参数定义与实际值格式校验
default:
throw new IllegalArgumentException("ParamDefine type " + paramDefine.getType() + " is invalid.");

View File

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

View File

@@ -16,6 +16,8 @@ configmap:
type: 1
- key: password
type: 2
- key: timeout
type: 0
# 指标组列表
metrics:
# 第一个监控指标组 basic
@@ -44,6 +46,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: (uname -r ; hostname ; uptime | awk -F "," '{print $1}' | sed "s/ //g") | sed ":a;N;s/\n/^/g;ta" | awk -F '^' 'BEGIN{print "version hostname uptime"} {print $1, $2, $3}'
# 响应数据解析方式oneRow, multiRow
parseType: multiRow
@@ -75,6 +78,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: "LANG=C lscpu | awk -F: '/Model name/ {print $2}';awk '/processor/{core++} END{print core}' /proc/cpuinfo;uptime | sed 's/,/ /g' | awk '{for(i=NF-2;i<=NF;i++)print $i }' | xargs;vmstat 1 1 | awk 'NR==3{print $11}';vmstat 1 1 | awk 'NR==3{print $12}'"
parseType: oneRow
@@ -107,6 +111,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: free -m | grep Mem | awk 'BEGIN{print "total used free buff_cache available"} {print $2,$3,$4,$6,$7}'
parseType: multiRow
@@ -139,6 +144,7 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: vmstat -D | awk 'NR==1{print $1}';vmstat -D | awk 'NR==2{print $1}';vmstat 1 1 | awk 'NR==3{print $10}';vmstat 1 1 | awk 'NR==3{print $9}';vmstat 1 1 | awk 'NR==3{print $16}'
parseType: oneRow
@@ -164,5 +170,6 @@ metrics:
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
timeout: ^_^timeout^_^
script: cat /proc/net/dev | tail -n +3 | awk 'BEGIN{ print "interface_name receive_bytes transmit_bytes"} {print $1,$2,$10}'
parseType: multiRow

View File

@@ -29,11 +29,141 @@ metrics:
# 指标组中的具体监控指标
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: DST_PRIMARY_TT_VERSION
- field: database_version
type: 1
instance: true
- field: NLS_RDBMS_VERSION
- field: database_type
type: 1
- field: hostname
type: 1
- field: instance_name
type: 1
- field: startup_time
type: 1
- field: status
type: 1
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- VERSION
- DATABASE_TYPE
- HOST_NAME
- INSTANCE_NAME
- STARTUP_TIME
- STATUS
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- database_version=VERSION
- database_type=DATABASE_TYPE
- hostname=HOST_NAME
- instance_name=INSTANCE_NAME
- startup_time=STARTUP_TIME
- status=STATUS
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: oracle
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: oneRow
# sql
sql: select * from sys.v_$instance
url: ^_^url^_^
- name: tablespace
priority: 1
# 指标组中的具体监控指标
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: file_id
type: 1
instance: true
- field: file_name
type: 1
- field: tablespace_name
type: 1
- field: status
type: 1
- field: bytes
type: 0
unit: MB
- field: blocks
type: 0
unit: 块数
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: oracle
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: oneRow
# sql
sql: select file_id, file_name, tablespace_name, status, bytes / 1024 / 1024 as bytes, blocks from dba_data_files
url: ^_^url^_^
- name: user_connect
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: username
type: 1
instance: true
- field: counts
type: 0
unit: 连接数
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
platform: oracle
username: ^_^username^_^
password: ^_^password^_^
database: ^_^database^_^
timeout: ^_^timeout^_^
# SQL查询方式 oneRow, multiRow, columns
queryType: oneRow
# sql
sql: SELECT username, count( username ) as counts FROM v$session WHERE username IS NOT NULL GROUP BY username
url: ^_^url^_^
- name: performance
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: qps
type: 0
unit: qps
- field: tps
type: 0
unit: tps
- field: mbps
type: 0
unit: mbps
# (非必须)监控指标别名,与上面的指标名映射。用于采集接口数据字段不直接是最终指标名称,需要此别名做映射转换
aliasFields:
- I/O Requests per Second
- User Transaction Per Sec
- I/O Megabytes per Second
# (非必须)指标计算表达式,与上面的别名一起作用,计算出最终需要的指标值
# eg: cores=core1+core2, usage=usage, waitTime=allTime-runningTime
calculates:
- qps=I/O Requests per Second
- tps=User Transaction Per Sec
- mbps=I/O Megabytes per Second
protocol: jdbc
jdbc:
# 主机host: ipv4 ipv6 域名
@@ -48,5 +178,5 @@ metrics:
# SQL查询方式 oneRow, multiRow, columns
queryType: columns
# sql
sql: select * from sys.props$
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

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

View File

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

View File

@@ -15,7 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
defaultValue: 3000
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称

View File

@@ -15,7 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
defaultValue: 3000
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称

View File

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

View File

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

View File

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

View File

@@ -15,7 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
defaultValue: 3000
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称

View File

@@ -15,7 +15,7 @@ param:
name: 查询超时时间
type: number
required: false
defaultValue: 3000
defaultValue: 6000
placeholder: '查询超时时间'
- field: database
name: 数据库名称

View File

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

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(255) comment '参数值,最大字符长度255',
value varchar(8126) comment '参数值,最大字符长度8126',
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
gmt_create timestamp default current_timestamp comment 'create time',
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',

View File

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

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(255) comment '参数值,最大字符长度255',
value varchar(8126) comment '参数值,最大字符长度8126',
type tinyint not null default 0 comment '参数类型 0:数字 1:字符串 2:加密串',
gmt_create timestamp default current_timestamp comment 'create time',
gmt_update datetime default current_timestamp on update current_timestamp comment 'update time',

View File

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

View File

@@ -9,4 +9,7 @@ export class ParamDefine {
limit: number | undefined;
//'[{"label":"GET请求","value":"GET"},{"label":"PUT请求","value":"PUT"}]'
options!: any[];
// 当type为key-value时有效,表示别名描述
keyAlias!: string;
valueAlias!: string;
}

View File

@@ -86,7 +86,7 @@
>{{ paramDefine.name }}
</nz-form-label>
<nz-form-control *ngIf="paramDefine.type === 'password'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
<nz-input-group [nzSuffix]="suffixTemplate">
<nz-input-group [nzSuffix]="suffixTemplate" style="width: 100%">
<input
[type]="passwordVisible ? 'text' : 'password'"
nz-input
@@ -147,6 +147,18 @@
</label>
</nz-radio-group>
</nz-form-control>
<nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
>{{ paramDefine.name }}
</nz-form-label>
<nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
<app-key-value-input
[(value)]="params[i].value"
[id]="paramDefine.field"
keyAlias="Header Name"
valueAlias="Header Value"
></app-key-value-input>
</nz-form-control>
</nz-form-item>
<nz-divider></nz-divider>

View File

@@ -78,7 +78,13 @@ export class MonitorEditComponent implements OnInit {
if (param === undefined) {
param = new Param();
param.field = define.field;
param.type = define.type === 'number' ? 0 : 1;
if (define.type === 'number') {
param.type = 0;
} else if (define.type === 'key-value') {
param.type = 3;
} else {
param.type = 1;
}
if (define.type === 'boolean') {
param.value = false;
}

View File

@@ -95,7 +95,7 @@
>{{ paramDefine.name }}
</nz-form-label>
<nz-form-control *ngIf="paramDefine.type === 'password'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
<nz-input-group [nzSuffix]="suffixTemplate">
<nz-input-group [nzSuffix]="suffixTemplate" style="width: 100%">
<input
[type]="passwordVisible ? 'text' : 'password'"
nz-input
@@ -156,6 +156,18 @@
</label>
</nz-radio-group>
</nz-form-control>
<nz-form-label *ngIf="paramDefine.type === 'key-value'" nzSpan="7" [nzRequired]="paramDefine.required" [nzFor]="paramDefine.field"
>{{ paramDefine.name }}
</nz-form-label>
<nz-form-control *ngIf="paramDefine.type === 'key-value'" nzSpan="8" [nzErrorTip]="'validation.required' | i18n">
<app-key-value-input
[(value)]="params[i].value"
[id]="paramDefine.field"
[keyAlias]="paramDefine.keyAlias ? paramDefine.keyAlias : 'Name'"
[valueAlias]="paramDefine.valueAlias ? paramDefine.valueAlias : 'Value'"
></app-key-value-input>
</nz-form-control>
</nz-form-item>
<nz-divider></nz-divider>

View File

@@ -58,7 +58,13 @@ export class MonitorNewComponent implements OnInit {
this.paramDefines.forEach(define => {
let param = new Param();
param.field = define.field;
param.type = define.type === 'number' ? 0 : 1;
if (define.type === 'number') {
param.type = 0;
} else if (define.type === 'key-value') {
param.type = 3;
} else {
param.type = 1;
}
if (define.type === 'boolean') {
param.value = false;
}

View File

@@ -1,2 +0,0 @@
### 公共通用小组件

View File

@@ -0,0 +1,12 @@
<div *ngFor="let item of keyValues; let i = index" nz-row>
<div nz-col nzSpan="10">
<input nz-input [placeholder]="keyAlias" [(ngModel)]="item.key" (ngModelChange)="onChange()" />
</div>
<div nz-col nzSpan="11">
<input nz-input [placeholder]="valueAlias" [(ngModel)]="item.value" (ngModelChange)="onChange()" />
</div>
<div nz-col nzSpan="3">
<i nz-icon nzType="plus-circle" class="dynamic-button" *ngIf="i === 0" (click)="addNew($event)"></i>
<i nz-icon nzType="minus-circle" class="dynamic-button" (click)="removeCurrent(i, $event)"></i>
</div>
</div>

View File

@@ -0,0 +1,12 @@
.dynamic-button {
cursor: pointer;
position: relative;
top: 4px;
font-size: 15px;
transition: all 0.3s;
margin-left: 6%;
}
.dynamic-button:hover {
font-size: 26px;
}

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { KeyValueInputComponent } from './key-value-input.component';
describe('KeyValueInputComponent', () => {
let component: KeyValueInputComponent;
let fixture: ComponentFixture<KeyValueInputComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ KeyValueInputComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(KeyValueInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,63 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-key-value-input',
templateUrl: './key-value-input.component.html',
styleUrls: ['./key-value-input.component.less']
})
export class KeyValueInputComponent implements OnInit {
constructor() {}
@Input() value!: any;
@Output() readonly valueChange = new EventEmitter<string>();
@Input()
keyAlias: string = 'Key';
@Input()
valueAlias: string = 'Value';
keyValues: any[] = [];
ngOnInit(): void {
if (this.value == undefined) {
this.value = {
'': ''
};
} else {
this.value = JSON.parse(this.value);
}
Object.keys(this.value).map(item => {
this.keyValues.push({
key: item,
value: this.value[item]
});
});
}
addNew(e?: MouseEvent) {
if (e) {
e.preventDefault();
}
this.keyValues.push({
key: '',
value: ''
});
}
removeCurrent(index: number, e?: MouseEvent) {
if (e) {
e.preventDefault();
}
if (this.keyValues.length > 1) {
this.keyValues.splice(index, 1);
}
}
onChange() {
this.value = {};
this.keyValues.forEach(item => {
if (item != null && item.key != null) {
this.value[item.key] = item.value;
}
});
this.valueChange.emit(JSON.stringify(this.value));
}
}

View File

@@ -6,6 +6,7 @@ import { DelonACLModule } from '@delon/acl';
import { DelonFormModule } from '@delon/form';
import { AlainThemeModule } from '@delon/theme';
import { KeyValueInputComponent } from './components/key-value-input/key-value-input.component';
import { TimezonePipe } from './pipe/timezone.pipe';
import { SHARED_DELON_MODULES } from './shared-delon.module';
import { SHARED_ZORRO_MODULES } from './shared-zorro.module';
@@ -18,7 +19,7 @@ const THIRDMODULES: Array<Type<void>> = [];
// #region your components & directives
const COMPONENTS: Array<Type<void>> = [];
const COMPONENTS: Array<Type<void>> = [KeyValueInputComponent];
const DIRECTIVES: Array<Type<void>> = [TimezonePipe];
// #endregion