"""Read-only statistics endpoints backed by Redis.""" import json from urllib.parse import unquote, urlsplit, parse_qs from flask import render_template, jsonify from adlist.services import redis_client def collect_stats(): stats_data, target_ips, url_requests, user_agents, client_ips = {}, {}, {}, {}, {} for key in redis_client.scan_iter("stats:*"): key_str = key.decode() value = (redis_client.get(key) or b"0").decode() if key_str.startswith("stats:target_ips:"): target_ips[key_str.split(":", 2)[2]] = value elif key_str.startswith("stats:url_requests:"): url_requests[unquote(key_str.split(":", 2)[2])] = value elif key_str.startswith("stats:user_agents:"): user_agents[unquote(key_str.split(":", 2)[2])] = value elif key_str.startswith("stats:client_ips:"): client_ips[key_str.split(":", 2)[2]] = value else: stats_data[key_str] = value recent = [] for item in redis_client.lrange("recent_converts", 0, 99): try: row = json.loads(item.decode()) params = parse_qs(urlsplit(row.get("url", "")).query) row["source_url"] = params.get("url", [""])[0] row["target_ip"] = params.get("ip", ["127.0.0.1"])[0] recent.append(row) except (ValueError, TypeError, AttributeError): continue total_time = float(redis_client.get("stats:processing_time_total") or 0) count_time = int(redis_client.get("stats:processing_time_count") or 0) total_size = int(redis_client.get("stats:content_size_total") or 0) count_size = int(redis_client.get("stats:content_size_count") or 0) detailed = { "processing_time_total_sec": total_time, "processing_time_count": count_time, "processing_time_avg_sec": total_time / count_time if count_time else 0, "processing_time_min_sec": float(redis_client.get("stats:processing_time_min") or 0), "processing_time_max_sec": float(redis_client.get("stats:processing_time_max") or 0), "content_size_total_bytes": total_size, "content_size_count": count_size, "content_size_avg_bytes": total_size / count_size if count_size else 0, } return { **stats_data, "target_ips": target_ips, "url_requests": url_requests, "user_agents": user_agents, "client_ips": client_ips, "recent_converts": recent, "detailed_stats": detailed, } def stats(): data = collect_stats() return render_template( "stats.html", stats=data, target_ips=data["target_ips"], url_requests=data["url_requests"], user_agents=data["user_agents"], client_ips=data["client_ips"], recent=data["recent_converts"], detailed=data["detailed_stats"], raw_json=json.dumps(data, indent=2), ) def stats_json(): return jsonify(collect_stats())