Compare commits

...

2 Commits

Author SHA1 Message Date
tomsun28
a9e6b73852 [manager]feature: support ubuntu linux and centos linux monitoring 2022-04-16 21:56:17 +08:00
会编程的王学长
7c54bf0203 feature:Add alarm template custom console and help document (#93)
* feat: [manager,alerter,home]feature:Add alarm template custom console and help document #wqh

* Update common/src/main/java/com/usthe/common/util/CommonConstants.java

Co-authored-by: tomsun28 <tomsun28@outlook.com>

Co-authored-by: tomsun28 <tomsun28@outlook.com>
2022-04-16 10:34:20 +08:00
10 changed files with 614 additions and 12 deletions

View File

@@ -1,10 +1,12 @@
package com.usthe.alert;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 数据仓储配置属性
*
* @author tom
* @date 2021/11/24 10:38
*/
@@ -12,11 +14,22 @@ import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "alerter")
public class AlerterProperties {
private String consoleUrl = "https://console.tancloud.cn";
public String getConsoleUrl() {
return consoleUrl;
}
public void setConsoleUrl(String url) {
this.consoleUrl = url;
}
/**
* 数据入口配置属性
*/
private EntranceProperties entrance;
public EntranceProperties getEntrance() {
return entrance;
}
@@ -25,6 +38,7 @@ public class AlerterProperties {
this.entrance = entrance;
}
/**
* 数据入口配置属性
* 入口可以是从kafka rabbitmq rocketmq等消息中间件获取数据
@@ -98,4 +112,5 @@ public class AlerterProperties {
}
}

View File

@@ -0,0 +1,18 @@
---
id: alert_console
title: 告警模板中自定义的控制台地址
sidebar_label: 告警模板登录台地址
---
> 阈值触发后发送告警信息,通过钉钉/企业微信/飞书机器人通知或者使用邮箱通知的时候,告警内容中有登录控制台的详情链接
### 自定义设置
在我们的启动配置文件application.yml中找到下面的配置
```yml
alerter:
console-url: #这里就是我们的自定义控制台地址
```
默认值是赫兹跳动的官方控制台地址

View File

@@ -1,6 +1,7 @@
package com.usthe.manager.component.alerter;
import com.usthe.alert.AlerterDataQueue;
import com.usthe.alert.AlerterProperties;
import com.usthe.alert.AlerterWorkerPool;
import com.usthe.common.util.CommonUtil;
import com.usthe.common.entity.alerter.Alert;
@@ -24,6 +25,7 @@ import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.util.ArrayList;
import java.util.Date;
@@ -48,6 +50,8 @@ public class DispatchAlarm {
private JavaMailSender javaMailSender;
private RestTemplate restTemplate;
private MailService mailService;
@Resource
private AlerterProperties alerterProperties;
@Value("${spring.mail.username}")
private String emailFromUser;
@@ -177,13 +181,13 @@ public class DispatchAlarm {
"\n所属监控ID :" + alert.getMonitorId() +
"\n所属监控名称 :" + alert.getMonitorName() +
"\n告警级别 :" + CommonUtil.transferAlertPriority(alert.getPriority()) +
"\n内容详情 : " + alert.getContent();
"\n内容详情 : " + alert.getContent() + "\n";
flyBookContent.setText(text);
contents1.add(flyBookContent);
FlyBookWebHookDto.FlyBookContent bookContent = new FlyBookWebHookDto.FlyBookContent();
bookContent.setTag("a");
bookContent.setText("登入控制台");
bookContent.setHref("https://www.tancloud.cn");
bookContent.setHref(alerterProperties.getConsoleUrl());
contents1.add(bookContent);
contents.add(contents1);
zhCn.setTitle("[TanCloud探云告警通知]");
@@ -214,14 +218,16 @@ public class DispatchAlarm {
private void sendDingTalkRobotAlert(NoticeReceiver receiver, Alert alert) {
DingTalkWebHookDto dingTalkWebHookDto = new DingTalkWebHookDto();
DingTalkWebHookDto.MarkdownDTO markdownDTO = new DingTalkWebHookDto.MarkdownDTO();
String content = "#### [TanCloud探云告警通知]\n##### **告警目标对象** : " +
StringBuilder content = new StringBuilder();
content.append("#### [TanCloud探云告警通知]\n##### **告警目标对象** : " +
alert.getTarget() + "\n " +
"##### **所属监控ID** : " + alert.getMonitorId() + "\n " +
"##### **所属监控名称** : " + alert.getMonitorName() + "\n " +
"##### **告警级别** : " +
CommonUtil.transferAlertPriority(alert.getPriority()) + "\n " +
"##### **内容详情** : " + alert.getContent();
markdownDTO.setText(content);
"##### **内容详情** : " + alert.getContent());
content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")");
markdownDTO.setText(content.toString());
markdownDTO.setTitle("TanCloud探云告警通知");
dingTalkWebHookDto.setMarkdown(markdownDTO);
String webHookUrl = DingTalkWebHookDto.WEBHOOK_URL + receiver.getAccessToken();
@@ -261,8 +267,10 @@ public class DispatchAlarm {
content.append("告警级别 : <font color=\"comment\">")
.append(CommonUtil.transferAlertPriority(alert.getPriority())).append("</font>\n");
}
content.append("内容详情 : ").append(alert.getContent());
content.append("内容详情 : ").append(alert.getContent() + "\n");
content.append("[点击跳转查看详情](" + alerterProperties.getConsoleUrl() + ")");
markdownDTO.setContent(content.toString());
//TODO 增加控制台地址登录可控制
weWorkWebHookDTO.setMarkdown(markdownDTO);
String webHookUrl = WeWorkWebHookDto.WEBHOOK_URL + receiver.getWechatId();
try {

View File

@@ -1,5 +1,6 @@
package com.usthe.manager.service.impl;
import com.usthe.alert.AlerterProperties;
import com.usthe.common.entity.alerter.Alert;
import com.usthe.common.util.CommonUtil;
import com.usthe.manager.service.MailService;
@@ -11,6 +12,7 @@ import org.thymeleaf.context.Context;
import javax.annotation.Resource;
/**
* Mailbox sending service interface implementation class
* 邮箱发送服务接口实现类
*
* @author 花城
@@ -23,16 +25,20 @@ public class MailServiceImpl implements MailService {
@Resource
private TemplateEngine templateEngine;
@Resource
private AlerterProperties alerterProperties;
@Override
public String buildAlertHtmlTemplate(final Alert alert) {
// Introduce thymeleaf context parameters to render pages
// 引入thymeleaf上下文参数渲染页面
Context context = new Context();
context.setVariable("target",alert.getTarget());
context.setVariable("monitorId",alert.getMonitorId());
context.setVariable("monitorName",alert.getMonitorName());
context.setVariable("target", alert.getTarget());
context.setVariable("monitorId", alert.getMonitorId());
context.setVariable("monitorName", alert.getMonitorName());
context.setVariable("priority", CommonUtil.transferAlertPriority(alert.getPriority()));
context.setVariable("content",alert.getContent());
context.setVariable("content", alert.getContent());
context.setVariable("consoleUrl", alerterProperties.getConsoleUrl());
return templateEngine.process("mailAlarm", context);
}
}

View File

@@ -68,4 +68,9 @@ warehouse:
driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
url: jdbc:TAOS-RS://localhost:6041/hertzbeat
username: root
password: taosdata
password: taosdata
#自定义告警控制台地址
alerter:
#这里就是我们的自定义控制台地址
console-url: https://console.tancloud.cn

View File

@@ -0,0 +1,247 @@
# 此监控类型所属类别service-应用服务监控 db-数据库监控 custom-自定义监控 os-操作系统监控
category: os
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: centos
name:
zh-CN: Centos Linux
en-US: Centos Linux
# 参数映射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: timeout
type: 0
# 指标组列表
metrics:
# 第一个监控指标组 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: basic
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
priority: 0
# 指标组中的具体监控指标
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: hostname
type: 1
instance: true
- field: version
type: 1
- field: uptime
type: 1
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
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
- name: cpu
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: info
type: 1
- field: cores
type: 0
unit: 核数
- field: interrupt
type: 0
unit: 个数
- field: load
type: 1
- field: context_switch
type: 0
unit: 个数
- 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协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
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}'"
parseType: oneRow
- name: memory
priority: 2
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: total
type: 0
unit: Mb
- field: used
type: 0
unit: Mb
- field: free
type: 0
unit: Mb
- field: buff_cache
type: 0
unit: Mb
- field: available
type: 0
unit: Mb
- 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协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
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
- name: disk
priority: 3
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: disk_num
type: 0
unit: 块数
- field: partition_num
type: 0
unit: 分区数
- field: block_write
type: 0
unit: 块数
- field: block_read
type: 0
unit: 块数
- field: write_rate
type: 0
unit: iops
# 监控采集使用协议 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: 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
- name: interface
priority: 4
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: interface_name
type: 1
instance: true
- field: receive_bytes
type: 0
unit: byte
- field: transmit_bytes
type: 0
unit: byte
# 监控采集使用协议 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: 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

@@ -0,0 +1,247 @@
# 此监控类型所属类别service-应用服务监控 db-数据库监控 custom-自定义监控 os-操作系统监控
category: os
# 监控应用类型(与文件名保持一致) eg: linux windows tomcat mysql aws...
app: ubuntu
name:
zh-CN: Ubuntu Linux
en-US: Ubuntu Linux
# 参数映射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: timeout
type: 0
# 指标组列表
metrics:
# 第一个监控指标组 basic
# 注意:内置监控指标有 (responseTime - 响应时间)
- name: basic
# 指标组调度优先级(0-127)越小优先级越高,优先级低的指标组会等优先级高的指标组采集完成后才会被调度,相同优先级的指标组会并行调度采集
# 优先级为0的指标组为可用性指标组,即它会被首先调度,采集成功才会继续调度其它指标组,采集失败则中断调度
priority: 0
# 指标组中的具体监控指标
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: hostname
type: 1
instance: true
- field: version
type: 1
- field: uptime
type: 1
# 监控采集使用协议 eg: sql, ssh, http, telnet, wmi, snmp, sdk
protocol: ssh
# 当protocol为http协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
port: ^_^port^_^
username: ^_^username^_^
password: ^_^password^_^
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
- name: cpu
priority: 1
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: info
type: 1
- field: cores
type: 0
unit: 核数
- field: interrupt
type: 0
unit: 个数
- field: load
type: 1
- field: context_switch
type: 0
unit: 个数
- 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协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
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}'"
parseType: oneRow
- name: memory
priority: 2
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: total
type: 0
unit: Mb
- field: used
type: 0
unit: Mb
- field: free
type: 0
unit: Mb
- field: buff_cache
type: 0
unit: Mb
- field: available
type: 0
unit: Mb
- 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协议时具体的采集配置
ssh:
# 主机host: ipv4 ipv6 域名
host: ^_^host^_^
# 端口
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
- name: disk
priority: 3
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: disk_num
type: 0
unit: 块数
- field: partition_num
type: 0
unit: 分区数
- field: block_write
type: 0
unit: 块数
- field: block_read
type: 0
unit: 块数
- field: write_rate
type: 0
unit: iops
# 监控采集使用协议 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: 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
- name: interface
priority: 4
fields:
# 指标信息 包括 field名称 type字段类型:0-number数字,1-string字符串 instance是否为实例主键 unit:指标单位
- field: interface_name
type: 1
instance: true
- field: receive_bytes
type: 0
unit: byte
- field: transmit_bytes
type: 0
unit: byte
# 监控采集使用协议 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: 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

@@ -0,0 +1,28 @@
app: centos
param:
- field: host
name: 主机Host
type: host
required: true
- field: port
name: 端口
type: number
range: '[0,65535]'
required: true
defaultValue: 22
placeholder: '请输入端口'
- field: timeout
name: 超时时间
type: number
required: false
defaultValue: 6000
placeholder: '超时时间'
- field: username
name: 用户名
type: text
limit: 20
required: true
- field: password
name: 密码
type: password
required: false

View File

@@ -0,0 +1,28 @@
app: ubuntu
param:
- field: host
name: 主机Host
type: host
required: true
- field: port
name: 端口
type: number
range: '[0,65535]'
required: true
defaultValue: 22
placeholder: '请输入端口'
- field: timeout
name: 超时时间
type: number
required: false
defaultValue: 6000
placeholder: '超时时间'
- field: username
name: 用户名
type: text
limit: 20
required: true
- field: password
name: 密码
type: password
required: false

View File

@@ -700,7 +700,7 @@
<span style="font-family:Arial, Verdana; font-size:14px;color:#FFFFFF;"><a
target="_blank"
style="color:#FFFFFF;text-decoration:none;"
href="https://console.tancloud.cn"
th:href="${consoleUrl}"
data-link-type="web">登入控制台</a></span>
</td>
</tr>