Compare commits

...

38 Commits

Author SHA1 Message Date
cppla
830938eac9
Update README.md 2025-04-01 10:35:26 +08:00
cppla
1a764ed104 1111 2024-12-02 14:13:00 +08:00
cppla
b0c543b44b update Dockerfile 2024-11-25 17:39:07 +08:00
cppla
f85c0a87f9 update tcp example 2024-11-25 16:50:32 +08:00
cppla
67d7c5ea0f
Merge pull request from ArashPartow/arashpartow/update_exprtk_0.0.3
Update ExprTk to 0.0.3
2024-11-25 16:42:00 +08:00
cppla
8576f81404 some update for probe tcp slow 2024-11-18 13:56:01 +08:00
cppla
fa0ee2bf57 重要线路丢包率告警例子 2024-09-18 13:24:06 +08:00
cppla
e9776b0e69 增加重要节点丢包率监控 2024-09-18 10:07:43 +08:00
cppla
e01cc118dc update css 2024-09-13 09:26:07 +08:00
cppla
784c40b153
Update README.md 2024-09-11 18:01:05 +08:00
cppla
6068a2ba17 yes 2024-09-11 17:54:24 +08:00
cppla
ced526824f 增加阿里云免费20G告警示例,限制username是aliyun1和aliyun2 2024-09-09 19:18:42 +08:00
cppla
7d2a73bf2e 修复月流量监控的bug,月流量加入表达式计算 2024-09-09 18:55:11 +08:00
cppla
51e2f664cd update theme set bug 2024-08-18 21:16:38 +08:00
cppla
937b1ea90f fix some bug 2024-08-18 21:13:53 +08:00
cppla
b95d1945bf
Update README.md 2024-08-18 19:44:57 +08:00
cppla
e8446cd52f
我震惊的是AI已经能够帮助重构前端页面
我震惊的是AI已经能够帮助重构前端页面
2024-08-18 13:09:25 +08:00
cppla
6098f0fb1a commit new css by ai 2024-08-18 13:00:45 +08:00
cppla
fc89a76cc2 resize css 2024-08-17 18:50:43 +08:00
cppla
f290947b2c update theme 2024-08-17 17:36:57 +08:00
cppla
b3adc6b782 update all 2024-08-17 17:31:40 +08:00
cppla
705a957606 bai piao copilot 2024-08-15 19:32:50 +08:00
cppla
a307ad7d19 ai niu bi 2024-08-15 15:59:26 +08:00
cppla
ad95e00723 不更新代码 无法续Copilot 2024-08-15 14:46:49 +08:00
cppla
31330168f3 ai modify 2024-08-15 14:18:34 +08:00
cppla
d9e8f8a7c1 del ie 2024-08-15 14:02:33 +08:00
cppla
08f15ebdc5 15s -> 25s 2024-04-18 15:34:43 +08:00
cppla
adb05818b9 改为15秒再次判断是否离线 2024-04-08 14:25:53 +08:00
cppla
4e73e8185e
Update README.md 2024-04-03 22:06:15 +08:00
cppla
0fe01064a4
Update README.md 2024-04-03 21:59:23 +08:00
cppla
510567eaec 修复驴头不对马嘴的bug 2024-04-03 21:31:35 +08:00
cppla
503037c7e2 add two logs 2024-04-03 19:53:04 +08:00
cppla
d75d5438a3 docker compose healthcheck 2024-04-03 17:44:43 +08:00
cppla
91f11dad76 屏蔽无用的nginx日志,增加健康检查wq 2024-04-03 17:16:32 +08:00
cppla
fdc5abacfc fix bug for offline 2024-04-03 16:42:40 +08:00
cppla
388938e02b 解决了网络闪断导致的错误报警 2024-04-03 16:39:08 +08:00
cppla
f912794068 add todo 2024-04-02 10:24:12 +08:00
Arash Partow
5ebf076330 Update ExprTk to 0.0.3 2024-01-01 00:00:00 +00:00
22 changed files with 10193 additions and 5164 deletions

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

@ -1,17 +1,16 @@
# ServerStatus中文版
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
* ServerStatus中文版是一个酷炫高逼格的云探针、云监控、服务器云监控、多服务器探针~。
* 在线演示https://tz.cloudcpp.com
[![Python Support](https://img.shields.io/badge/python-3.6%2B%20-blue.svg)](https://github.com/cppla/ServerStatus)
[![C++ Compiler](http://img.shields.io/badge/C++-GNU-blue.svg?style=flat&logo=cplusplus)](https://github.com/cppla/ServerStatus)
[![License](https://img.shields.io/badge/license-MIT-4EB1BA.svg?style=flat-square)](https://github.com/cppla/ServerStatus)
[![Version](https://img.shields.io/badge/Version-Build%201.1.2-red)](https://github.com/cppla/ServerStatus)
[![Version](https://img.shields.io/badge/Version-Build%201.1.5-red)](https://github.com/cppla/ServerStatus)
![Latest Host Version](https://dl.cpp.la/Archive/serverstatus_1.1.2_host.png)
![Latest Server Version](https://dl.cpp.la/Archive/serverstatus_1.1.2_server.png)
![Latest Host Version](https://dl.cpp.la/Archive/serverstatus_1.1.5.png)
`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",

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(&currentStamp));
//url encode, Rules conflict with url special characterseg&, 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]; }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

@ -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='&shy;<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');
});
});
}