LinuxAwesomeBot: OneBot 11 Linux monitoring bot (power/CPU/temp/alerts)
This commit is contained in:
commit
b1ffd86bd9
12 files changed
+1468
No files matched your search
+84
@@ -0,0 +1,84 @@
|
||||
"""后台高负载告警任务。"""
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
|
||||
import monitor
|
||||
|
||||
log = logging.getLogger("alerter")
|
||||
|
||||
|
||||
class Alerter:
|
||||
def __init__(self, ob, cfg: dict):
|
||||
self.ob = ob
|
||||
self.cfg = cfg
|
||||
self.interval = cfg.get("interval", 10)
|
||||
self.threshold = cfg.get("cpu_threshold", 85.0)
|
||||
self.consecutive_need = cfg.get("consecutive", 2)
|
||||
self.cooldown = cfg.get("cooldown", 600)
|
||||
self.top_n = cfg.get("top_n", 5)
|
||||
self.groups = cfg.get("groups", []) or []
|
||||
self.friends = cfg.get("friends", []) or []
|
||||
|
||||
self._consecutive = 0
|
||||
self._alerting = False # 当前是否处于高负载状态
|
||||
self._last_alert_ts = 0.0
|
||||
self._task = None
|
||||
|
||||
def start(self):
|
||||
self._task = asyncio.get_running_loop().create_task(self._loop())
|
||||
|
||||
async def stop(self):
|
||||
if self._task:
|
||||
self._task.cancel()
|
||||
|
||||
async def _loop(self):
|
||||
log.info("告警监控已启动: 阈值 %.0f%%, 连续 %d 次, 间隔 %ds, 冷却 %ds",
|
||||
self.threshold, self.consecutive_need, self.interval, self.cooldown)
|
||||
while True:
|
||||
try:
|
||||
await asyncio.sleep(self.interval)
|
||||
if not self.ob.connected or (not self.groups and not self.friends):
|
||||
continue
|
||||
cpu = monitor.get_cpu()
|
||||
await self._check(cpu["percent"])
|
||||
except asyncio.CancelledError:
|
||||
break
|
||||
except Exception:
|
||||
log.exception("告警循环出错")
|
||||
|
||||
async def _check(self, cpu_percent: float):
|
||||
now = time.monotonic()
|
||||
if cpu_percent >= self.threshold:
|
||||
self._consecutive += 1
|
||||
if (self._consecutive >= self.consecutive_need
|
||||
and (not self._alerting or now - self._last_alert_ts >= self.cooldown)):
|
||||
self._alerting = True
|
||||
self._last_alert_ts = now
|
||||
await self._send_alert(cpu_percent)
|
||||
else:
|
||||
self._consecutive = 0
|
||||
if self._alerting:
|
||||
self._alerting = False
|
||||
msg = (f"✅ [恢复] 服务器 CPU 已回落到 {cpu_percent:.1f}%,"
|
||||
f"负载恢复正常。")
|
||||
log.info(msg)
|
||||
await self.ob.broadcast(msg, self.groups, self.friends)
|
||||
|
||||
async def _send_alert(self, cpu_percent: float):
|
||||
top = monitor.get_top_processes(self.top_n)
|
||||
cpu = monitor.get_cpu()
|
||||
load = cpu["load"]
|
||||
lines = [
|
||||
f"⚠️ [高负载告警] CPU 持续超过 {self.threshold:.0f}%,当前 {cpu_percent:.1f}%",
|
||||
f"负载: {load[0]:.2f} / {load[1]:.2f} / {load[2]:.2f} 核心: {cpu['cores']}",
|
||||
"",
|
||||
f"TOP{self.top_n} 高负载进程:",
|
||||
]
|
||||
for i, p in enumerate(top, 1):
|
||||
lines.append(
|
||||
f"{i}. {p['name']} (PID {p['pid']}) CPU {p['cpu']}% 内存 {p['mem_mb']}MB"
|
||||
)
|
||||
msg = "\n".join(lines)
|
||||
log.warning("触发高负载告警: %.1f%%", cpu_percent)
|
||||
await self.ob.broadcast(msg, self.groups, self.friends)
|
||||
Reference in new issue
Block a user