From d96e711a34ce621b5a37e0506e8b315f0a5bf10a Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Fri, 19 Jan 2024 16:03:43 +0800 Subject: [PATCH 01/14] change ms and lost rate --- web/js/serverstatus.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/js/serverstatus.js b/web/js/serverstatus.js index ce3a692..43c1237 100644 --- a/web/js/serverstatus.js +++ b/web/js/serverstatus.js @@ -82,7 +82,6 @@ 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>" ); @@ -255,13 +254,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"; From 71cadcfebe05d97fb609b2b380ff82213f01faa0 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Sun, 21 Jan 2024 21:09:37 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E9=87=8D=E8=A6=81=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clients/client-linux.py | 118 +++++++++++++++++++++++++++++++++++++-- clients/client-psutil.py | 118 +++++++++++++++++++++++++++++++++++++-- server/config.json | 40 +++++++++---- server/src/main.cpp | 34 +++++++++++ server/src/main.h | 11 +++- web/css/dark.css | 66 +++++++++------------- web/css/light.css | 66 +++++++++------------- web/index.html | 73 ++++++++++++++++-------- web/js/serverstatus.js | 42 +++++++++++--- 9 files changed, 434 insertions(+), 134 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 00e59d5..0574453 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -20,6 +20,7 @@ PING_PACKET_HISTORY_LEN = 100 INTERVAL = 1 import socket +import ssl import time import timeit import re @@ -29,10 +30,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 +151,7 @@ diskIO = { 'read': 0, 'write': 0 } +monitorServer = {} def _ping_thread(host, mark, port): lostPacket = 0 @@ -314,6 +316,97 @@ def get_realtime_data(): ti.daemon = True ti.start() + +def _monitor_thread(name, host, interval, type): + lostPacket = 0 + packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) + while True: + if name not in monitorServer.keys(): + monitorServer[name] = { + "type": type, + "dns_time": 0, + "connect_time": 0, + "download_time": 0, + "online_rate": 1 + } + 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\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\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 +453,20 @@ 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]) + 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 +485,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) @@ -412,7 +518,7 @@ 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"<code>{k}</code>\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100}%</code>" for k, v in monitorServer.items()) s.send(byte_str("update " + json.dumps(array) + "\n")) except KeyboardInterrupt: raise diff --git a/clients/client-psutil.py b/clients/client-psutil.py index ceac788..c2b3928 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -21,6 +21,7 @@ PING_PACKET_HISTORY_LEN = 100 INTERVAL = 1 import socket +import ssl import time import timeit import os @@ -29,10 +30,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 +149,7 @@ diskIO = { 'read': 0, 'write': 0 } +monitorServer = {} def _ping_thread(host, mark, port): lostPacket = 0 @@ -303,6 +305,97 @@ def get_realtime_data(): ti.daemon = True ti.start() +def _monitor_thread(name, host, interval, type): + lostPacket = 0 + packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) + while True: + if name not in monitorServer.keys(): + monitorServer[name] = { + "type": type, + "dns_time": 0, + "connect_time": 0, + "download_time": 0, + "online_rate": 1 + } + 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\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\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 +442,20 @@ 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]) + 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 +475,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) @@ -402,7 +508,7 @@ 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"<code>{k}</code>\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100}%</code>" for k, v in monitorServer.items()) s.send(byte_str("update " + json.dumps(array) + "\n")) except KeyboardInterrupt: raise diff --git a/server/config.json b/server/config.json index c60018f..29a4df4 100644 --- a/server/config.json +++ b/server/config.json @@ -38,6 +38,26 @@ "monthstart": 1 } ], + "monitors": [ + { + "name": "百度一下", + "host": "https://www.baidu.com", + "interval": 60, + "type": "https" + }, + { + "name": "主机交流", + "host": "https://www.hostloc.com", + "interval": 60, + "type": "https" + }, + { + "name": "DNS服务", + "host": "114.114.114.114:53", + "interval": 60, + "type": "tcp" + } + ], "watchdog": [ { "name": "cpu high warning,exclude username s01", @@ -58,17 +78,17 @@ "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", diff --git a/server/src/main.cpp b/server/src/main.cpp index d24d605..2dc5c43 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -92,6 +92,18 @@ 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) @@ -572,6 +584,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 record,reset m_LastNetworkIN and m_LastNetworkOUT // support by: https://cpp.la IOHANDLE nFile = io_open(m_Config.m_aJSONFile, IOFLAG_READ); diff --git a/server/src/main.h b/server/src/main.h index eb3fb3e..848d246 100644 --- a/server/src/main.h +++ b/server/src/main.h @@ -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,6 +90,13 @@ 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; @@ -108,6 +115,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, diff --git a/web/css/dark.css b/web/css/dark.css index 5bfb949..eea98f3 100644 --- a/web/css/dark.css +++ b/web/css/dark.css @@ -23,48 +23,32 @@ tr.odd.expandRow > :hover { background: #212e36 !important; } #ping { max-width: 110px; } @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; } + #server { + #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; } + } } @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; } + #server { + 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; } + } } @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; } -} + #server { + 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; } + } +} \ No newline at end of file diff --git a/web/css/light.css b/web/css/light.css index e881dcb..37e7f77 100644 --- a/web/css/light.css +++ b/web/css/light.css @@ -20,48 +20,32 @@ tr.odd.expandRow > :hover { background: #FFF !important; } #ping { max-width: 110px; } @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; } + #server { + #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; } + } } @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; } + #server { + 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; } + } } @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; } -} + #server { + 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; } + } +} \ No newline at end of file diff --git a/web/index.html b/web/index.html index ed68d63..5fa6175 100644 --- a/web/index.html +++ b/web/index.html @@ -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> diff --git a/web/js/serverstatus.js b/web/js/serverstatus.js index 43c1237..529456c 100644 --- a/web/js/serverstatus.js +++ b/web/js/serverstatus.js @@ -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,16 +83,28 @@ function uptime() { "<div id=\"expand_hdd\">加载中</div>" + "<div id=\"expand_tupd\">加载中</div>" + "<div id=\"expand_ping\">加载中</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-toggle=\"collapse\" 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; } @@ -99,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 = "–"; @@ -138,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; } @@ -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; }); } From 7e46b1062e49225a324726a3a9c3cac600430b8f Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Sun, 21 Jan 2024 21:34:07 +0800 Subject: [PATCH 03/14] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=EF=BC=8C=E6=AF=94=E8=BE=83=E7=B2=97=E7=B3=99=E4=B8=8D=E5=BB=BA?= =?UTF-8?q?=E8=AE=AE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clients/client-linux.py | 4 +++- clients/client-psutil.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 0574453..4d79bed 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -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, 探测间隔60s,记录24小时在线率(1440);探测间隔60s,记录7天(10080);探测时间30s,记录24小时(2880) # 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。 SERVER = "127.0.0.1" @@ -17,6 +18,7 @@ CM = "cm.tz.cloudcpp.com" PROBEPORT = 80 PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6 PING_PACKET_HISTORY_LEN = 100 +ONLINE_PACKET_HISTORY_LEN = 1440 INTERVAL = 1 import socket @@ -319,7 +321,7 @@ def get_realtime_data(): def _monitor_thread(name, host, interval, type): lostPacket = 0 - packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) + packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN) while True: if name not in monitorServer.keys(): monitorServer[name] = { diff --git a/clients/client-psutil.py b/clients/client-psutil.py index c2b3928..d468fcb 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -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, 探测间隔60s,记录24小时在线率(1440);探测时间60s,记录7天在线率(10080);探测时间30s,记录24小时(2880) # 说明: 默认情况下修改server和user就可以了。丢包率监测方向可以自定义,例如:CU = "www.facebook.com"。 SERVER = "127.0.0.1" @@ -18,6 +19,7 @@ CM = "cm.tz.cloudcpp.com" PROBEPORT = 80 PROBE_PROTOCOL_PREFER = "ipv4" # ipv4, ipv6 PING_PACKET_HISTORY_LEN = 100 +ONLINE_PACKET_HISTORY_LEN = 1440 INTERVAL = 1 import socket @@ -307,7 +309,7 @@ def get_realtime_data(): def _monitor_thread(name, host, interval, type): lostPacket = 0 - packet_queue = Queue(maxsize=PING_PACKET_HISTORY_LEN) + packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN) while True: if name not in monitorServer.keys(): monitorServer[name] = { From 144987bcf119e5c6c462b9cd55e462cec0bbd259 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Sun, 21 Jan 2024 22:55:07 +0800 Subject: [PATCH 04/14] .2f --- clients/client-linux.py | 2 +- clients/client-psutil.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 4d79bed..9f3e315 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -520,7 +520,7 @@ 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"<code>{k}</code>\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100}%</code>" for k, v in monitorServer.items()) + array['custom'] = "<br>".join(f"<code>{k}</code>\\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 diff --git a/clients/client-psutil.py b/clients/client-psutil.py index d468fcb..4e9c1f6 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -510,7 +510,7 @@ 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"<code>{k}</code>\\t解析: {v['dns_time']}\\t连接: {v['connect_time']}\\t下载: {v['download_time']}\\t在线率: <code>{v['online_rate']*100}%</code>" for k, v in monitorServer.items()) + array['custom'] = "<br>".join(f"<code>{k}</code>\\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 From 94708c588cab6ec3cb18df78b7d70220b5f7091c Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Mon, 22 Jan 2024 15:21:06 +0800 Subject: [PATCH 05/14] css resize --- web/css/dark.css | 44 +++++++++++++++++++------------------------- web/css/light.css | 44 +++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 50 deletions(-) diff --git a/web/css/dark.css b/web/css/dark.css index eea98f3..0d6881c 100644 --- a/web/css/dark.css +++ b/web/css/dark.css @@ -20,35 +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) { - #server { - #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) { - #server { - 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) { - #server { - 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; } - } + 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; } } \ No newline at end of file diff --git a/web/css/light.css b/web/css/light.css index 37e7f77..811c8d0 100644 --- a/web/css/light.css +++ b/web/css/light.css @@ -17,35 +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) { - #server { - #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) { - #server { - 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) { - #server { - 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; } - } + 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; } } \ No newline at end of file From 6ab046be51683c064bf38a97e5236e184d9b9378 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Mon, 22 Jan 2024 15:32:20 +0800 Subject: [PATCH 06/14] update --- clients/client-linux.py | 4 ++-- clients/client-psutil.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 9f3e315..8de029d 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -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 = 1440 +ONLINE_PACKET_HISTORY_LEN = 10080 INTERVAL = 1 import socket @@ -520,7 +520,7 @@ 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"<code>{k}</code>\\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()) + 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 diff --git a/clients/client-psutil.py b/clients/client-psutil.py index 4e9c1f6..4946a45 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -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 = 1440 +ONLINE_PACKET_HISTORY_LEN = 10080 INTERVAL = 1 import socket @@ -510,7 +510,7 @@ 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"<code>{k}</code>\\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()) + 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 From 03446b8f29a1d5e6d4998281439aed12b170d587 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Mon, 22 Jan 2024 15:34:44 +0800 Subject: [PATCH 07/14] update some for cl --- clients/client-linux.py | 2 -- clients/client-psutil.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 8de029d..8ebb327 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -509,8 +509,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 diff --git a/clients/client-psutil.py b/clients/client-psutil.py index 4946a45..278db93 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -499,8 +499,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 From 8dfc6d4718fe209ea9160401d0e6e489e60c3eca Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Mon, 22 Jan 2024 19:49:29 +0800 Subject: [PATCH 08/14] update --- clients/client-linux.py | 1 + clients/client-psutil.py | 1 + 2 files changed, 2 insertions(+) diff --git a/clients/client-linux.py b/clients/client-linux.py index 8ebb327..5a6bd1c 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -455,6 +455,7 @@ 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]) diff --git a/clients/client-psutil.py b/clients/client-psutil.py index 278db93..da871b8 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -444,6 +444,7 @@ 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]) From eddf37c413667dc46b32d6845b33522ba6ae361f Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 10:30:43 +0800 Subject: [PATCH 09/14] fix bug --- clients/client-linux.py | 17 ++++++++++------- clients/client-psutil.py | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/clients/client-linux.py b/clients/client-linux.py index 5a6bd1c..fc65827 100755 --- a/clients/client-linux.py +++ b/clients/client-linux.py @@ -324,13 +324,7 @@ def _monitor_thread(name, host, interval, type): packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN) while True: if name not in monitorServer.keys(): - monitorServer[name] = { - "type": type, - "dns_time": 0, - "connect_time": 0, - "download_time": 0, - "online_rate": 1 - } + break if packet_queue.full(): if packet_queue.get() == 0: lostPacket -= 1 @@ -459,6 +453,13 @@ if __name__ == '__main__': 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={ @@ -524,11 +525,13 @@ if __name__ == '__main__': 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 diff --git a/clients/client-psutil.py b/clients/client-psutil.py index da871b8..bcb8ea0 100755 --- a/clients/client-psutil.py +++ b/clients/client-psutil.py @@ -312,13 +312,7 @@ def _monitor_thread(name, host, interval, type): packet_queue = Queue(maxsize=ONLINE_PACKET_HISTORY_LEN) while True: if name not in monitorServer.keys(): - monitorServer[name] = { - "type": type, - "dns_time": 0, - "connect_time": 0, - "download_time": 0, - "online_rate": 1 - } + break if packet_queue.full(): if packet_queue.get() == 0: lostPacket -= 1 @@ -444,10 +438,16 @@ 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={ @@ -514,11 +514,13 @@ if __name__ == '__main__': 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 From 810f6a0d8a231ba676c46fc6e873d821a43102d9 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 16:47:26 +0800 Subject: [PATCH 10/14] fix --- web/js/serverstatus.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/js/serverstatus.js b/web/js/serverstatus.js index 529456c..02ca72b 100644 --- a/web/js/serverstatus.js +++ b/web/js/serverstatus.js @@ -91,7 +91,7 @@ function uptime() { } if (!MableRow.length) { $("#monitors").append( - "<tr id=\"r" + i + "\" data-toggle=\"collapse\" data-target=\"#rt" + i + "\" class=\"accordion-toggle " + hack + "\">" + + "<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>" + From fb3ecd179651e81d12095e8eafc6bfe5dd9d002f Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 17:43:27 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AAtodo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++++++++++++------- server/config.json | 2 +- server/src/main.cpp | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a980f6c..64b72c1 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ cd ServerStatus/server && make #### 二、修改配置文件 ```diff -! watchdog rule 可以为任何已知字段的表达式 +! watchdog rule 可以为任何已知字段的表达式。注意Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,todo等待修复 ! watchdog interval 最小通知间隔 ! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调 @@ -89,13 +89,21 @@ cd ServerStatus/server && make "location": "🇨🇳", "password": "USER_DEFAULT_PASSWORD", "monthstart": 1 - }, + } + ], + "monitors": [ + { + "name": "百度一下", + "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 +114,8 @@ cd ServerStatus/server && make "callback": "https://yourSMSurl" }, { - "name": "服务器宕机告警,排出俄勒冈,排除s02", - "rule": "online4=0&online6=0&name!='俄勒冈'&username!='s02'", + "name": "服务器宕机告警,排出node1,排除s02", + "rule": "online4=0&online6=0&name!='node1'&username!='s02'", "interval": 600, "callback": "https://yourSMSurl" }, @@ -124,7 +132,7 @@ cd ServerStatus/server && make "callback": "https://yourSMSurl" }, { - "name": "你可以组合任何已知字段的表达式", + "name": "你可以组合任何已知字段的表达式,注意Exprtk库目前不支持中文等Unicode字符", "rule": "(hdd_used/hdd_total)*100>95", "interval": 1800, "callback": "https://yourSMSurl" diff --git a/server/config.json b/server/config.json index 29a4df4..aea2573 100644 --- a/server/config.json +++ b/server/config.json @@ -46,7 +46,7 @@ "type": "https" }, { - "name": "主机交流", + "name": "502论坛", "host": "https://www.hostloc.com", "interval": 60, "type": "https" diff --git a/server/src/main.cpp b/server/src/main.cpp index 2dc5c43..acada37 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -278,6 +278,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; From c236aee5dc38a92cf54e133a1b96b7f4b8ea6520 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 17:52:59 +0800 Subject: [PATCH 12/14] todo list --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 64b72c1..c306d97 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ [](https://github.com/cppla/ServerStatus) [](https://github.com/cppla/ServerStatus) [](https://github.com/cppla/ServerStatus) -[](https://github.com/cppla/ServerStatus) +[](https://github.com/cppla/ServerStatus)  -`Watchdog触发式告警,interval只是为了防止频繁收到报警信息造成的骚扰,并不是探测间隔。 同时为了防止海外机器闪断报警,也加入username、name、type等静态字符串参数的计算支持。` +`Watchdog触发式告警,interval只是为了防止频繁收到报警信息造成的骚扰,并不是探测间隔。 同时为了防止海外机器闪断报警,也加入username、name、type等静态字符串参数的计算支持。值得注意的是,Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,等待修复 ` # 目录: @@ -67,7 +67,7 @@ cd ServerStatus/server && make #### 二、修改配置文件 ```diff -! watchdog rule 可以为任何已知字段的表达式。注意Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,todo等待修复 +! watchdog rule 可以为任何已知字段的表达式。注意Exprtk库默认使用窄字符类型,中文等Unicode字符无法解析计算,等待修复 ! watchdog interval 最小通知间隔 ! watchdog callback 可自定义为Post方法的URL,告警内容将拼接其后并发起回调 @@ -132,7 +132,7 @@ cd ServerStatus/server && make "callback": "https://yourSMSurl" }, { - "name": "你可以组合任何已知字段的表达式,注意Exprtk库目前不支持中文等Unicode字符", + "name": "你可以组合任何已知字段的表达式", "rule": "(hdd_used/hdd_total)*100>95", "interval": 1800, "callback": "https://yourSMSurl" From 1f7827cc211e9b482bd3b8cfcd65c7cb719ff968 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 18:00:24 +0800 Subject: [PATCH 13/14] change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c306d97..d5e0968 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ cd ServerStatus/server && make ], "monitors": [ { - "name": "百度一下", + "name": "你可以监测自己的网站以及MySQL、Redis", "host": "https://www.baidu.com", "interval": 60, "type": "https" From 052c75ef23c79557d87c393b2ff483110a0707f7 Mon Sep 17 00:00:00 2001 From: cppla <i@cpp.la> Date: Tue, 23 Jan 2024 18:09:23 +0800 Subject: [PATCH 14/14] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5e0968..f44c254 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ cd ServerStatus/server && make ], "monitors": [ { - "name": "你可以监测自己的网站以及MySQL、Redis", + "name": "监测网站以及MySQL、Redis,默认为七天在线率", "host": "https://www.baidu.com", "interval": 60, "type": "https"