fix: KCP日志在A端记录
This commit is contained in:
100
scripts/dev/log-network-summary.py
Normal file
100
scripts/dev/log-network-summary.py
Normal file
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
STOP_REQUESTED = False
|
||||
|
||||
|
||||
def handle_signal(signum: int, frame: object) -> None:
|
||||
del signum, frame
|
||||
global STOP_REQUESTED
|
||||
STOP_REQUESTED = True
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Poll /api/network/latest/ and append JSONL snapshots.")
|
||||
parser.add_argument("--url", required=True, help="HTTP endpoint that returns the network summary JSON.")
|
||||
parser.add_argument("--output", required=True, help="Output JSONL path.")
|
||||
parser.add_argument(
|
||||
"--interval-ms",
|
||||
type=int,
|
||||
default=2000,
|
||||
help="Polling interval in milliseconds. Default: 2000.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--request-timeout-sec",
|
||||
type=float,
|
||||
default=3.0,
|
||||
help="Single request timeout in seconds. Default: 3.0.",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def sleep_with_stop(seconds: float) -> None:
|
||||
deadline = time.monotonic() + max(0.0, seconds)
|
||||
while not STOP_REQUESTED:
|
||||
remaining = deadline - time.monotonic()
|
||||
if remaining <= 0.0:
|
||||
return
|
||||
time.sleep(min(remaining, 0.2))
|
||||
|
||||
|
||||
def fetch_json(url: str, timeout_sec: float) -> str:
|
||||
request = urllib.request.Request(
|
||||
url,
|
||||
headers={
|
||||
"Accept": "application/json",
|
||||
"Cache-Control": "no-cache",
|
||||
},
|
||||
method="GET",
|
||||
)
|
||||
with urllib.request.urlopen(request, timeout=timeout_sec) as response:
|
||||
charset = response.headers.get_content_charset("utf-8")
|
||||
payload = response.read().decode(charset)
|
||||
parsed = json.loads(payload)
|
||||
return json.dumps(parsed, separators=(",", ":"), ensure_ascii=False)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
interval_sec = max(args.interval_ms, 200) / 1000.0
|
||||
output_path = Path(args.output)
|
||||
last_error_log_monotonic = 0.0
|
||||
|
||||
signal.signal(signal.SIGINT, handle_signal)
|
||||
signal.signal(signal.SIGTERM, handle_signal)
|
||||
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with output_path.open("a", encoding="utf-8") as output_file:
|
||||
while not STOP_REQUESTED:
|
||||
started = time.monotonic()
|
||||
try:
|
||||
line = fetch_json(args.url, args.request_timeout_sec)
|
||||
except (TimeoutError, urllib.error.URLError, urllib.error.HTTPError, json.JSONDecodeError) as error:
|
||||
now = time.monotonic()
|
||||
if now - last_error_log_monotonic >= 10.0:
|
||||
print(f"[network-summary] poll failed: {error}", file=sys.stderr)
|
||||
last_error_log_monotonic = now
|
||||
else:
|
||||
output_file.write(line)
|
||||
output_file.write("\n")
|
||||
output_file.flush()
|
||||
|
||||
elapsed = time.monotonic() - started
|
||||
sleep_with_stop(max(0.0, interval_sec - elapsed))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user