initial: import DOLPHIN baseline 2026-04-21 from dolphinng5_predict working tree
Includes core prod + GREEN/BLUE subsystems: - prod/ (BLUE harness, configs, scripts, docs) - nautilus_dolphin/ (GREEN Nautilus-native impl + dvae/ preserved) - adaptive_exit/ (AEM engine + models/bucket_assignments.pkl) - Observability/ (EsoF advisor, TUI, dashboards) - external_factors/ (EsoF producer) - mc_forewarning_qlabs_fork/ (MC regime/envelope) Excludes runtime caches, logs, backups, and reproducible artifacts per .gitignore.
This commit is contained in:
89
prod/system_stats_service.py
Executable file
89
prod/system_stats_service.py
Executable file
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
system_stats_service.py — Lightweight host metrics → ClickHouse.
|
||||
Polls /proc every 30s. Zero dependencies beyond stdlib.
|
||||
Writes to dolphin.system_stats via HTTP INSERT.
|
||||
|
||||
Run: python3 /root/ch-setup/system_stats_service.py
|
||||
(Place on mount at prod/system_stats_service.py before adding to supervisord)
|
||||
"""
|
||||
import time, json, urllib.request, logging
|
||||
|
||||
CH_URL = "http://localhost:8123"
|
||||
CH_USER = "dolphin"
|
||||
CH_PASS = "dolphin_ch_2026"
|
||||
POLL_S = 30
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s")
|
||||
log = logging.getLogger("system_stats")
|
||||
|
||||
_prev_net: dict = {}
|
||||
|
||||
def read_mem() -> dict:
|
||||
"""Parse /proc/meminfo → used/available GB."""
|
||||
info = {}
|
||||
with open("/proc/meminfo") as f:
|
||||
for line in f:
|
||||
k, v = line.split(":")
|
||||
info[k.strip()] = int(v.split()[0]) # kB
|
||||
total = info["MemTotal"] / 1024 / 1024
|
||||
available = info["MemAvailable"] / 1024 / 1024
|
||||
used = total - available
|
||||
return {"mem_used_gb": round(used, 2),
|
||||
"mem_available_gb": round(available, 2),
|
||||
"mem_pct": round(used / total * 100, 1)}
|
||||
|
||||
def read_load() -> dict:
|
||||
"""Parse /proc/loadavg."""
|
||||
with open("/proc/loadavg") as f:
|
||||
parts = f.read().split()
|
||||
return {"load_1m": float(parts[0]),
|
||||
"load_5m": float(parts[1]),
|
||||
"load_15m": float(parts[2])}
|
||||
|
||||
def read_net() -> dict:
|
||||
"""Parse /proc/net/dev → MB/s delta across non-lo interfaces."""
|
||||
global _prev_net
|
||||
ifaces = {}
|
||||
with open("/proc/net/dev") as f:
|
||||
for line in f.readlines()[2:]:
|
||||
parts = line.split()
|
||||
iface = parts[0].rstrip(":")
|
||||
if iface == "lo":
|
||||
continue
|
||||
ifaces[iface] = {"rx": int(parts[1]), "tx": int(parts[9])}
|
||||
|
||||
now = time.monotonic()
|
||||
result = {"net_rx_mb_s": 0.0, "net_tx_mb_s": 0.0, "net_iface": "all"}
|
||||
if _prev_net:
|
||||
dt = now - _prev_net["_ts"]
|
||||
rx_total = sum(ifaces[i]["rx"] - _prev_net.get(i, {}).get("rx", ifaces[i]["rx"]) for i in ifaces)
|
||||
tx_total = sum(ifaces[i]["tx"] - _prev_net.get(i, {}).get("tx", ifaces[i]["tx"]) for i in ifaces)
|
||||
result["net_rx_mb_s"] = round(max(0, rx_total) / 1024 / 1024 / dt, 3)
|
||||
result["net_tx_mb_s"] = round(max(0, tx_total) / 1024 / 1024 / dt, 3)
|
||||
|
||||
_prev_net = {**ifaces, "_ts": now}
|
||||
return result
|
||||
|
||||
def ch_insert(row: dict):
|
||||
body = (json.dumps(row) + "\n").encode()
|
||||
url = f"{CH_URL}/?database=dolphin&query=INSERT+INTO+system_stats+FORMAT+JSONEachRow"
|
||||
req = urllib.request.Request(url, data=body, method="POST")
|
||||
req.add_header("X-ClickHouse-User", CH_USER)
|
||||
req.add_header("X-ClickHouse-Key", CH_PASS)
|
||||
req.add_header("Content-Type", "application/octet-stream")
|
||||
urllib.request.urlopen(req, timeout=5)
|
||||
|
||||
def main():
|
||||
log.info("system_stats_service starting — poll every %ds", POLL_S)
|
||||
while True:
|
||||
try:
|
||||
ts_ms = int(time.time() * 1_000) # DateTime64(3) expects milliseconds
|
||||
row = {"ts": ts_ms, **read_mem(), **read_load(), **read_net()}
|
||||
ch_insert(row)
|
||||
log.debug("inserted: %s", row)
|
||||
except Exception as e:
|
||||
log.warning("error: %s", e)
|
||||
time.sleep(POLL_S)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user