32 Commits
1.1.1 ... 1.1.4

Author SHA1 Message Date
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
cppla
6331d7d45b update 2024-03-11 15:06:47 +08:00
cppla
25f878a38a 5分钟一次probe service 2024-03-11 15:03:57 +08:00
cppla
a8b9b2d00d 默认一天在线率 2024-02-04 14:43:19 +08:00
cppla
dc3868998a 256->512 2024-02-04 14:37:39 +08:00
cppla
75d06c8666 add some ua 2024-01-27 15:27:10 +08:00
cppla
360252182d Merge branch 'dev' 2024-01-23 18:51:49 +08:00
cppla
aa0ccd254c update readme 2024-01-23 18:50:15 +08:00
cppla
f7b2e7db42 Merge pull request #242 from cppla/dev
1.1.2 测试
2024-01-23 18:10:19 +08:00
cppla
052c75ef23 update 2024-01-23 18:09:23 +08:00
cppla
1f7827cc21 change 2024-01-23 18:00:24 +08:00
cppla
c236aee5dc todo list 2024-01-23 17:52:59 +08:00
cppla
fb3ecd1796 增加一个todo 2024-01-23 17:43:27 +08:00
cppla
810f6a0d8a fix 2024-01-23 16:47:26 +08:00
cppla
eddf37c413 fix bug 2024-01-23 10:30:43 +08:00
cppla
8dfc6d4718 update 2024-01-22 19:49:29 +08:00
cppla
03446b8f29 update some for cl 2024-01-22 15:34:44 +08:00
cppla
6ab046be51 update 2024-01-22 15:32:20 +08:00
cppla
94708c588c css resize 2024-01-22 15:21:06 +08:00
cppla
144987bcf1 .2f 2024-01-21 22:55:07 +08:00
cppla
7e46b1062e 新增说明,比较粗糙不建议更新 2024-01-21 21:34:07 +08:00
cppla
71cadcfebe 测试监控重要服务 2024-01-21 21:09:37 +08:00
cppla
d96e711a34 change ms and lost rate 2024-01-19 16:03:43 +08:00
cppla
4a9f5adb6b Update index3.html
cppla/Serverstatus version modify
2023-10-17 09:49:44 +08:00
cppla
59fa2d8eab fix light bug 2023-10-17 01:46:19 +00:00
16 changed files with 603 additions and 170 deletions

View File

@@ -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
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 nohup sh -c '/etc/init.d/nginx start && /ServerStatus/server/sergate --config=/ServerStatus/server/config.json --web-dir=/usr/share/nginx/html'

View File

@@ -6,11 +6,12 @@
[![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.1-red)](https://github.com/cppla/ServerStatus)
[![Version](https://img.shields.io/badge/Version-Build%201.1.3-red)](https://github.com/cppla/ServerStatus)
![Latest Version](http://dl.cpp.la/Archive/serverstatus_1.0.9.png)
![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)
`Watchdog触发式告警interval只是为了防止频繁收到报警信息造成的骚扰并不是探测间隔。 同时为了防止海外机器闪断报警也加入username、name、type等静态字符串参数的计算支持。`
`Watchdog触发式告警interval只是为了防止频繁收到报警信息造成的骚扰并不是探测间隔。值得注意的是Exprtk库默认使用窄字符类型中文等Unicode字符无法解析计算等待修复。 `
# 目录:
@@ -67,7 +68,7 @@ cd ServerStatus/server && make
#### 二、修改配置文件
```diff
! watchdog rule 可以为任何已知字段的表达式
! watchdog rule 可以为任何已知字段的表达式。注意Exprtk库默认使用窄字符类型中文等Unicode字符无法解析计算等待修复
! watchdog interval 最小通知间隔
! watchdog callback 可自定义为Post方法的URL告警内容将拼接其后并发起回调
@@ -89,13 +90,21 @@ cd ServerStatus/server && make
"location": "🇨🇳",
"password": "USER_DEFAULT_PASSWORD",
"monthstart": 1
},
}
],
"monitors": [
{
"name": "监测网站以及MySQL、Redis默认为七天在线率",
"host": "https://www.baidu.com",
"interval": 60,
"type": "https"
}
],
"watchdog":
[
{
"name": "服务器负载高监控排除内存大于32G物理机同时排除俄勒冈机器",
"rule": "cpu>90&load_1>4&memory_total<33554432&name!='俄勒冈'",
"name": "服务器负载高监控排除内存大于32G物理机同时排除node1机器",
"rule": "cpu>90&load_1>4&memory_total<33554432&name!='node1'",
"interval": 600,
"callback": "https://yourSMSurl"
},
@@ -106,8 +115,8 @@ cd ServerStatus/server && make
"callback": "https://yourSMSurl"
},
{
"name": "服务器宕机告警排出俄勒冈排除s02",
"rule": "online4=0&online6=0&name!='俄勒冈'&username!='s02'",
"name": "服务器宕机告警",
"rule": "online4=0&online6=0",
"interval": 600,
"callback": "https://yourSMSurl"
},

View File

@@ -3,6 +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
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义例如CU = "www.facebook.com"。
SERVER = "127.0.0.1"
@@ -17,9 +18,11 @@ CM = "cm.tz.cloudcpp.com"
PROBEPORT = 80
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
PING_PACKET_HISTORY_LEN = 100
ONLINE_PACKET_HISTORY_LEN = 288
INTERVAL = 1
import socket
import ssl
import time
import timeit
import re
@@ -29,10 +32,10 @@ import json
import errno
import subprocess
import threading
try:
from queue import Queue # python3
except ImportError:
from Queue import Queue # python2
if sys.version_info.major == 3:
from queue import Queue
elif sys.version_info.major == 2:
from Queue import Queue
def get_uptime():
with open('/proc/uptime', 'r') as f:
@@ -150,6 +153,7 @@ diskIO = {
'read': 0,
'write': 0
}
monitorServer = {}
def _ping_thread(host, mark, port):
lostPacket = 0
@@ -314,6 +318,91 @@ def get_realtime_data():
ti.daemon = True
ti.start()
def _monitor_thread(name, host, interval, type):
lostPacket = 0
packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN)
while True:
if name not in monitorServer.keys():
break
if packet_queue.full():
if packet_queue.get() == 0:
lostPacket -= 1
try:
if type == "http":
address = host.replace("http://", "")
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(address, None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(address, None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, 80), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k.sendall("GET / HTTP/1.2\r\nHost:{}\r\nUser-Agent:ServerStatus/cppla\r\nConnection:close\r\n\r\n".format(address).encode('utf-8'))
response = b""
while True:
data = k.recv(4096)
if not data:
break
response += data
http_code = response.decode('utf-8').split('\r\n')[0].split()[1]
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
k.close()
if http_code not in ['200', '204', '301', '302', '401']:
raise Exception("http code not in 200, 204, 301, 302, 401")
elif type == "https":
context = ssl._create_unverified_context()
address = host.replace("https://", "")
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(address, None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(address, None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, 443), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
kk = context.wrap_socket(k, server_hostname=address)
kk.sendall("GET / HTTP/1.2\r\nHost:{}\r\nUser-Agent:ServerStatus/cppla\r\nConnection:close\r\n\r\n".format(address).encode('utf-8'))
response = b""
while True:
data = kk.recv(4096)
if not data:
break
response += data
http_code = response.decode('utf-8').split('\r\n')[0].split()[1]
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
kk.close()
k.close()
if http_code not in ['200', '204', '301', '302', '401']:
raise Exception("http code not in 200, 204, 301, 302, 401")
elif type == "tcp":
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(host.split(":")[0], None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(host.split(":")[0], None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, int(host.split(":")[1])), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k.send(b"GET / HTTP/1.2\r\n\r\n")
k.recv(1024)
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
k.close()
packet_queue.put(1)
except Exception as e:
lostPacket += 1
packet_queue.put(0)
if packet_queue.qsize() > 5:
monitorServer[name]["online_rate"] = 1 - float(lostPacket) / packet_queue.qsize()
time.sleep(interval)
def byte_str(object):
'''
bytes to str, str to bytes
@@ -360,6 +449,28 @@ if __name__ == '__main__':
if data.find("You are connecting via") < 0:
data = byte_str(s.recv(1024))
print(data)
monitorServer.clear()
for i in data.split('\n'):
if "monitor" in i and "type" in i and "{" in i and "}" in i:
jdata = json.loads(i[i.find("{"):i.find("}")+1])
monitorServer[jdata.get("name")] = {
"type": jdata.get("type"),
"dns_time": 0,
"connect_time": 0,
"download_time": 0,
"online_rate": 1
}
t = threading.Thread(
target=_monitor_thread,
kwargs={
'name': jdata.get("name"),
'host': jdata.get("host"),
'interval': jdata.get("interval"),
'type': jdata.get("type")
}
)
t.daemon = True
t.start()
timer = 0
check_ip = 0
@@ -378,7 +489,6 @@ if __name__ == '__main__':
Load_1, Load_5, Load_15 = os.getloadavg()
MemoryTotal, MemoryUsed, SwapTotal, SwapFree = get_memory()
HDDTotal, HDDUsed = get_hdd()
array = {}
if not timer:
array['online' + str(check_ip)] = get_network(check_ip)
@@ -401,8 +511,6 @@ if __name__ == '__main__':
array['network_tx'] = netSpeed.get("nettx")
array['network_in'] = NET_IN
array['network_out'] = NET_OUT
# todo兼容旧版本下个版本删除ip_status
array['ip_status'] = True
array['ping_10010'] = lostRate.get('10010') * 100
array['ping_189'] = lostRate.get('189') * 100
array['ping_10086'] = lostRate.get('10086') * 100
@@ -412,16 +520,18 @@ if __name__ == '__main__':
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
array['io_read'] = diskIO.get("read")
array['io_write'] = diskIO.get("write")
array['custom'] = "<br>".join(f"{k}\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100:.1f}%</code>" for k, v in monitorServer.items())
s.send(byte_str("update " + json.dumps(array) + "\n"))
except KeyboardInterrupt:
raise
except socket.error:
monitorServer.clear()
print("Disconnected...")
if 's' in locals().keys():
del s
time.sleep(3)
except Exception as e:
monitorServer.clear()
print("Caught Exception:", e)
if 's' in locals().keys():
del s

View File

@@ -4,6 +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
# 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义例如CU = "www.facebook.com"。
SERVER = "127.0.0.1"
@@ -18,9 +19,11 @@ CM = "cm.tz.cloudcpp.com"
PROBEPORT = 80
PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6
PING_PACKET_HISTORY_LEN = 100
ONLINE_PACKET_HISTORY_LEN = 288
INTERVAL = 1
import socket
import ssl
import time
import timeit
import os
@@ -29,10 +32,10 @@ import json
import errno
import psutil
import threading
try:
from queue import Queue # python3
except ImportError:
from Queue import Queue # python2
if sys.version_info.major == 3:
from queue import Queue
elif sys.version_info.major == 2:
from Queue import Queue
def get_uptime():
return int(time.time() - psutil.boot_time())
@@ -148,6 +151,7 @@ diskIO = {
'read': 0,
'write': 0
}
monitorServer = {}
def _ping_thread(host, mark, port):
lostPacket = 0
@@ -303,6 +307,91 @@ def get_realtime_data():
ti.daemon = True
ti.start()
def _monitor_thread(name, host, interval, type):
lostPacket = 0
packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN)
while True:
if name not in monitorServer.keys():
break
if packet_queue.full():
if packet_queue.get() == 0:
lostPacket -= 1
try:
if type == "http":
address = host.replace("http://", "")
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(address, None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(address, None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, 80), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k.sendall("GET / HTTP/1.2\r\nHost:{}\r\nUser-Agent:ServerStatus/cppla\r\nConnection:close\r\n\r\n".format(address).encode('utf-8'))
response = b""
while True:
data = k.recv(4096)
if not data:
break
response += data
http_code = response.decode('utf-8').split('\r\n')[0].split()[1]
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
k.close()
if http_code not in ['200', '204', '301', '302', '401']:
raise Exception("http code not in 200, 204, 301, 302, 401")
elif type == "https":
context = ssl._create_unverified_context()
address = host.replace("https://", "")
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(address, None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(address, None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, 443), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
kk = context.wrap_socket(k, server_hostname=address)
kk.sendall("GET / HTTP/1.2\r\nHost:{}\r\nUser-Agent:ServerStatus/cppla\r\nConnection:close\r\n\r\n".format(address).encode('utf-8'))
response = b""
while True:
data = kk.recv(4096)
if not data:
break
response += data
http_code = response.decode('utf-8').split('\r\n')[0].split()[1]
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
kk.close()
k.close()
if http_code not in ['200', '204', '301', '302', '401']:
raise Exception("http code not in 200, 204, 301, 302, 401")
elif type == "tcp":
m = timeit.default_timer()
if PROBE_PROTOCOL_PREFER == 'ipv4':
IP = socket.getaddrinfo(host.split(":")[0], None, socket.AF_INET)[0][4][0]
else:
IP = socket.getaddrinfo(host.split(":")[0], None, socket.AF_INET6)[0][4][0]
monitorServer[name]["dns_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k = socket.create_connection((IP, int(host.split(":")[1])), timeout=6)
monitorServer[name]["connect_time"] = int((timeit.default_timer() - m) * 1000)
m = timeit.default_timer()
k.send(b"GET / HTTP/1.2\r\n\r\n")
k.recv(1024)
monitorServer[name]["download_time"] = int((timeit.default_timer() - m) * 1000)
k.close()
packet_queue.put(1)
except Exception as e:
lostPacket += 1
packet_queue.put(0)
if packet_queue.qsize() > 5:
monitorServer[name]["online_rate"] = 1 - float(lostPacket) / packet_queue.qsize()
time.sleep(interval)
def byte_str(object):
'''
bytes to str, str to bytes
@@ -349,6 +438,27 @@ if __name__ == '__main__':
if data.find("You are connecting via") < 0:
data = byte_str(s.recv(1024))
print(data)
for i in data.split('\n'):
if "monitor" in i and "type" in i and "{" in i and "}" in i:
jdata = json.loads(i[i.find("{"):i.find("}")+1])
monitorServer[jdata.get("name")] = {
"type": jdata.get("type"),
"dns_time": 0,
"connect_time": 0,
"download_time": 0,
"online_rate": 1
}
t = threading.Thread(
target=_monitor_thread,
kwargs={
'name': jdata.get("name"),
'host': jdata.get("host"),
'interval': jdata.get("interval"),
'type': jdata.get("type")
}
)
t.daemon = True
t.start()
timer = 0
check_ip = 0
@@ -368,7 +478,6 @@ if __name__ == '__main__':
MemoryTotal, MemoryUsed = get_memory()
SwapTotal, SwapUsed = get_swap()
HDDTotal, HDDUsed = get_hdd()
array = {}
if not timer:
array['online' + str(check_ip)] = get_network(check_ip)
@@ -391,8 +500,6 @@ if __name__ == '__main__':
array['network_tx'] = netSpeed.get("nettx")
array['network_in'] = NET_IN
array['network_out'] = NET_OUT
# todo兼容旧版本下个版本删除ip_status
array['ip_status'] = True
array['ping_10010'] = lostRate.get('10010') * 100
array['ping_189'] = lostRate.get('189') * 100
array['ping_10086'] = lostRate.get('10086') * 100
@@ -402,16 +509,18 @@ if __name__ == '__main__':
array['tcp'], array['udp'], array['process'], array['thread'] = tupd()
array['io_read'] = diskIO.get("read")
array['io_write'] = diskIO.get("write")
array['custom'] = "<br>".join(f"{k}\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100:.2f}%</code>" for k, v in monitorServer.items())
s.send(byte_str("update " + json.dumps(array) + "\n"))
except KeyboardInterrupt:
raise
except socket.error:
monitorServer.clear()
print("Disconnected...")
if 's' in locals().keys():
del s
time.sleep(3)
except Exception as e:
monitorServer.clear()
print("Caught Exception:", e)
if 's' in locals().keys():
del s

View File

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

View File

@@ -38,6 +38,26 @@
"monthstart": 1
}
],
"monitors": [
{
"name": "baidu",
"host": "https://www.baidu.com",
"interval": 300,
"type": "https"
},
{
"name": "aliyun",
"host": "https://www.aliyun.com",
"interval": 300,
"type": "https"
},
{
"name": "114",
"host": "114.114.114.114:53",
"interval": 300,
"type": "tcp"
}
],
"watchdog": [
{
"name": "cpu high warning,exclude username s01",
@@ -52,23 +72,23 @@
"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"
},
{
"name": "ddcc attack,limit type Oracle",
"rule": "tcp_count>600&type='Oracle'",
"interval": 300,
"callback": "https://yourSMSurl"
},
"name": "ddcc attack,limit type Oracle",
"rule": "tcp_count>600&type='Oracle'",
"interval": 300,
"callback": "https://yourSMSurl"
},
{
"name": "month traffic warning",
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
"interval": 3600,
"callback": "https://yourSMSurl"
},
"name": "month traffic warning",
"rule": "(network_out-last_network_out)/1024/1024/1024>999",
"interval": 3600,
"callback": "https://yourSMSurl"
},
{
"name": "you can parse an expression combining any known field",
"rule": "load_5>3",

View File

@@ -92,19 +92,24 @@ void CMain::OnNewClient(int ClientNetID, int ClientID)
Client(ClientID)->m_Stats.m_Online4 = true;
else if(Client(ClientID)->m_ClientNetType == NETTYPE_IPV6)
Client(ClientID)->m_Stats.m_Online6 = true;
// Send monitor to client
// support by cpp.la
int ID = 0;
char monitorBuffer[2048];
while (strcmp(Monitors(ID)->m_aName, "NULL"))
{
memset(monitorBuffer, 0, sizeof(monitorBuffer));
sprintf(monitorBuffer, "{\"name\":\"%s\",\"host\":\"%s\",\"interval\":%d,\"type\":\"%s\",\"monitor\":%d}", Monitors(ID)->m_aName, Monitors(ID)->m_aHost, Monitors(ID)->m_aInterval, Monitors(ID)->m_aType, ID);
m_Server.Network()->Send(ClientNetID, monitorBuffer);
ID++;
}
}
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;
@@ -112,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)
@@ -266,6 +275,23 @@ void CMain::WatchdogMessage(int ClientNetID, double load_1, double load_5, doubl
int ID = 0;
while (strcmp(Watchdog(ID)->m_aName, "NULL"))
{
// Exprtk库默认使用窄字符类型但可能会出现中文等Unicode字符无法正确解析的问题。
// todo: 为解决此问题可以使用宽字符类型替换Exprtk库中默认的窄字符类型。
// #include <string>
// #include <vector>
// #include <exprtk.hpp>
// typedef exprtk::expression<wchar_t> expression_type;
// typedef exprtk::parser<wchar_t> parser_type;
// int main()
// {
// std::wstring expression_string = L"sin(x)";
// expression_type expression;
// parser_type parser;
// parser.compile(expression_string, expression);
// double x = 3.14;
// double result = expression.value();
// return 0;
// }
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
@@ -324,6 +350,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;
@@ -469,6 +500,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(6000);
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
@@ -572,6 +706,28 @@ int CMain::ReadConfig()
} else
str_copy(Watchdog(ID)->m_aName, "NULL", sizeof(Watchdog(ID)->m_aName));
// monitor
// support by: https://cpp.la
ID = 0;
const json_value &mStart = (*pJsonData)["monitors"];
if(mStart.type == json_array)
{
for(unsigned i = 0; i < mStart.u.array.length; i++)
{
if(ID < 0 || ID >= NET_MAX_CLIENTS)
continue;
str_copy(Monitors(ID)->m_aName, mStart[i]["name"].u.string.ptr, sizeof(Monitors(ID)->m_aName));
str_copy(Monitors(ID)->m_aHost, mStart[i]["host"].u.string.ptr, sizeof(Monitors(ID)->m_aHost));
Monitors(ID)->m_aInterval = mStart[i]["interval"].u.integer;
str_copy(Monitors(ID)->m_aType, mStart[i]["type"].u.string.ptr, sizeof(Monitors(ID)->m_aType));
ID++;
}
str_copy(Monitors(ID)->m_aName, "NULL", sizeof(Monitors(ID)->m_aName));
} else
str_copy(Monitors(ID)->m_aName, "NULL", sizeof(Monitors(ID)->m_aName));
// if file exists, read last network traffic recordreset m_LastNetworkIN and m_LastNetworkOUT
// support by: https://cpp.la
IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ);
@@ -645,6 +801,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);

View File

@@ -77,7 +77,7 @@ class CMain
int64_t m_IORead;
int64_t m_IOWrite;
double m_CPU;
char m_aCustom[512];
char m_aCustom[1024];
// Options
bool m_Pong;
} m_Stats;
@@ -90,14 +90,23 @@ class CMain
char m_aCallback[1024];
} m_aCWatchDogs[NET_MAX_CLIENTS];
struct CMonitors{
char m_aName[128];
char m_aHost[128];
int m_aInterval;
char m_aType[128];
} m_aCMonitors[NET_MAX_CLIENTS];
struct CJSONUpdateThreadData
{
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);
@@ -108,6 +117,8 @@ public:
int Run();
CWatchDog *Watchdog(int ruleID) { return &m_aCWatchDogs[ruleID]; }
CMonitors *Monitors(int ruleID) { return &m_aCMonitors[ruleID]; }
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,

View File

@@ -10,7 +10,7 @@ enum
NET_CONNSTATE_ERROR=4,
NET_MAX_PACKETSIZE = 1400,
NET_MAX_CLIENTS = 256
NET_MAX_CLIENTS = 512
};
typedef int (*NETFUNC_DELCLIENT)(int ClientID, const char* pReason, void *pUser);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -20,51 +20,29 @@ tr.odd.expandRow > :hover { background: #212e36 !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: 110px; }
#ping { max-width: 115px; }
@media only screen and (max-width: 1200px) {
#type, tr td:nth-child(4) { 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; }
#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; }
}
@media only screen and (max-width: 720px) {
body { font-size: 10px; }
.content { padding: 0; }
#type, tr td:nth-child(4) { 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; }
#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; }
}
@media only screen and (max-width: 620px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#type, tr td:nth-child(4) { 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; }
}
@media only screen and (max-width: 533px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#type, tr td:nth-child(4) { 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; }
}
@media only screen and (max-width: 450px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
#type, tr td:nth-child(4) { 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; }
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
}
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; }
}

View File

@@ -17,51 +17,29 @@ tr.odd.expandRow > :hover { background: #FFF !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: 110px; }
#ping { max-width: 115px; }
@media only screen and (max-width: 1200px) {
#type, tr td:nth-child(4) { 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; }
#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; }
}
@media only screen and (max-width: 720px) {
body { font-size: 10px; }
.content { padding: 0; }
#type, tr td:nth-child(4) { 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; }
#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; }
}
@media only screen and (max-width: 620px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#type, tr td:nth-child(4) { 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; }
}
@media only screen and (max-width: 533px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#type, tr td:nth-child(4) { 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; }
}
@media only screen and (max-width: 450px) {
body { font-size: 10px; }
.content { padding: 0; }
#month_traffic, tr td:nth-child(2) { display:none; visibility:hidden; }
#name, tr td:nth-child(3) { min-width: 55px; max-width: 85px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
#type, tr td:nth-child(4) { 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; }
#cpu, #ram, #hdd { min-width: 25px; max-width: 50px; }
#ping, tr td:nth-child(13) { display:none; visibility:hidden; }
}
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; }
}

View File

@@ -47,6 +47,12 @@
</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">
@@ -73,28 +79,51 @@
</div>
<p></p>
</div>
<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 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>
<br />
<div id="updated">Updating...</div>
</div>

View File

@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ServerStatus</title>
<link rel="shortcut icon" href="./assets/favicon-65bd9f8a.png" type="image/x-icon">
<script type="module" crossorigin src="./assets/index-982ea826.js"></script>
<script type="module" crossorigin src="./assets/index-e069a4f0.js"></script>
<link rel="stylesheet" href="./assets/index-282247e3.css">
</head>
@@ -17,8 +17,8 @@
</h1>
<div id="app"></div>
<div class="text-center absolute left-0 bottom-0 py-4 w-full">
Powered by <a class="text-blue-500" href="https://github.com/zdz/ServerStatus-Rust"
target="_blank">ServerStatus-Rust</a>.
Powered by <a class="text-blue-500" href="https://github.com/cppla/ServerStatus"
target="_blank">ServerStatus中文版</a>.
Theme <a class="text-blue-500" href="https://github.com/orilights/ServerStatus-Theme-Light"
target="_blank">Light</a> by <a class="text-blue-500" href="https://orilight.top/" target="_blank">OriLight</a>
</div>

View File

@@ -57,6 +57,7 @@ function uptime() {
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";
@@ -82,17 +83,28 @@ function uptime() {
"<div id=\"expand_hdd\">加载中</div>" +
"<div id=\"expand_tupd\">加载中</div>" +
"<div id=\"expand_ping\">加载中</div>" +
"<div id=\"expand_lost\">加载中</div>" +
"<div id=\"expand_custom\">加载中</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;
}
@@ -100,25 +112,35 @@ function uptime() {
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>";
}
// Name
TableRow.children["name"].innerHTML = result.servers[i].name;
MableRow.children["monitor_node"].innerHTML = result.servers[i].name;
// Type
TableRow.children["type"].innerHTML = result.servers[i].type;
// 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 = "";
@@ -139,15 +161,18 @@ function uptime() {
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;
}
@@ -255,13 +280,14 @@ function uptime() {
// 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;
ExpandRow[0].children["expand_ping"].innerHTML = "联通/电信/移动: " + result.servers[i].time_10010 + "ms / " + result.servers[i].time_189 + "ms / " + result.servers[i].time_10086 + "ms"
// 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);
ExpandRow[0].children["expand_lost"].innerHTML = "丢包:联通/电信/移动: " + PING_10010 + "% / " + PING_189 + "% / " + PING_10086 + "%"
// 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)+"%)"
if (PING_10010 >= 20 || PING_189 >= 20 || PING_10086 >= 20)
TableRow.children["ping"].children[0].children[0].className = "progress-bar progress-bar-danger";
@@ -271,12 +297,8 @@ function uptime() {
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 + "%";
// Custom
if (result.servers[i].custom) {
ExpandRow[0].children["expand_custom"].innerHTML = result.servers[i].custom
} else {
ExpandRow[0].children["expand_custom"].innerHTML = ""
}
// monitor
MableRow.children["monitor_text"].innerHTML = result.servers[i].custom;
}
};
@@ -286,9 +308,12 @@ function uptime() {
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";
@@ -311,10 +336,13 @@ function uptime() {
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;
});
}