mirror of
https://github.com//cppla/ServerStatus
synced 2025-06-01 21:29:50 +08:00
Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
830938eac9 | ||
|
1a764ed104 | ||
|
b0c543b44b | ||
|
f85c0a87f9 | ||
|
67d7c5ea0f | ||
|
8576f81404 | ||
|
fa0ee2bf57 | ||
|
e9776b0e69 | ||
|
e01cc118dc | ||
|
784c40b153 | ||
|
6068a2ba17 | ||
|
ced526824f | ||
|
7d2a73bf2e | ||
|
51e2f664cd | ||
|
937b1ea90f | ||
|
b95d1945bf | ||
|
e8446cd52f | ||
|
6098f0fb1a | ||
|
fc89a76cc2 | ||
|
f290947b2c | ||
|
b3adc6b782 | ||
|
705a957606 | ||
|
a307ad7d19 | ||
|
ad95e00723 | ||
|
31330168f3 | ||
|
d9e8f8a7c1 | ||
|
08f15ebdc5 | ||
|
adb05818b9 | ||
|
4e73e8185e | ||
|
0fe01064a4 | ||
|
510567eaec | ||
|
503037c7e2 | ||
|
d75d5438a3 | ||
|
91f11dad76 | ||
|
fdc5abacfc | ||
|
388938e02b | ||
|
f912794068 | ||
|
5ebf076330 |
10
Dockerfile
10
Dockerfile
@ -1,7 +1,7 @@
|
||||
# The Dockerfile for build localhost source, not git repo
|
||||
FROM debian:buster as builder
|
||||
FROM debian:buster AS builder
|
||||
|
||||
MAINTAINER cppla https://cpp.la
|
||||
LABEL maintainer="cppla <https://cpp.la>"
|
||||
|
||||
RUN apt-get update -y && apt-get -y install gcc g++ make libcurl4-openssl-dev
|
||||
|
||||
@ -15,7 +15,7 @@ RUN pwd && ls -a
|
||||
# glibc env run
|
||||
FROM nginx:latest
|
||||
|
||||
RUN mkdir -p /ServerStatus/server/
|
||||
RUN mkdir -p /ServerStatus/server/ && ln -sf /dev/null /var/log/nginx/access.log && ln -sf /dev/null /var/log/nginx/error.log
|
||||
|
||||
COPY --from=builder server /ServerStatus/server/
|
||||
COPY --from=builder web /usr/share/nginx/html/
|
||||
@ -25,5 +25,5 @@ ENV TZ=Asia/Shanghai
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
EXPOSE 80 35601
|
||||
|
||||
CMD nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'
|
||||
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:80 || bash -c 'kill -s 15 -1 && (sleep 10; kill -s 9 -1)'
|
||||
CMD ["sh", "-c", "/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html"]
|
53
README.md
53
README.md
@ -1,17 +1,16 @@
|
||||
# ServerStatus中文版:
|
||||
|
||||
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
|
||||
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。。
|
||||
* 在线演示:https://tz.cloudcpp.com
|
||||
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
[](https://github.com/cppla/ServerStatus)
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
`Watchdog触发式告警,interval只是为了防止频繁收到报警信息造成的骚扰,并不是探测间隔。 同时为了防止海外机器闪断报警,也加入username、name、type等静态字符串参数的计算支持。值得注意的是,Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,等待修复。 `
|
||||
`Watchdog触发式告警,interval只是为了防止频繁收到报警信息造成的骚扰,并不是探测间隔。值得注意的是,Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,等待修复。 `
|
||||
|
||||
# 目录:
|
||||
|
||||
@ -70,12 +69,12 @@ cd ServerStatus/server && make
|
||||
```diff
|
||||
! watchdog rule 可以为任何已知字段的表达式。注意Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,等待修复
|
||||
! watchdog interval 最小通知间隔
|
||||
! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调
|
||||
! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调
|
||||
|
||||
! watchdog callback Telegram: https://api.telegram.org/bot你自己的密钥/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=你自己的标识&text=
|
||||
! watchdog callback Server酱: https://sctapi.ftqq.com/你自己的密钥.send?title=ServerStatus&desp=
|
||||
! watchdog callback PushDeer: https://api2.pushdeer.com/message/push?pushkey=你自己的密钥&text=
|
||||
! watchdog callback BasicAuth: https://用户名:密码@你自己的域名/api/push?message=
|
||||
! Telegram: https://api.telegram.org/bot你自己的密钥/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=你自己的标识&text=
|
||||
! Server酱: https://sctapi.ftqq.com/你自己的密钥.send?title=ServerStatus&desp=
|
||||
! PushDeer: https://api2.pushdeer.com/message/push?pushkey=你自己的密钥&text=
|
||||
! HttpBasicAuth: https://用户名:密码@你自己的域名/api/push?message=
|
||||
```
|
||||
|
||||
```
|
||||
@ -94,10 +93,16 @@ cd ServerStatus/server && make
|
||||
],
|
||||
"monitors": [
|
||||
{
|
||||
"name": "监测网站以及MySQL、Redis,默认为七天在线率",
|
||||
"name": "监测网站,默认为一天在线率",
|
||||
"host": "https://www.baidu.com",
|
||||
"interval": 60,
|
||||
"interval": 1200,
|
||||
"type": "https"
|
||||
},
|
||||
{
|
||||
"name": "监测tcp服务端口",
|
||||
"host": "1.1.1.1:80",
|
||||
"interval": 1200,
|
||||
"type": "tcp"
|
||||
}
|
||||
],
|
||||
"watchdog":
|
||||
@ -109,20 +114,20 @@ cd ServerStatus/server && make
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器内存使用率过高监控",
|
||||
"rule": "(memory_used/memory_total)*100>90",
|
||||
"name": "服务器内存使用率过高监控,排除小于1G的机器",
|
||||
"rule": "(memory_used/memory_total)*100>90&memory_total>1048576",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "服务器宕机告警,排出node1,排除s02",
|
||||
"rule": "online4=0&online6=0&name!='node1'&username!='s02'",
|
||||
"name": "服务器宕机告警",
|
||||
"rule": "online4=0&online6=0",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "DDOS和CC攻击监控",
|
||||
"rule": "tcp_count>600",
|
||||
"name": "DDOS和CC攻击监控,限制甲骨文机器",
|
||||
"rule": "tcp_count>600&type='Oracle'",
|
||||
"interval": 300,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
@ -132,6 +137,18 @@ cd ServerStatus/server && make
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "阿里云服务器流量18GB告警,限制username为乌兰察布",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>18&(username='wlcb1'|username='wlcb2'|username='wlcb3'|username='wlcb4')",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "重要线路丢包率过高检查",
|
||||
"rule": "(ping_10010>10|ping_189>10|ping_10086>10)&(host='sgp'|host='qqhk'|host='hk-21-x'|host='hk-31-x')",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "你可以组合任何已知字段的表达式",
|
||||
"rule": "(hdd_used/hdd_total)*100>95",
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Update by : https://github.com/cppla/ServerStatus, Update date: 20220530
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# 支持操作系统: Linux, OSX, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# ONLINE_PACKET_HISTORY_LEN, 探测间隔120s,记录24小时在线率(720);探测时间300s,记录24小时(288);探测间隔60s,记录7天(10080)
|
||||
# ONLINE_PACKET_HISTORY_LEN, 探测间隔1200s,记录24小时在线率(72);探测时间300s,记录24小时(288);探测间隔60s,记录7天(10080)
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
@ -18,7 +18,7 @@ CM = "cm.tz.cloudcpp.com"
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
ONLINE_PACKET_HISTORY_LEN = 288
|
||||
ONLINE_PACKET_HISTORY_LEN = 72
|
||||
INTERVAL = 1
|
||||
|
||||
import socket
|
||||
|
@ -4,7 +4,7 @@
|
||||
# 依赖于psutil跨平台库
|
||||
# 版本:1.0.3, 支持Python版本:2.7 to 3.10
|
||||
# 支持操作系统: Linux, Windows, OSX, Sun Solaris, FreeBSD, OpenBSD and NetBSD, both 32-bit and 64-bit architectures
|
||||
# ONLINE_PACKET_HISTORY_LEN, 探测间隔120s,记录24小时在线率(720);探测时间300s,记录24小时(288);探测间隔60s,记录7天(10080)
|
||||
# ONLINE_PACKET_HISTORY_LEN, 探测间隔1200s,记录24小时在线率(72);探测时间300s,记录24小时(288);探测间隔60s,记录7天(10080)
|
||||
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。
|
||||
|
||||
SERVER = "127.0.0.1"
|
||||
@ -19,7 +19,7 @@ CM = "cm.tz.cloudcpp.com"
|
||||
PROBEPORT = 80
|
||||
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
|
||||
PING_PACKET_HISTORY_LEN = 100
|
||||
ONLINE_PACKET_HISTORY_LEN = 288
|
||||
ONLINE_PACKET_HISTORY_LEN = 72
|
||||
INTERVAL = 1
|
||||
|
||||
import socket
|
||||
|
@ -5,6 +5,11 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: serverstatus_server
|
||||
healthcheck:
|
||||
test: curl --fail http://localhost:80 || bash -c 'kill -s 15 -1 && (sleep 10; kill -s 9 -1)'
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
container_name: serverstatus
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
@ -19,7 +24,6 @@ services:
|
||||
|
||||
networks:
|
||||
serverstatus-network:
|
||||
name: serverstatus-network
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/24
|
||||
|
@ -42,19 +42,13 @@
|
||||
{
|
||||
"name": "baidu",
|
||||
"host": "https://www.baidu.com",
|
||||
"interval": 300,
|
||||
"interval": 1200,
|
||||
"type": "https"
|
||||
},
|
||||
{
|
||||
"name": "aliyun",
|
||||
"host": "https://www.aliyun.com",
|
||||
"interval": 300,
|
||||
"type": "https"
|
||||
},
|
||||
{
|
||||
"name": "114",
|
||||
"host": "114.114.114.114:53",
|
||||
"interval": 300,
|
||||
"name": "1111",
|
||||
"host": "1.1.1.1:80",
|
||||
"interval": 1200,
|
||||
"type": "tcp"
|
||||
}
|
||||
],
|
||||
@ -72,8 +66,8 @@
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "offline warning,exclude name node1",
|
||||
"rule": "online4=0&online6=0&name!='node1'",
|
||||
"name": "offline warning",
|
||||
"rule": "online4=0&online6=0",
|
||||
"interval": 600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
@ -84,11 +78,23 @@
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "month traffic warning",
|
||||
"name": "month 999GB traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "aliyun china free 18GB traffic warning",
|
||||
"rule": "(network_out-last_network_out)/1024/1024/1024>18&(username='aliyun1'|username='aliyun2')",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "packet loss rate warning",
|
||||
"rule": "(ping_10010>10|ping_189>10|ping_10086>10)&(host='sgp'|host='qqhk'|host='hk-21-x'|host='hk-31-x')",
|
||||
"interval": 3600,
|
||||
"callback": "https://yourSMSurl"
|
||||
},
|
||||
{
|
||||
"name": "you can parse an expression combining any known field",
|
||||
"rule": "load_5>3",
|
||||
|
13419
server/src/exprtk.hpp
13419
server/src/exprtk.hpp
File diff suppressed because it is too large
Load Diff
@ -110,13 +110,6 @@ void CMain::OnDelClient(int ClientNetID)
|
||||
{
|
||||
int ClientID = ClientNetToClient(ClientNetID);
|
||||
dbg_msg("main", "OnDelClient(ncid=%d, cid=%d)", ClientNetID, ClientID);
|
||||
//copy offline message for watchdog
|
||||
WatchdogMessage(ClientNetID,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0,0, 0, 0,
|
||||
0, 0, 0, 0);
|
||||
if(ClientID >= 0 && ClientID < NET_MAX_CLIENTS)
|
||||
{
|
||||
Client(ClientID)->m_Connected = false;
|
||||
@ -124,6 +117,10 @@ void CMain::OnDelClient(int ClientNetID)
|
||||
Client(ClientID)->m_ClientNetType = NETTYPE_INVALID;
|
||||
mem_zero(&Client(ClientID)->m_Stats, sizeof(CClient::CStats));
|
||||
}
|
||||
m_OfflineAlarmThreadData.pClients = m_aClients;
|
||||
m_OfflineAlarmThreadData.pWatchDogs = m_aCWatchDogs;
|
||||
m_OfflineAlarmThreadData.m_ReloadRequired = ClientID;
|
||||
thread_create(offlineAlarmThread, &m_OfflineAlarmThreadData);
|
||||
}
|
||||
|
||||
int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
@ -219,7 +216,8 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
pClient->m_Stats.m_time_10010, pClient->m_Stats.m_time_189, pClient->m_Stats.m_time_10086,
|
||||
pClient->m_Stats.m_tcpCount, pClient->m_Stats.m_udpCount, pClient->m_Stats.m_processCount,
|
||||
pClient->m_Stats.m_threadCount, pClient->m_Stats.m_NetworkRx, pClient->m_Stats.m_NetworkTx,
|
||||
pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT,pClient->m_Stats.m_MemTotal,
|
||||
pClient->m_Stats.m_NetworkIN, pClient->m_Stats.m_NetworkOUT,
|
||||
pClient->m_LastNetworkIN, pClient->m_LastNetworkOUT, pClient->m_Stats.m_MemTotal,
|
||||
pClient->m_Stats.m_MemUsed, pClient->m_Stats.m_SwapTotal, pClient->m_Stats.m_SwapUsed,
|
||||
pClient->m_Stats.m_HDDTotal, pClient->m_Stats.m_HDDUsed, pClient->m_Stats.m_IORead,
|
||||
pClient->m_Stats.m_IOWrite, pClient->m_Stats.m_CPU, pClient->m_Stats.m_Online4,
|
||||
@ -271,7 +269,7 @@ int CMain::HandleMessage(int ClientNetID, char *pMessage)
|
||||
|
||||
void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out, double memory_total, double memory_used,
|
||||
double network_rx, double network_tx, double network_in, double network_out, double last_network_in, double last_network_out, double memory_total, double memory_used,
|
||||
double swap_total, double swap_used, double hdd_total, double hdd_used, double io_read, double io_write, double cpu,
|
||||
double online4, double online6)
|
||||
{
|
||||
@ -329,6 +327,8 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
|
||||
symbol_table.add_variable("network_tx",network_tx);
|
||||
symbol_table.add_variable("network_in",network_in);
|
||||
symbol_table.add_variable("network_out",network_out);
|
||||
symbol_table.add_variable("last_network_in",last_network_in);
|
||||
symbol_table.add_variable("last_network_out",last_network_out);
|
||||
symbol_table.add_variable("memory_total",memory_total);
|
||||
symbol_table.add_variable("memory_used",memory_used);
|
||||
symbol_table.add_variable("swap_total",swap_total);
|
||||
@ -353,6 +353,11 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if ((currentStamp-Client(ClientID)->m_AlarmLastTime) > Watchdog(ID)->m_aInterval)
|
||||
{
|
||||
if (!Client(ClientID)->m_Stats.m_Online4 && !Client(ClientID)->m_Stats.m_Online6)
|
||||
{
|
||||
//休眠5分钟如果5分钟后状态发生了变更,消息不发出。
|
||||
printf("download\n");
|
||||
}
|
||||
Client(ClientID)->m_AlarmLastTime = currentStamp;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
@ -498,6 +503,109 @@ void CMain::JSONUpdateThread(void *pUser)
|
||||
fs_rename(pConfig->m_aJSONFile, aJSONFileTmp);
|
||||
}
|
||||
|
||||
void CMain::offlineAlarmThread(void *pUser)
|
||||
{
|
||||
CJSONUpdateThreadData *m_OfflineAlarmThreadData = (CJSONUpdateThreadData *)pUser;
|
||||
CClient *pClients = m_OfflineAlarmThreadData->pClients;
|
||||
CWatchDog *pWatchDogs = m_OfflineAlarmThreadData->pWatchDogs;
|
||||
volatile short ClientID = m_OfflineAlarmThreadData->m_ReloadRequired;
|
||||
thread_sleep(25000);
|
||||
if(!pClients[ClientID].m_Connected)
|
||||
{
|
||||
int ID = 0;
|
||||
while (strcmp(pWatchDogs[ID].m_aName, "NULL"))
|
||||
{
|
||||
typedef exprtk::symbol_table<double> symbol_table_t;
|
||||
typedef exprtk::expression<double> expression_t;
|
||||
typedef exprtk::parser<double> parser_t;
|
||||
const std::string expression_string = pWatchDogs[ID].m_aRule;
|
||||
std::string username = pClients[ClientID].m_aUsername;
|
||||
std::string name = pClients[ClientID].m_aName;
|
||||
std::string type = pClients[ClientID].m_aType;
|
||||
std::string host = pClients[ClientID].m_aHost;
|
||||
std::string location = pClients[ClientID].m_aLocation;
|
||||
std::double_t online4 = pClients[ClientID].m_Stats.m_Online4;
|
||||
std::double_t online6 = pClients[ClientID].m_Stats.m_Online6;
|
||||
|
||||
symbol_table_t symbol_table;
|
||||
symbol_table.add_stringvar("username", username);
|
||||
symbol_table.add_stringvar("name", name);
|
||||
symbol_table.add_stringvar("type", type);
|
||||
symbol_table.add_stringvar("host", host);
|
||||
symbol_table.add_stringvar("location", location);
|
||||
symbol_table.add_variable("online4",online4);
|
||||
symbol_table.add_variable("online6",online6);
|
||||
symbol_table.add_constants();
|
||||
|
||||
expression_t expression;
|
||||
expression.register_symbol_table(symbol_table);
|
||||
|
||||
parser_t parser;
|
||||
parser.compile(expression_string,expression);
|
||||
|
||||
if (expression.value() > 0)
|
||||
{
|
||||
time_t currentStamp = (long long)time(/*ago*/0);
|
||||
if ((currentStamp-pClients[ClientID].m_AlarmLastTime) > pWatchDogs[ID].m_aInterval)
|
||||
{
|
||||
printf("客户端下线且超过阈值, Client disconnects and sends alert information\n");
|
||||
pClients[ClientID].m_AlarmLastTime = currentStamp;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
curl = curl_easy_init();
|
||||
if(curl) {
|
||||
//standard time
|
||||
char standardTime[32]= { 0 };
|
||||
strftime(standardTime, sizeof(standardTime), "%Y-%m-%d %H:%M:%S",localtime(¤tStamp));
|
||||
|
||||
//url encode, Rules conflict with url special characters,eg:&, del rules, by https://cpp.la, 2023-10-09
|
||||
char encodeBuffer[2048] = { 0 };
|
||||
sprintf(encodeBuffer, "【告警名称】 %s \n\n【告警时间】 %s \n\n【用户名】 %s \n\n【节点名】 %s \n\n【虚拟化】 %s \n\n【主机名】 %s \n\n【位 置】 %s",
|
||||
pWatchDogs[ID].m_aName,
|
||||
standardTime,
|
||||
pClients[ClientID].m_aUsername,
|
||||
pClients[ClientID].m_aName,
|
||||
pClients[ClientID].m_aType,
|
||||
pClients[ClientID].m_aHost,
|
||||
pClients[ClientID].m_aLocation);
|
||||
char *encodeUrl = curl_easy_escape(curl, encodeBuffer, strlen(encodeBuffer));
|
||||
|
||||
//standard url
|
||||
char urlBuffer[2048] = { 0 };
|
||||
sprintf(urlBuffer, "%s%s",pWatchDogs[ID].m_aCallback, encodeUrl);
|
||||
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, urlBuffer);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,"signature=ServerStatus");
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 6L);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "watchdog failed: %s\n", curl_easy_strerror(res));
|
||||
if(encodeUrl)
|
||||
curl_free(encodeUrl);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
curl_global_cleanup();
|
||||
}
|
||||
else
|
||||
printf("客户端下线但未超过阈值,No alarm if the threshold is not exceeded\n");
|
||||
}
|
||||
ID++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("网络波动,No alarm information is sent due to network fluctuations\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
int CMain::ReadConfig()
|
||||
{
|
||||
// read and parse config
|
||||
@ -696,6 +804,7 @@ int CMain::Run()
|
||||
m_JSONUpdateThreadData.m_ReloadRequired = 2;
|
||||
m_JSONUpdateThreadData.pClients = m_aClients;
|
||||
m_JSONUpdateThreadData.pConfig = &m_Config;
|
||||
m_JSONUpdateThreadData.pWatchDogs = m_aCWatchDogs;
|
||||
void *LoadThread = thread_create(JSONUpdateThread, &m_JSONUpdateThreadData);
|
||||
//thread_detach(LoadThread);
|
||||
|
||||
|
@ -101,10 +101,12 @@ class CMain
|
||||
{
|
||||
CClient *pClients;
|
||||
CConfig *pConfig;
|
||||
CWatchDog *pWatchDogs;
|
||||
volatile short m_ReloadRequired;
|
||||
} m_JSONUpdateThreadData;
|
||||
} m_JSONUpdateThreadData, m_OfflineAlarmThreadData;
|
||||
|
||||
static void JSONUpdateThread(void *pUser);
|
||||
static void offlineAlarmThread(void *pUser);
|
||||
public:
|
||||
CMain(CConfig Config);
|
||||
|
||||
@ -120,8 +122,8 @@ public:
|
||||
void WatchdogMessage(int ClientNetID,
|
||||
double load_1, double load_5, double load_15, double ping_10010, double ping_189, double ping_10086,
|
||||
double time_10010, double time_189, double time_10086, double tcp_count, double udp_count, double process_count, double thread_count,
|
||||
double network_rx, double network_tx, double network_in, double network_out,double memory_total,
|
||||
double memory_used,double swap_total, double swap_used, double hdd_total,
|
||||
double network_rx, double network_tx, double network_in, double network_out, double last_network_in, double last_network_out,
|
||||
double memory_total, double memory_used,double swap_total, double swap_used, double hdd_total,
|
||||
double hdd_used, double io_read, double io_write, double cpu,double online4, double online6);
|
||||
|
||||
CClient *Client(int ClientID) { return &m_aClients[ClientID]; }
|
||||
|
6
web/css/bootstrap-theme.min.css
vendored
6
web/css/bootstrap-theme.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
10
web/css/bootstrap.min.css
vendored
10
web/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
218
web/css/dark.css
218
web/css/dark.css
@ -1,48 +1,182 @@
|
||||
body { background: #212e36 url('../img/dark.png'); color: #dcdcdc; }
|
||||
.navbar { min-height: 40px; }
|
||||
.navbar-brand { color: #FFF !important; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.dropdown-menu > li > a { color: #FFF !important; background-color: #222222 !important; }
|
||||
.dropdown-menu > li > a:hover { color: #FFF !important; background: #000 !important; }
|
||||
.dropdown-menu { background: #222 !important; background-color: #222222 !important; }
|
||||
.navbar-inverse .navbar-inner { background-color:#1B1B1B; background-image:-moz-linear-gradient(top, #222222, #111111); background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111)); background-image:-webkit-linear-gradient(top, #222222, #111111); background-image:-o-linear-gradient(top, #222222, #111111); background-image:linear-gradient(to bottom, #212e36, #212e36); background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0); border-color: #252525; }
|
||||
.content { background: #212e36; padding: 20px; border-radius: 5px; border: 1px #212e36 solid; -webkit-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); -moz-box-shadow: 0 0px 0px rgba(0, 0, 0, 0); box-shadow: 0 0px 0px rgba(0, 0, 0, 0); margin-bottom: 20px; }
|
||||
.table { background: #363b40; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th { text-align: center; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #212e36; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #212e36; }
|
||||
.table td { text-align: center; border-color: #2F2F2F; }
|
||||
.progress { margin-bottom: 0; background: #363b40; }
|
||||
.table-hover > tbody > tr:hover > td { background: #414141; }
|
||||
tr.even.expandRow > :hover { background: #212e36 !important; }
|
||||
tr.odd.expandRow > :hover { background: #212e36 !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 115px; }
|
||||
body {
|
||||
background: #212e36 url('../img/dark.png') repeat;
|
||||
color: #dcdcdc;
|
||||
font-size: 15px;
|
||||
padding-top: 70px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
min-height: 40px;
|
||||
background-color: #1B1B1B;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
color: #FFF !important;
|
||||
padding: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.dropdown .dropdown-toggle {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a {
|
||||
color: #FFF !important;
|
||||
background-color: #222222 !important;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover {
|
||||
color: #FFF !important;
|
||||
background: #000 !important;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background: #222 !important;
|
||||
background-color: #222222 !important;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-inner {
|
||||
background-color: #1B1B1B;
|
||||
background-image: linear-gradient(to bottom, #212e36, #212e36);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #252525;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: #212e36;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #212e36;
|
||||
box-shadow: 0 0px 0px rgba(0, 0, 0, 0);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.table {
|
||||
background-color: #212e36 !important;
|
||||
margin-bottom: 0;
|
||||
border-collapse: collapse;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
background-color: #212e36 !important;
|
||||
color: #dcdcdc !important;
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-child(even) {
|
||||
background-color: #212e36;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-child(odd) {
|
||||
background-color: #212e36;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
background: #363b40;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.table-hover tbody tr:hover td {
|
||||
background: #414141;
|
||||
}
|
||||
|
||||
tr.even.expandRow:hover {
|
||||
background: #212e36 !important;
|
||||
}
|
||||
|
||||
tr.odd.expandRow:hover {
|
||||
background: #212e36 !important;
|
||||
}
|
||||
|
||||
.expandRow td {
|
||||
padding: 0 !important;
|
||||
border-top: 0 !important;
|
||||
}
|
||||
|
||||
#month_traffic {
|
||||
min-width: 85px;
|
||||
max-width: 95px;
|
||||
}
|
||||
|
||||
#traffic, #network {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
#cpu, #ram, #hdd {
|
||||
min-width: 45px;
|
||||
max-width: 68px;
|
||||
}
|
||||
|
||||
#ping {
|
||||
width: 115px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#traffic, #network {
|
||||
width: 120px;
|
||||
}
|
||||
#type, #location, #uptime, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 720px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#traffic, #network {
|
||||
width: 120px;
|
||||
}
|
||||
#month_traffic, #type, #location, #uptime, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic { display:none; visibility:hidden; }
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#network {
|
||||
width: 120px;
|
||||
}
|
||||
#month_traffic, #type, #location, #uptime, #traffic, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-nav .nav-link {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.navbar-nav .dropdown-toggle::after {
|
||||
vertical-align: 0.15em;
|
||||
}
|
||||
|
@ -1,45 +1,163 @@
|
||||
body { background: #ebebeb url('../img/light.png'); }
|
||||
.navbar { min-height: 40px; }
|
||||
.navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.dropdown .dropdown-toggle { padding-bottom: 10px; padding-top: 10px; }
|
||||
.navbar-inverse .navbar-brand { color: #fff; padding: 10px; font-size: 20px; }
|
||||
.content { background: #ffffff; padding: 20px; border-radius: 5px; border: 1px #cecece solid; -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, .1); box-shadow: 0 1px 10px rgba(0, 0, 0, .1); margin-bottom: 20px; }
|
||||
.table { background: #ffffff; margin-bottom: 0; border-collapse: collapse; border-radius: 3px; }
|
||||
.table th, .table td { text-align: center; }
|
||||
.table-striped tbody > tr.even > td, .table-striped tbody > tr.even > th { background-color: #F9F9F9; }
|
||||
.table-striped tbody > tr.odd > td, .table-striped tbody > tr.odd > th { background-color: #FFF; }
|
||||
.progress { margin-bottom: 0; }
|
||||
.progress-bar { color: #000; }
|
||||
.table-hover > tbody > tr:hover > td { background: #E6E6E6; }
|
||||
tr.even.expandRow > :hover { background: #F9F9F9 !important; }
|
||||
tr.odd.expandRow > :hover { background: #FFF !important; }
|
||||
.expandRow > td { padding: 0 !important; border-top: 0px !important; }
|
||||
#month_traffic { min-width: 85px; max-width: 95px;}
|
||||
#network { min-width: 110px; }
|
||||
#cpu, #ram, #hdd { min-width: 45px; max-width: 90px; }
|
||||
#ping { max-width: 115px; }
|
||||
body {
|
||||
background: #ebebeb url('../img/light.png') repeat;
|
||||
font-size: 15px;
|
||||
padding-top: 70px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
min-height: 40px;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.dropdown .dropdown-toggle {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-brand {
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.content {
|
||||
background: #ffffff;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #cecece;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, .1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.table {
|
||||
background: #ffffff;
|
||||
margin-bottom: 0;
|
||||
border-collapse: collapse;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-child(even) {
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-child(odd) {
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
color: #000;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.table-hover tbody tr:hover td {
|
||||
background: #E6E6E6;
|
||||
}
|
||||
|
||||
tr.even.expandRow:hover {
|
||||
background: #F9F9F9 !important;
|
||||
}
|
||||
|
||||
tr.odd.expandRow:hover {
|
||||
background: #FFF !important;
|
||||
}
|
||||
|
||||
.expandRow td {
|
||||
padding: 0 !important;
|
||||
border-top: 0 !important;
|
||||
}
|
||||
|
||||
#month_traffic {
|
||||
min-width: 85px;
|
||||
max-width: 95px;
|
||||
}
|
||||
|
||||
#traffic, #network {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
#cpu, #ram, #hdd {
|
||||
min-width: 45px;
|
||||
max-width: 68px;
|
||||
}
|
||||
|
||||
#ping {
|
||||
width: 115px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#traffic, #network {
|
||||
width: 120px;
|
||||
}
|
||||
#type, #location, #uptime, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 720px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#traffic, #network {
|
||||
width: 120px;
|
||||
}
|
||||
#month_traffic, #type, #location, #uptime, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 620px) {
|
||||
body { font-size: 10px; }
|
||||
.content { padding: 0; }
|
||||
#month_traffic { display:none; visibility:hidden; }
|
||||
#type { display:none; visibility:hidden; }
|
||||
#location, tr td:nth-child(5) { display:none; visibility:hidden; }
|
||||
#uptime, tr td:nth-child(6) { display:none; visibility:hidden; }
|
||||
#traffic, tr td:nth-child(9) { display:none; visibility:hidden; }
|
||||
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
|
||||
}
|
||||
body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0;
|
||||
}
|
||||
#network {
|
||||
width: 120px;
|
||||
}
|
||||
#month_traffic, #type, #location, #uptime, #traffic, #ping {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-nav .nav-link {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.navbar-nav .dropdown-toggle::after {
|
||||
vertical-align: 0.15em;
|
||||
}
|
||||
|
241
web/index.html
241
web/index.html
@ -1,140 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
json字段保持完整, 自行自定义前端展示
|
||||
ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)ლ(•̀ _ •́ ლ)
|
||||
ლ(•̀ _ •́ ლ)
|
||||
follow me, better solution for you. by:https://cpp.la
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>云监控</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="云监控">
|
||||
<meta name="author" content="BotoX">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
|
||||
<link rel="stylesheet" href="css/light.css" title="light">
|
||||
<link rel="stylesheet" href="css/dark.css" title="dark">
|
||||
<style>
|
||||
body {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="js/html5shiv.js"></script>
|
||||
<script src="js/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div role="navigation" class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="navbar-inner">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button data-target=".navbar-collapse" data-toggle="collapse" class="navbar-toggle" type="button">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a href="#" class="navbar-brand">云监控</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown">
|
||||
<a data-toggle="tab" class="dropdown-toggle" href="#server">首页</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a data-toggle="tab" class="dropdown-toggle" href="#monitor">服务</a>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">风格<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" onclick="setActiveStyleSheet('dark', true)">黑夜</a></li>
|
||||
<li><a href="#" onclick="setActiveStyleSheet('light', true)">白天</a></li>
|
||||
<li><a href="/index3.html">简洁</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="云监控,ServerStatus中文版,ServerStatus,ServerStatus cppla">
|
||||
<meta name="author" content="ServerStatus Theme by AI">
|
||||
<title>云监控</title>
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/light.css" title="light">
|
||||
<link rel="stylesheet" href="css/dark.css" title="dark">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">云监控</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#server" data-bs-toggle="tab">首页</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#monitor" data-bs-toggle="tab">服务</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
风格
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="#" onclick="setActiveStyleSheet('dark')">黑夜</a></li>
|
||||
<li><a class="dropdown-item" href="#" onclick="setActiveStyleSheet('light')">白天</a></li>
|
||||
<li><a class="dropdown-item" href="/index3.html">简洁</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container content">
|
||||
<div id="loading-notice">
|
||||
<noscript>
|
||||
<div class="alert alert-danger" style="text-align: center;">
|
||||
<strong>Enable JavaScript</strong> , please do it.
|
||||
</div>
|
||||
</noscript>
|
||||
<div style="text-align: center;">
|
||||
警告:如果出现此消息,请确保您已启用Javascript! <br />否则云监控主服务没启动或已关闭.
|
||||
</div>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="container content">
|
||||
<noscript>
|
||||
<div class="alert alert-danger text-center">
|
||||
<strong>请启用 JavaScript</strong>,否则无法正常使用本站功能。
|
||||
</div>
|
||||
</noscript>
|
||||
<div id="loading-notice" class="text-center">
|
||||
警告:如果出现此消息,请确保您已启用 Javascript!<br>
|
||||
否则云监控主服务没启动或已关闭。
|
||||
</div>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade in active" id="server">
|
||||
<!--主机-->
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="online_status" style="text-align: center;">🔗协议</th>
|
||||
<th id="month_traffic" style="text-align: center;">📊月流量↓|↑</th>
|
||||
<th id="name">📌节点</th>
|
||||
<th id="type">🗂️虚拟化</th>
|
||||
<th id="location">🌍位置</th>
|
||||
<th id="uptime">⏱️在线</th>
|
||||
<th id="load">负载</th>
|
||||
<th id="network">🚦网络↓|↑</th>
|
||||
<th id="traffic">📋总流量↓|↑</th>
|
||||
<th id="cpu">🎯核芯</th>
|
||||
<th id="ram">⚡️内存</th>
|
||||
<th id="hdd">💾硬盘</th>
|
||||
<th id="ping">🌐CU|CT|CM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="servers">
|
||||
<!-- Servers here \o/ -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="monitor">
|
||||
<!--服务-->
|
||||
<table class="table table-striped table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="monitor_status" style="text-align: center;">🔗协议</th>
|
||||
<th id="monitor_node">📌监测节点</th>
|
||||
<th id="monitor_location">🌍监测位置</th>
|
||||
<th id="monitor_text" style="text-align: center;">📋监测内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="monitors">
|
||||
<!-- Monitors here \o/ -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="server">
|
||||
<!--主机-->
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="online_status" style="text-align: center;">🔗协议</th>
|
||||
<th id="month_traffic" style="text-align: center;">📊月流量↓|↑</th>
|
||||
<th id="name">📌节点</th>
|
||||
<th id="type">🗂️虚拟化</th>
|
||||
<th id="location">🌍位置</th>
|
||||
<th id="uptime">⏱️在线</th>
|
||||
<th id="load">负载</th>
|
||||
<th id="network">🚦网络↓|↑</th>
|
||||
<th id="traffic">📋总流量↓|↑</th>
|
||||
<th id="cpu">🎯核芯</th>
|
||||
<th id="ram">⚡️内存</th>
|
||||
<th id="hdd">💾硬盘</th>
|
||||
<th id="ping">🌐CU|CT|CM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="servers">
|
||||
<!-- Servers here \o/ -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="monitor">
|
||||
<!--服务-->
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="monitor_status" style="text-align: center;">🔗协议</th>
|
||||
<th id="monitor_node">📌监测节点</th>
|
||||
<th id="monitor_location">🌍监测位置</th>
|
||||
<th id="monitor_text" style="text-align: center;">📋监测内容</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="monitors">
|
||||
<!-- Monitors here \o/ -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<div id="updated">Updating...</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div id="updated">更新中...</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<p style="text-align: center; font-size: 10px;">
|
||||
<a href="https://github.com/cppla/ServerStatus">ServerStatus中文版</a>
|
||||
</p>
|
||||
</div>
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
<script src="js/serverstatus.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<footer class="container">
|
||||
<p class="text-center" style="font-size: 10px;">
|
||||
<a href="https://github.com/cppla/ServerStatus">ServerStatus中文版</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/serverstatus.js"></script>
|
||||
</body>
|
||||
</html>
|
7
web/js/bootstrap.bundle.min.js
vendored
Normal file
7
web/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
web/js/bootstrap.min.js
vendored
7
web/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
326
web/js/html5shiv.js
vendored
326
web/js/html5shiv.js
vendored
@ -1,326 +0,0 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.7.3';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the built-in list of html5 elements
|
||||
* @memberOf html5
|
||||
* @param {String|Array} newElements whitespace separated list or array of new element names to shiv
|
||||
* @param {Document} ownerDocument The context document.
|
||||
*/
|
||||
function addElements(newElements, ownerDocument) {
|
||||
var elements = html5.elements;
|
||||
if(typeof elements != 'string'){
|
||||
elements = elements.join(' ');
|
||||
}
|
||||
if(typeof newElements != 'string'){
|
||||
newElements = newElements.join(' ');
|
||||
}
|
||||
html5.elements = elements +' '+ newElements;
|
||||
shivDocument(ownerDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document|DocumentFragment} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment,
|
||||
|
||||
//extends list of elements
|
||||
addElements: addElements
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
if(typeof module == 'object' && module.exports){
|
||||
module.exports = html5;
|
||||
}
|
||||
|
||||
}(typeof window !== "undefined" ? window : this, document));
|
2
web/js/jquery.min.js
vendored
2
web/js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
5
web/js/respond.min.js
vendored
5
web/js/respond.min.js
vendored
@ -1,5 +0,0 @@
|
||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||
* */
|
||||
|
||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
@ -4,424 +4,350 @@ var d = 0;
|
||||
var server_status = new Array();
|
||||
|
||||
function timeSince(date) {
|
||||
if(date == 0)
|
||||
return "从未.";
|
||||
|
||||
var seconds = Math.floor((new Date() - date) / 1000);
|
||||
var interval = Math.floor(seconds / 60);
|
||||
if (interval > 1)
|
||||
return interval + " 分钟前.";
|
||||
else
|
||||
return "几秒前.";
|
||||
if (date == 0) return "从未.";
|
||||
var seconds = Math.floor((new Date() - date) / 1000);
|
||||
var interval = Math.floor(seconds / 60);
|
||||
return interval > 1 ? interval + " 分钟前." : "几秒前.";
|
||||
}
|
||||
|
||||
function bytesToSize(bytes, precision, si)
|
||||
{
|
||||
var ret;
|
||||
si = typeof si !== 'undefined' ? si : 0;
|
||||
if(si != 0) {
|
||||
var megabyte = 1000 * 1000;
|
||||
var gigabyte = megabyte * 1000;
|
||||
var terabyte = gigabyte * 1000;
|
||||
} else {
|
||||
var megabyte = 1024 * 1024;
|
||||
var gigabyte = megabyte * 1024;
|
||||
var terabyte = gigabyte * 1024;
|
||||
}
|
||||
|
||||
if ((bytes >= megabyte) && (bytes < gigabyte)) {
|
||||
ret = (bytes / megabyte).toFixed(precision) + ' M';
|
||||
|
||||
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
|
||||
ret = (bytes / gigabyte).toFixed(precision) + ' G';
|
||||
|
||||
} else if (bytes >= terabyte) {
|
||||
ret = (bytes / terabyte).toFixed(precision) + ' T';
|
||||
|
||||
} else {
|
||||
return bytes + ' B';
|
||||
}
|
||||
return ret;
|
||||
/*if(si != 0) {
|
||||
return ret + 'B';
|
||||
} else {
|
||||
return ret + 'iB';
|
||||
}*/
|
||||
function bytesToSize(bytes, precision, si = false) {
|
||||
const units = si ? ['B', 'KB', 'MB', 'GB', 'TB'] : ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
|
||||
if (bytes === 0) return '0 B';
|
||||
const k = si ? 1000 : 1024;
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(precision)) + ' ' + units[i];
|
||||
}
|
||||
|
||||
function uptime() {
|
||||
$.getJSON("json/stats.json", function(result) {
|
||||
$("#loading-notice").remove();
|
||||
if(result.reload)
|
||||
setTimeout(function() { location.reload() }, 1000);
|
||||
fetch("json/stats.json")
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(result => {
|
||||
document.getElementById("loading-notice")?.remove();
|
||||
if (result.reload) setTimeout(location.reload, 1000);
|
||||
|
||||
for (var i = 0, rlen=result.servers.length; i < rlen; i++) {
|
||||
var TableRow = $("#servers tr#r" + i);
|
||||
var MableRow = $("#monitors tr#r" + i);
|
||||
var ExpandRow = $("#servers #rt" + i);
|
||||
var hack; // fuck CSS for making me do this
|
||||
if(i%2) hack="odd"; else hack="even";
|
||||
if (!TableRow.length) {
|
||||
$("#servers").append(
|
||||
"<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" +
|
||||
"<td id=\"online_status\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"month_traffic\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"name\">加载中</td>" +
|
||||
"<td id=\"type\">加载中</td>" +
|
||||
"<td id=\"location\">加载中</td>" +
|
||||
"<td id=\"uptime\">加载中</td>" +
|
||||
"<td id=\"load\">加载中</td>" +
|
||||
"<td id=\"network\">加载中</td>" +
|
||||
"<td id=\"traffic\">加载中</td>" +
|
||||
"<td id=\"cpu\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"memory\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"hdd\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"ping\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"</tr>" +
|
||||
"<tr class=\"expandRow " + hack + "\"><td colspan=\"16\"><div class=\"accordian-body collapse\" id=\"rt" + i + "\">" +
|
||||
"<div id=\"expand_mem\">加载中</div>" +
|
||||
"<div id=\"expand_hdd\">加载中</div>" +
|
||||
"<div id=\"expand_tupd\">加载中</div>" +
|
||||
"<div id=\"expand_ping\">加载中</div>" +
|
||||
"</div></td></tr>"
|
||||
);
|
||||
TableRow = $("#servers tr#r" + i);
|
||||
ExpandRow = $("#servers #rt" + i);
|
||||
server_status[i] = true;
|
||||
}
|
||||
if (!MableRow.length) {
|
||||
$("#monitors").append(
|
||||
"<tr id=\"r" + i + "\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" +
|
||||
"<td id=\"monitor_status\"><div class=\"progress\"><div style=\"width: 100%;\" class=\"progress-bar progress-bar-warning\"><small>加载中</small></div></div></td>" +
|
||||
"<td id=\"monitor_node\">加载中</td>" +
|
||||
"<td id=\"monitor_location\">加载中</td>" +
|
||||
"<td id=\"monitor_text\">加载中</td>" +
|
||||
"</tr>"
|
||||
);
|
||||
MableRow = $("#monitors tr#r" + i);
|
||||
}
|
||||
TableRow = TableRow[0];
|
||||
MableRow = MableRow[0];
|
||||
if(error) {
|
||||
TableRow.setAttribute("data-target", "#rt" + i);
|
||||
MableRow.setAttribute("data-target", "#rt" + i);
|
||||
server_status[i] = true;
|
||||
}
|
||||
result.servers.forEach((server, i) => {
|
||||
let TableRow = document.querySelector(`#servers tr#r${i}`);
|
||||
let MableRow = document.querySelector(`#monitors tr#r${i}`);
|
||||
let ExpandRow = document.querySelector(`#servers #rt${i}`);
|
||||
let hack = i % 2 ? "odd" : "even";
|
||||
|
||||
// online_status
|
||||
if (result.servers[i].online4 && !result.servers[i].online6) {
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv4</small>";
|
||||
MableRow.children["monitor_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
MableRow.children["monitor_status"].children[0].children[0].innerHTML = "<small>IPv4</small>";
|
||||
} else if (result.servers[i].online4 && result.servers[i].online6) {
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>双栈</small>";
|
||||
MableRow.children["monitor_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
MableRow.children["monitor_status"].children[0].children[0].innerHTML = "<small>双栈</small>";
|
||||
} else if (!result.servers[i].online4 && result.servers[i].online6) {
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>IPv6</small>";
|
||||
MableRow.children["monitor_status"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
MableRow.children["monitor_status"].children[0].children[0].innerHTML = "<small>IPv6</small>";
|
||||
} else {
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
MableRow.children["monitor_status"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
MableRow.children["monitor_status"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
if (!TableRow) {
|
||||
document.getElementById("servers").insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`<tr id="r${i}" data-bs-toggle="collapse" data-bs-target="#rt${i}" class="accordion-toggle ${hack}">
|
||||
<td id="online_status"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="month_traffic"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="name">加载中</td>
|
||||
<td id="type">加载中</td>
|
||||
<td id="location">加载中</td>
|
||||
<td id="uptime">加载中</td>
|
||||
<td id="load">加载中</td>
|
||||
<td id="network">加载中</td>
|
||||
<td id="traffic">加载中</td>
|
||||
<td id="cpu"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="memory"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="hdd"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="ping"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
</tr>
|
||||
<tr class="expandRow ${hack}"><td colspan="16"><div class="accordian-body collapse" id="rt${i}">
|
||||
<div id="expand_mem">加载中</div>
|
||||
<div id="expand_hdd">加载中</div>
|
||||
<div id="expand_tupd">加载中</div>
|
||||
<div id="expand_ping">加载中</div>
|
||||
</div></td></tr>`
|
||||
);
|
||||
TableRow = document.querySelector(`#servers tr#r${i}`);
|
||||
ExpandRow = document.querySelector(`#servers #rt${i}`);
|
||||
server_status[i] = true;
|
||||
}
|
||||
|
||||
// Name
|
||||
TableRow.children["name"].innerHTML = result.servers[i].name;
|
||||
MableRow.children["monitor_node"].innerHTML = result.servers[i].name;
|
||||
if (!MableRow) {
|
||||
document.getElementById("monitors").insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`<tr id="r${i}" data-bs-target="#rt${i}" class="accordion-toggle ${hack}">
|
||||
<td id="monitor_status"><div class="progress"><div style="width: 100%;" class="progress-bar bg-warning"><small>加载中</small></div></div></td>
|
||||
<td id="monitor_node">加载中</td>
|
||||
<td id="monitor_location">加载中</td>
|
||||
<td id="monitor_text">加载中</td>
|
||||
</tr>`
|
||||
);
|
||||
MableRow = document.querySelector(`#monitors tr#r${i}`);
|
||||
}
|
||||
|
||||
// Type
|
||||
TableRow.children["type"].innerHTML = result.servers[i].type;
|
||||
if (error) {
|
||||
TableRow.setAttribute("data-bs-target", `#rt${i}`);
|
||||
MableRow.setAttribute("data-bs-target", `#rt${i}`);
|
||||
server_status[i] = true;
|
||||
}
|
||||
|
||||
// Location
|
||||
TableRow.children["location"].innerHTML = result.servers[i].location;
|
||||
MableRow.children["monitor_location"].innerHTML = result.servers[i].location;
|
||||
if (!result.servers[i].online4 && !result.servers[i].online6) {
|
||||
if (server_status[i]) {
|
||||
TableRow.children["uptime"].innerHTML = "–";
|
||||
TableRow.children["load"].innerHTML = "–";
|
||||
TableRow.children["network"].innerHTML = "–";
|
||||
TableRow.children["traffic"].innerHTML = "–";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["cpu"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["cpu"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["memory"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["memory"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["hdd"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["hdd"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
TableRow.children["ping"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["ping"].children[0].children[0].innerHTML = "<small>关闭</small>";
|
||||
MableRow.children["monitor_text"].innerHTML = "-";
|
||||
if(ExpandRow.hasClass("in")) {
|
||||
ExpandRow.collapse("hide");
|
||||
}
|
||||
TableRow.setAttribute("data-target", "");
|
||||
MableRow.setAttribute("data-target", "");
|
||||
server_status[i] = false;
|
||||
}
|
||||
} else {
|
||||
if (!server_status[i]) {
|
||||
TableRow.setAttribute("data-target", "#rt" + i);
|
||||
MableRow.setAttribute("data-target", "#rt" + i);
|
||||
server_status[i] = true;
|
||||
}
|
||||
const statusClass = server.online4 || server.online6 ? "progress-bar bg-success" : "progress-bar bg-danger";
|
||||
const statusText = server.online4 && server.online6 ? "双栈" : server.online4 ? "IPv4" : server.online6 ? "IPv6" : "关闭";
|
||||
|
||||
// month traffic
|
||||
var monthtraffic = "";
|
||||
var trafficdiff_in = result.servers[i].network_in - result.servers[i].last_network_in;
|
||||
var trafficdiff_out = result.servers[i].network_out - result.servers[i].last_network_out;
|
||||
if(trafficdiff_in < 1024*1024*1024*1024)
|
||||
monthtraffic += (trafficdiff_in/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
monthtraffic += (trafficdiff_in/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
monthtraffic += " | "
|
||||
if(trafficdiff_out < 1024*1024*1024*1024)
|
||||
monthtraffic += (trafficdiff_out/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
monthtraffic += (trafficdiff_out/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>"+monthtraffic+"</small>";
|
||||
if (TableRow) {
|
||||
const onlineStatusBar = TableRow.querySelector("#online_status .progress-bar");
|
||||
if (onlineStatusBar) {
|
||||
onlineStatusBar.setAttribute("class", statusClass);
|
||||
onlineStatusBar.innerHTML = `<small>${statusText}</small>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Uptime
|
||||
TableRow.children["uptime"].innerHTML = result.servers[i].uptime;
|
||||
if (MableRow) {
|
||||
const monitorStatusBar = MableRow.querySelector("#monitor_status .progress-bar");
|
||||
if (monitorStatusBar) {
|
||||
monitorStatusBar.setAttribute("class", statusClass);
|
||||
monitorStatusBar.innerHTML = `<small>${statusText}</small>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Load: default load_1, you can change show: load_1, load_5, load_15
|
||||
if(result.servers[i].load == -1) {
|
||||
TableRow.children["load"].innerHTML = "–";
|
||||
} else {
|
||||
TableRow.children["load"].innerHTML = result.servers[i].load_1.toFixed(2);
|
||||
}
|
||||
if (TableRow) {
|
||||
TableRow.querySelector("#name").innerHTML = server.name;
|
||||
TableRow.querySelector("#type").innerHTML = server.type;
|
||||
TableRow.querySelector("#location").innerHTML = server.location;
|
||||
}
|
||||
|
||||
// Network
|
||||
var netstr = "";
|
||||
if(result.servers[i].network_rx < 1024*1024)
|
||||
netstr += (result.servers[i].network_rx/1024).toFixed(1) + "K";
|
||||
else
|
||||
netstr += (result.servers[i].network_rx/1024/1024).toFixed(1) + "M";
|
||||
netstr += " | "
|
||||
if(result.servers[i].network_tx < 1024*1024)
|
||||
netstr += (result.servers[i].network_tx/1024).toFixed(1) + "K";
|
||||
else
|
||||
netstr += (result.servers[i].network_tx/1024/1024).toFixed(1) + "M";
|
||||
TableRow.children["network"].innerHTML = netstr;
|
||||
if (MableRow) {
|
||||
MableRow.querySelector("#monitor_node").innerHTML = server.name;
|
||||
MableRow.querySelector("#monitor_location").innerHTML = server.location;
|
||||
}
|
||||
|
||||
//Traffic
|
||||
var trafficstr = "";
|
||||
if(result.servers[i].network_in < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
trafficstr += (result.servers[i].network_in/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
trafficstr += " | "
|
||||
if(result.servers[i].network_out < 1024*1024*1024*1024)
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024).toFixed(1) + "G";
|
||||
else
|
||||
trafficstr += (result.servers[i].network_out/1024/1024/1024/1024).toFixed(1) + "T";
|
||||
TableRow.children["traffic"].innerHTML = trafficstr;
|
||||
if (!server.online4 && !server.online6) {
|
||||
if (server_status[i]) {
|
||||
if (TableRow) {
|
||||
TableRow.querySelector("#uptime").innerHTML = "–";
|
||||
TableRow.querySelector("#load").innerHTML = "–";
|
||||
TableRow.querySelector("#network").innerHTML = "–";
|
||||
TableRow.querySelector("#traffic").innerHTML = "–";
|
||||
const monthTrafficBar = TableRow.querySelector("#month_traffic .progress-bar");
|
||||
if (monthTrafficBar) {
|
||||
monthTrafficBar.setAttribute("class", "progress-bar bg-warning");
|
||||
monthTrafficBar.innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
const cpuBar = TableRow.querySelector("#cpu .progress-bar");
|
||||
if (cpuBar) {
|
||||
cpuBar.setAttribute("class", "progress-bar bg-danger");
|
||||
cpuBar.style.width = "100%";
|
||||
cpuBar.innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
const memoryBar = TableRow.querySelector("#memory .progress-bar");
|
||||
if (memoryBar) {
|
||||
memoryBar.setAttribute("class", "progress-bar bg-danger");
|
||||
memoryBar.style.width = "100%";
|
||||
memoryBar.innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
const hddBar = TableRow.querySelector("#hdd .progress-bar");
|
||||
if (hddBar) {
|
||||
hddBar.setAttribute("class", "progress-bar bg-danger");
|
||||
hddBar.style.width = "100%";
|
||||
hddBar.innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
const pingBar = TableRow.querySelector("#ping .progress-bar");
|
||||
if (pingBar) {
|
||||
pingBar.setAttribute("class", "progress-bar bg-danger");
|
||||
pingBar.style.width = "100%";
|
||||
pingBar.innerHTML = "<small>关闭</small>";
|
||||
}
|
||||
}
|
||||
if (MableRow) {
|
||||
MableRow.querySelector("#monitor_text").innerHTML = "-";
|
||||
}
|
||||
if (ExpandRow && ExpandRow.classList.contains("show")) ExpandRow.classList.remove("show");
|
||||
if (TableRow) TableRow.setAttribute("data-bs-target", "");
|
||||
if (MableRow) MableRow.setAttribute("data-bs-target", "");
|
||||
server_status[i] = false;
|
||||
}
|
||||
} else {
|
||||
if (!server_status[i]) {
|
||||
if (TableRow) TableRow.setAttribute("data-bs-target", `#rt${i}`);
|
||||
if (MableRow) MableRow.setAttribute("data-bs-target", `#rt${i}`);
|
||||
server_status[i] = true;
|
||||
}
|
||||
|
||||
// CPU
|
||||
if (result.servers[i].cpu >= 90)
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
else if (result.servers[i].cpu >= 80)
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
else
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["cpu"].children[0].children[0].style.width = result.servers[i].cpu + "%";
|
||||
TableRow.children["cpu"].children[0].children[0].innerHTML = result.servers[i].cpu + "%";
|
||||
const trafficdiff_in = server.network_in - server.last_network_in;
|
||||
const trafficdiff_out = server.network_out - server.last_network_out;
|
||||
const monthtraffic = `${bytesToSize(trafficdiff_in, 1, true)} | ${bytesToSize(trafficdiff_out, 1, true)}`;
|
||||
if (TableRow) {
|
||||
const monthTrafficBar = TableRow.querySelector("#month_traffic .progress-bar");
|
||||
if (monthTrafficBar) {
|
||||
monthTrafficBar.setAttribute("class", "progress-bar bg-success");
|
||||
monthTrafficBar.innerHTML = `<small>${monthtraffic}</small>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Memory
|
||||
var Mem = ((result.servers[i].memory_used/result.servers[i].memory_total)*100.0).toFixed(0);
|
||||
if (Mem >= 90)
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
else if (Mem >= 80)
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
else
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["memory"].children[0].children[0].style.width = Mem + "%";
|
||||
TableRow.children["memory"].children[0].children[0].innerHTML = Mem + "%";
|
||||
// 内存|swap
|
||||
ExpandRow[0].children["expand_mem"].innerHTML = "内存|虚存: " + bytesToSize(result.servers[i].memory_used*1024, 1) + " / " + bytesToSize(result.servers[i].memory_total*1024, 1) + " | " + bytesToSize(result.servers[i].swap_used*1024, 0) + " / " + bytesToSize(result.servers[i].swap_total*1024, 0);
|
||||
if (TableRow) TableRow.querySelector("#uptime").innerHTML = server.uptime;
|
||||
if (TableRow) TableRow.querySelector("#load").innerHTML = server.load_1 == -1 ? "–" : server.load_1.toFixed(2);
|
||||
|
||||
// HDD
|
||||
var HDD = ((result.servers[i].hdd_used/result.servers[i].hdd_total)*100.0).toFixed(0);
|
||||
if (HDD >= 90)
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
else if (HDD >= 80)
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
else
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["hdd"].children[0].children[0].style.width = HDD + "%";
|
||||
TableRow.children["hdd"].children[0].children[0].innerHTML = HDD + "%";
|
||||
// IO Speed for HDD.
|
||||
// IO, 过小的B字节单位没有意义
|
||||
var io = "";
|
||||
if(result.servers[i].io_read < 1024*1024)
|
||||
io += parseInt(result.servers[i].io_read/1024) + "K";
|
||||
else
|
||||
io += parseInt(result.servers[i].io_read/1024/1024) + "M";
|
||||
io += " / "
|
||||
if(result.servers[i].io_write < 1024*1024)
|
||||
io += parseInt(result.servers[i].io_write/1024) + "K";
|
||||
else
|
||||
io += parseInt(result.servers[i].io_write/1024/1024) + "M";
|
||||
// Expand for HDD.
|
||||
ExpandRow[0].children["expand_hdd"].innerHTML = "硬盘|读写: " + bytesToSize(result.servers[i].hdd_used*1024*1024, 2) + " / " + bytesToSize(result.servers[i].hdd_total*1024*1024, 2) + " | " + io;
|
||||
const netstr = `${bytesToSize(server.network_rx, 1, true)} | ${bytesToSize(server.network_tx, 1, true)}`;
|
||||
if (TableRow) TableRow.querySelector("#network").innerHTML = netstr;
|
||||
|
||||
// delay time
|
||||
const trafficstr = `${bytesToSize(server.network_in, 1, true)} | ${bytesToSize(server.network_out, 1, true)}`;
|
||||
if (TableRow) TableRow.querySelector("#traffic").innerHTML = trafficstr;
|
||||
|
||||
// tcp, udp, process, thread count
|
||||
ExpandRow[0].children["expand_tupd"].innerHTML = "TCP/UDP/进/线: " + result.servers[i].tcp_count + " / " + result.servers[i].udp_count + " / " + result.servers[i].process_count+ " / " + result.servers[i].thread_count;
|
||||
const cpuClass = server.cpu >= 90 ? "progress-bar bg-danger" : server.cpu >= 80 ? "progress-bar bg-warning" : "progress-bar bg-success";
|
||||
if (TableRow) {
|
||||
const cpuBar = TableRow.querySelector("#cpu .progress-bar");
|
||||
if (cpuBar) {
|
||||
cpuBar.setAttribute("class", cpuClass);
|
||||
cpuBar.style.width = `${server.cpu}%`;
|
||||
cpuBar.innerHTML = `${server.cpu}%`;
|
||||
}
|
||||
}
|
||||
|
||||
// ping
|
||||
var PING_10010 = result.servers[i].ping_10010.toFixed(0);
|
||||
var PING_189 = result.servers[i].ping_189.toFixed(0);
|
||||
var PING_10086 = result.servers[i].ping_10086.toFixed(0);
|
||||
const Mem = ((server.memory_used / server.memory_total) * 100).toFixed(0);
|
||||
const memClass = Mem >= 90 ? "progress-bar bg-danger" : Mem >= 80 ? "progress-bar bg-warning" : "progress-bar bg-success";
|
||||
if (TableRow) {
|
||||
const memoryBar = TableRow.querySelector("#memory .progress-bar");
|
||||
if (memoryBar) {
|
||||
memoryBar.setAttribute("class", memClass);
|
||||
memoryBar.style.width = `${Mem}%`;
|
||||
memoryBar.innerHTML = `${Mem}%`;
|
||||
}
|
||||
}
|
||||
if (ExpandRow) ExpandRow.querySelector("#expand_mem").innerHTML = `内存|虚存: ${bytesToSize(server.memory_used * 1024, 1)} / ${bytesToSize(server.memory_total * 1024, 1)} | ${bytesToSize(server.swap_used * 1024, 0)} / ${bytesToSize(server.swap_total * 1024, 0)}`;
|
||||
|
||||
// ping ms + lost rate
|
||||
ExpandRow[0].children["expand_ping"].innerHTML = "CU/CT/CM: " + result.servers[i].time_10010 + "ms ("+result.servers[i].ping_10010.toFixed(0)+"%) / " + result.servers[i].time_189 + "ms ("+result.servers[i].ping_189.toFixed(0)+"%) / " + result.servers[i].time_10086 + "ms ("+result.servers[i].ping_10086.toFixed(0)+"%)"
|
||||
const HDD = ((server.hdd_used / server.hdd_total) * 100).toFixed(0);
|
||||
const hddClass = HDD >= 90 ? "progress-bar bg-danger" : HDD >= 80 ? "progress-bar bg-warning" : "progress-bar bg-success";
|
||||
if (TableRow) {
|
||||
const hddBar = TableRow.querySelector("#hdd .progress-bar");
|
||||
if (hddBar) {
|
||||
hddBar.setAttribute("class", hddClass);
|
||||
hddBar.style.width = `${HDD}%`;
|
||||
hddBar.innerHTML = `${HDD}%`;
|
||||
}
|
||||
}
|
||||
const io = `${bytesToSize(server.io_read, 0, true)} / ${bytesToSize(server.io_write, 0, true)}`;
|
||||
if (ExpandRow) ExpandRow.querySelector("#expand_hdd").innerHTML = `硬盘|读写: ${bytesToSize(server.hdd_used * 1024 * 1024, 2)} / ${bytesToSize(server.hdd_total * 1024 * 1024, 2)} | ${io}`;
|
||||
|
||||
if (PING_10010 >= 20 || PING_189 >= 20 || PING_10086 >= 20)
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger";
|
||||
else if (PING_10010 >= 10 || PING_189 >= 10 || PING_10086 >= 10)
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-warning";
|
||||
else
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-success";
|
||||
TableRow.children["ping"].children[0].children[0].innerHTML = PING_10010 + "%💻" + PING_189 + "%💻" + PING_10086 + "%";
|
||||
if (ExpandRow) ExpandRow.querySelector("#expand_tupd").innerHTML = `TCP/UDP/进/线: ${server.tcp_count} / ${server.udp_count} / ${server.process_count} / ${server.thread_count}`;
|
||||
|
||||
// monitor
|
||||
MableRow.children["monitor_text"].innerHTML = result.servers[i].custom;
|
||||
}
|
||||
};
|
||||
const PING_10010 = server.ping_10010.toFixed(0);
|
||||
const PING_189 = server.ping_189.toFixed(0);
|
||||
const PING_10086 = server.ping_10086.toFixed(0);
|
||||
const pingClass = PING_10010 >= 20 || PING_189 >= 20 || PING_10086 >= 20 ? "progress-bar bg-danger" : PING_10010 >= 10 || PING_189 >= 10 || PING_10086 >= 10 ? "progress-bar bg-warning" : "progress-bar bg-success";
|
||||
if (TableRow) {
|
||||
const pingBar = TableRow.querySelector("#ping .progress-bar");
|
||||
if (pingBar) {
|
||||
pingBar.setAttribute("class", pingClass);
|
||||
pingBar.innerHTML = `${PING_10010}%💻${PING_189}%💻${PING_10086}%`;
|
||||
}
|
||||
}
|
||||
if (ExpandRow) ExpandRow.querySelector("#expand_ping").innerHTML = `CU/CT/CM: ${server.time_10010}ms (${PING_10010}%) / ${server.time_189}ms (${PING_189}%) / ${server.time_10086}ms (${PING_10086}%)`;
|
||||
|
||||
d = new Date(result.updated*1000);
|
||||
error = 0;
|
||||
}).fail(function(update_error) {
|
||||
if (!error) {
|
||||
$("#servers > tr.accordion-toggle").each(function(i) {
|
||||
var TableRow = $("#servers tr#r" + i)[0];
|
||||
var MableRow = $("#monitors tr#r" + i)[0];
|
||||
var ExpandRow = $("#servers #rt" + i);
|
||||
TableRow.children["online_status"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["online_status"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
MableRow.children["monitor_status"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
MableRow.children["monitor_status"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["month_traffic"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["month_traffic"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["uptime"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["uptime"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["load"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["load"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["network"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["network"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["traffic"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["traffic"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["cpu"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["cpu"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["cpu"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["memory"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["memory"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["memory"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["hdd"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["hdd"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["hdd"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
TableRow.children["ping"].children[0].children[0].style.width = "100%";
|
||||
TableRow.children["ping"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
MableRow.children["monitor_text"].children[0].children[0].className = "progress-bar progress-bar-error";
|
||||
MableRow.children["monitor_text"].children[0].children[0].innerHTML = "<small>错误</small>";
|
||||
if(ExpandRow.hasClass("in")) {
|
||||
ExpandRow.collapse("hide");
|
||||
}
|
||||
TableRow.setAttribute("data-target", "");
|
||||
MableRow.setAttribute("data-target", "");
|
||||
server_status[i] = false;
|
||||
});
|
||||
}
|
||||
error = 1;
|
||||
$("#updated").html("更新错误.");
|
||||
});
|
||||
if (MableRow) MableRow.querySelector("#monitor_text").innerHTML = server.custom;
|
||||
}
|
||||
});
|
||||
|
||||
d = new Date(result.updated * 1000);
|
||||
error = 0;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Fetch error: ", error);
|
||||
if (!error) {
|
||||
document.querySelectorAll("#servers > tr.accordion-toggle").forEach((TableRow, i) => {
|
||||
const MableRow = document.querySelector(`#monitors tr#r${i}`);
|
||||
const ExpandRow = document.querySelector(`#servers #rt${i}`);
|
||||
|
||||
if (TableRow && MableRow) {
|
||||
TableRow.querySelectorAll(".progress-bar").forEach(bar => {
|
||||
if (bar) {
|
||||
bar.setAttribute("class", "progress-bar bg-danger");
|
||||
bar.innerHTML = "<small>错误</small>";
|
||||
}
|
||||
});
|
||||
|
||||
MableRow.querySelectorAll(".progress-bar").forEach(bar => {
|
||||
if (bar) {
|
||||
bar.setAttribute("class", "progress-bar bg-danger");
|
||||
bar.innerHTML = "<small>错误</small>";
|
||||
}
|
||||
});
|
||||
|
||||
if (ExpandRow && ExpandRow.classList.contains("show")) {
|
||||
ExpandRow.classList.remove("show");
|
||||
}
|
||||
|
||||
TableRow.setAttribute("data-bs-target", "");
|
||||
MableRow.setAttribute("data-bs-target", "");
|
||||
server_status[i] = false;
|
||||
} else {
|
||||
console.error(`TableRow or MableRow is undefined for index ${i}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
error = 1;
|
||||
document.getElementById("updated").innerHTML = "更新错误.";
|
||||
});
|
||||
}
|
||||
|
||||
function updateTime() {
|
||||
if (!error)
|
||||
$("#updated").html("最后更新: " + timeSince(d));
|
||||
if (!error) document.getElementById("updated").innerHTML = "最后更新: " + timeSince(d);
|
||||
}
|
||||
|
||||
uptime();
|
||||
updateTime();
|
||||
// 降低改值,可以减少cpu占用
|
||||
setInterval(uptime, 2000);
|
||||
setInterval(updateTime, 2000);
|
||||
|
||||
|
||||
// styleswitcher.js
|
||||
function setActiveStyleSheet(title, cookie=false) {
|
||||
var i, a, main;
|
||||
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
|
||||
a.disabled = true;
|
||||
if(a.getAttribute("title") == title) a.disabled = false;
|
||||
}
|
||||
}
|
||||
if (true==cookie) {
|
||||
createCookie("style", title, 365);
|
||||
function setActiveStyleSheet(title) {
|
||||
var i, a, main;
|
||||
for (i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if (a.getAttribute("rel").indexOf("stylesheet") != -1 && a.getAttribute("title")) {
|
||||
a.disabled = true;
|
||||
if (a.getAttribute("title") == title) a.disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getActiveStyleSheet() {
|
||||
var i, a;
|
||||
for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
|
||||
if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled)
|
||||
return a.getAttribute("title");
|
||||
}
|
||||
return null;
|
||||
return Array.from(document.getElementsByTagName("link")).find(a => a.getAttribute("rel").includes("style") && a.getAttribute("title") && !a.disabled)?.getAttribute("title") || null;
|
||||
}
|
||||
|
||||
function createCookie(name,value,days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
function createCookie(name, value, days) {
|
||||
const expires = days ? `; expires=${new Date(Date.now() + days * 24 * 60 * 60 * 1000).toGMTString()}` : "";
|
||||
document.cookie = `${name}=${value}${expires}; path=/`;
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==' ')
|
||||
c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0)
|
||||
return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
const nameEQ = name + "=";
|
||||
const ca = document.cookie.split(';');
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
window.onload = function(e) {
|
||||
var cookie = readCookie("style");
|
||||
if (cookie && cookie != 'null' ) {
|
||||
setActiveStyleSheet(cookie);
|
||||
} else {
|
||||
function handleChange (mediaQueryListEvent) {
|
||||
if (mediaQueryListEvent.matches) {
|
||||
setActiveStyleSheet('dark');
|
||||
} else {
|
||||
setActiveStyleSheet('light');
|
||||
}
|
||||
}
|
||||
const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setActiveStyleSheet(mediaQueryListDark.matches ? 'dark' : 'light');
|
||||
mediaQueryListDark.addEventListener("change",handleChange);
|
||||
}
|
||||
}
|
||||
window.onload = function() {
|
||||
const cookie = readCookie("style");
|
||||
if (cookie && cookie != 'null') {
|
||||
setActiveStyleSheet(cookie);
|
||||
} else {
|
||||
const handleChange = mediaQueryListEvent => setActiveStyleSheet(mediaQueryListEvent.matches ? 'dark' : 'light');
|
||||
const mediaQueryListDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setActiveStyleSheet(mediaQueryListDark.matches ? 'dark' : 'light');
|
||||
mediaQueryListDark.addEventListener("change", handleChange);
|
||||
}
|
||||
|
||||
// 处理标签页切换
|
||||
const tabs = document.querySelectorAll('.nav-link');
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', function(event) {
|
||||
if (this.id === 'navbarDropdown') {
|
||||
return; // 阻止“风格”标签的默认行为
|
||||
}
|
||||
event.preventDefault();
|
||||
const target = this.getAttribute('href');
|
||||
document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('show', 'active'));
|
||||
document.querySelector(target).classList.add('show', 'active');
|
||||
tabs.forEach(t => t.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user