게시판SGF 기보로 학습하는 바둑 LLM 인공지능예제 소스

예제 소스

SGF 기보로 학습하는 바둑 LLM 인공지능 · 파일 169개

probe_mariago_uptime.py

#!/usr/bin/env python3
"""IDC(또는 외부망)에서 MariaGO 홈 도달성 연속 점검.

집 Mac이 아니라 **IDC에서** 돌리면, 외부→집 경로(공인 IP/NAT/절전) 이상을
휴대폰과 비슷한 시점에서 잡을 수 있습니다.

  # IDC에서 (stdlib only)
  python3 probe_mariago_uptime.py --url https://baduk.mariago.kr/login --interval 30

  # 백그라운드
  nohup python3 probe_mariago_uptime.py --interval 30 --out-dir ./mariago_uptime \\
    > mariago_uptime/stdout.log 2>&1 &

결과:
  out-dir/probes.jsonl  — 매회 1줄
  out-dir/STATUS.md     — 최근 요약 (ok율, 연속실패, 최근 실패)
"""

from __future__ import annotations

import argparse
import json
import ssl
import time
import urllib.error
import urllib.request
from collections import deque
from datetime import datetime, timezone
from pathlib import Path


def iso() -> str:
    return datetime.now(timezone.utc).isoformat()


def probe_one(url: str, timeout_s: float) -> dict:
    t0 = time.monotonic()
    ctx = ssl.create_default_context()
    req = urllib.request.Request(
        url,
        method="GET",
        headers={
            "User-Agent": "MariaGO-uptime-probe/1.0 (+idc)",
            "Accept": "text/html,*/*",
            "Connection": "close",
        },
    )
    try:
        with urllib.request.urlopen(req, timeout=timeout_s, context=ctx) as resp:
            body = resp.read(2048)
            dt_ms = (time.monotonic() - t0) * 1000
            code = int(resp.status)
            ok = 200 <= code < 400
            return {
                "ts": iso(),
                "url": url,
                "ok": ok,
                "status": code,
                "ms": round(dt_ms, 1),
                "bytes": len(body),
                "error": None,
            }
    except Exception as e:
        dt_ms = (time.monotonic() - t0) * 1000
        return {
            "ts": iso(),
            "url": url,
            "ok": False,
            "status": None,
            "ms": round(dt_ms, 1),
            "bytes": 0,
            "error": f"{type(e).__name__}: {e}",
        }


def write_status(
    path: Path,
    *,
    url: str,
    interval: float,
    window: deque,
    fail_streak: int,
    total_ok: int,
    total_n: int,
) -> None:
    recent_fail = [r for r in list(window)[-20:] if not r["ok"]]
    lines = [
        f"# MariaGO uptime probe — {iso()}",
        "",
        f"- **url**: `{url}`",
        f"- **interval_s**: `{interval}`",
        f"- **total**: `{total_n}` (ok `{total_ok}` = `{100.0 * total_ok / max(1, total_n):.1f}%`)",
        f"- **fail_streak**: `{fail_streak}`",
        f"- **window_ok**: `{sum(1 for r in window if r['ok'])}/{len(window)}`",
        "",
        "## recent failures",
        "",
    ]
    if recent_fail:
        for r in recent_fail[-10:]:
            lines.append(
                f"- `{r['ts']}` status=`{r['status']}` ms=`{r['ms']}` err=`{r['error']}`"
            )
    else:
        lines.append("- (없음)")
    lines.append("")
    path.write_text("\n".join(lines), encoding="utf-8")


def main() -> int:
    p = argparse.ArgumentParser(description="External uptime probe for MariaGO")
    p.add_argument("--url", default="https://baduk.mariago.kr/login")
    p.add_argument("--interval", type=float, default=30.0, help="초 단위")
    p.add_argument("--timeout", type=float, default=15.0)
    p.add_argument("--out-dir", default="mariago_uptime")
    p.add_argument("--window", type=int, default=120, help="STATUS 요약용 최근 N회")
    args = p.parse_args()

    out = Path(args.out_dir)
    out.mkdir(parents=True, exist_ok=True)
    jsonl = out / "probes.jsonl"
    status = out / "STATUS.md"

    window: deque = deque(maxlen=max(10, args.window))
    fail_streak = 0
    total_ok = total_n = 0

    print(
        f"[probe] url={args.url} interval={args.interval}s out={out.resolve()}",
        flush=True,
    )

    while True:
        r = probe_one(args.url, args.timeout)
        total_n += 1
        if r["ok"]:
            total_ok += 1
            fail_streak = 0
            tag = "OK"
        else:
            fail_streak += 1
            tag = "FAIL"
        window.append(r)
        with jsonl.open("a", encoding="utf-8") as f:
            f.write(json.dumps(r, ensure_ascii=False) + "\n")
        write_status(
            status,
            url=args.url,
            interval=args.interval,
            window=window,
            fail_streak=fail_streak,
            total_ok=total_ok,
            total_n=total_n,
        )
        print(
            f"[{tag}] {r['ts']} status={r['status']} {r['ms']}ms "
            f"streak={fail_streak} err={r['error']}",
            flush=True,
        )
        time.sleep(max(1.0, args.interval))


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except KeyboardInterrupt:
        print("[probe] stopped", flush=True)
        raise SystemExit(0)