Add log retention settings and clear logs
This commit is contained in:
@@ -59,6 +59,7 @@ def default_config() -> dict[str, Any]:
|
||||
"target_port": 443,
|
||||
"fail_threshold": 3,
|
||||
"recover_threshold": 1,
|
||||
"max_checks_per_proxy": 500,
|
||||
"db_path": str(DEFAULT_DB),
|
||||
"proxies": [],
|
||||
"notifications": {"enabled": True, "timeout_seconds": 10, "channels": []},
|
||||
@@ -74,6 +75,7 @@ def merge_defaults(cfg: dict[str, Any]) -> dict[str, Any]:
|
||||
base["target_host"] = "www.baidu.com"
|
||||
base["target_port"] = int(base.get("target_port") or 443)
|
||||
base["interval_seconds"] = int(base.get("interval_seconds") or 300)
|
||||
base["max_checks_per_proxy"] = max(1, int(base.get("max_checks_per_proxy") or 500))
|
||||
base.setdefault("proxies", [])
|
||||
for proxy in base["proxies"]:
|
||||
if proxy.get("target_host") in (None, "", "1.1.1.1", "8.8.8.8", "google.com"):
|
||||
@@ -180,12 +182,22 @@ class Store:
|
||||
)
|
||||
self.conn.commit()
|
||||
|
||||
async def add_check(self, proxy_id: str, ok: bool, latency_ms: int | None, error: str | None, exit_ip: str | None) -> None:
|
||||
async def add_check(self, proxy_id: str, ok: bool, latency_ms: int | None, error: str | None, exit_ip: str | None, max_per_proxy: int | None = None) -> None:
|
||||
async with self.lock:
|
||||
self.conn.execute(
|
||||
"insert into checks(proxy_id,ts,ok,latency_ms,error,exit_ip) values(?,?,?,?,?,?)",
|
||||
(proxy_id, now_ts(), 1 if ok else 0, latency_ms, error, exit_ip),
|
||||
)
|
||||
if max_per_proxy:
|
||||
self.conn.execute(
|
||||
"""
|
||||
delete from checks
|
||||
where proxy_id=? and id not in (
|
||||
select id from checks where proxy_id=? order by ts desc, id desc limit ?
|
||||
)
|
||||
""",
|
||||
(proxy_id, proxy_id, max(1, int(max_per_proxy))),
|
||||
)
|
||||
self.conn.commit()
|
||||
|
||||
async def add_event(self, proxy_id: str, old_status: str | None, new_status: str, message: str) -> None:
|
||||
@@ -205,7 +217,7 @@ class Store:
|
||||
self.conn.commit()
|
||||
|
||||
def recent_checks(self, proxy_id: str, limit: int = 50) -> list[dict[str, Any]]:
|
||||
rows = self.conn.execute("select * from checks where proxy_id=? order by ts desc limit ?", (proxy_id, limit)).fetchall()
|
||||
rows = self.conn.execute("select * from checks where proxy_id=? order by ts desc, id desc limit ?", (proxy_id, limit)).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
def recent_events(self, limit: int = 50) -> list[dict[str, Any]]:
|
||||
@@ -216,6 +228,15 @@ class Store:
|
||||
rows = self.conn.execute("select * from notification_logs order by ts desc limit ?", (limit,)).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
|
||||
async def clear_logs(self) -> dict[str, int]:
|
||||
async with self.lock:
|
||||
removed = {}
|
||||
for table in ("checks", "events", "notification_logs"):
|
||||
cur = self.conn.execute(f"delete from {table}")
|
||||
removed[table] = cur.rowcount if cur.rowcount is not None else 0
|
||||
self.conn.commit()
|
||||
return removed
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class RuntimeState:
|
||||
@@ -538,6 +559,8 @@ class App:
|
||||
out["fail_threshold"] = max(1, int(data.get("fail_threshold") or 3))
|
||||
if "recover_threshold" in data:
|
||||
out["recover_threshold"] = max(1, int(data.get("recover_threshold") or 1))
|
||||
if "max_checks_per_proxy" in data:
|
||||
out["max_checks_per_proxy"] = max(1, int(data.get("max_checks_per_proxy") or 500))
|
||||
return out
|
||||
|
||||
async def update_settings(self, data: dict[str, Any]) -> dict[str, Any]:
|
||||
@@ -554,7 +577,7 @@ class App:
|
||||
await self.save_config()
|
||||
for p in list(self.proxies):
|
||||
await self.restart_proxy_task(p["id"])
|
||||
return {k: self.config.get(k) for k in ["interval_seconds", "timeout_seconds", "target_host", "target_port", "fail_threshold", "recover_threshold"]}
|
||||
return {k: self.config.get(k) for k in ["interval_seconds", "timeout_seconds", "target_host", "target_port", "fail_threshold", "recover_threshold", "max_checks_per_proxy"]}
|
||||
|
||||
async def upsert_proxy(self, data: dict[str, Any], proxy_id: str | None = None) -> dict[str, Any]:
|
||||
existing = self.get_proxy(proxy_id) if proxy_id else None
|
||||
@@ -600,7 +623,7 @@ class App:
|
||||
proxy_id = proxy["id"]
|
||||
st = self.state_for(proxy_id)
|
||||
ok, latency, err, exit_ip = await check_proxy(proxy)
|
||||
await self.store.add_check(proxy_id, ok, latency, err, exit_ip)
|
||||
await self.store.add_check(proxy_id, ok, latency, err, exit_ip, int(self.config.get("max_checks_per_proxy") or 500))
|
||||
st.last_ts = now_ts(); st.last_ok = ok; st.latency_ms = latency; st.error = err; st.exit_ip = exit_ip
|
||||
fail_threshold = int(proxy.get("fail_threshold", self.config.get("fail_threshold", 3)))
|
||||
recover_threshold = int(proxy.get("recover_threshold", self.config.get("recover_threshold", 1)))
|
||||
@@ -650,7 +673,7 @@ class App:
|
||||
items.append({"proxy": public_proxy(p), "state": dataclasses.asdict(st), "recent": self.store.recent_checks(sid, 20)})
|
||||
return {
|
||||
"ok": True, "now": now_ts(), "now_text": iso(),
|
||||
"settings": {k: self.config.get(k) for k in ["interval_seconds", "timeout_seconds", "target_host", "target_port", "fail_threshold", "recover_threshold"]},
|
||||
"settings": {k: self.config.get(k) for k in ["interval_seconds", "timeout_seconds", "target_host", "target_port", "fail_threshold", "recover_threshold", "max_checks_per_proxy"]},
|
||||
"proxies": items,
|
||||
"notifications": self.config.get("notifications", {}),
|
||||
"events": self.store.recent_events(50),
|
||||
@@ -696,6 +719,8 @@ async def handle_http(reader: asyncio.StreamReader, writer: asyncio.StreamWriter
|
||||
status, ctype, resp = json_response(app.status_payload())
|
||||
elif method == "PUT" and p == "/api/settings":
|
||||
status, ctype, resp = json_response({"ok": True, "settings": await app.update_settings(data)})
|
||||
elif method == "DELETE" and p == "/api/logs":
|
||||
status, ctype, resp = json_response({"ok": True, "removed": await app.store.clear_logs()})
|
||||
elif method == "POST" and p == "/api/proxies":
|
||||
status, ctype, resp = json_response({"ok": True, "proxy": await app.upsert_proxy(data)}, 201)
|
||||
elif method == "PUT" and p.startswith("/api/proxies/"):
|
||||
|
||||
Reference in New Issue
Block a user