"""Traffic report from server.py --stats JSONL. python3 tools/stats_report.py /path/to/stats.jsonl [days] """ import json import sys import time from collections import defaultdict path = sys.argv[1] if len(sys.argv) > 1 else 'stats.jsonl' days_back = int(sys.argv[2]) if len(sys.argv) > 2 else 14 cutoff = time.time() - days_back * 86400 daily = defaultdict(lambda: {'views': 0, 'uniq': set(), 'hosts': 0, 'patients': 0}) sessions = [] for line in open(path, encoding='utf-8'): try: d = json.loads(line) except ValueError: continue if d.get('t', 0) < cutoff: continue day = time.strftime('%Y-%m-%d', time.localtime(d['t'])) row = daily[day] if d['e'] == 'page': row['views'] += 1 row['uniq'].add(d.get('u')) elif d['e'] == 'join': row['hosts' if d.get('role') == 'admin' else 'patients'] += 1 elif d['e'] == 'session' and d.get('role') == 'admin': sessions.append(d.get('secs', 0)) print(f"{'day':12} {'views':>6} {'uniques':>8} {'hosts':>6} {'patients':>9}") for day in sorted(daily): r = daily[day] print(f"{day:12} {r['views']:>6} {len(r['uniq']):>8} {r['hosts']:>6} {r['patients']:>9}") if sessions: sessions.sort() med = sessions[len(sessions) // 2] print(f"\n{len(sessions)} hosted relay sessions · median {med // 60}m{med % 60:02d}s " f"· longest {max(sessions) // 60}m") else: print('\nno completed relay sessions in range')