This commit is contained in:
Mateusz Gruszczyński committed 2026-10-09 10:53:10 +02:00
1 parent ad620c976a
commit 0973129c17
26 files changed
+2255 -2245

No files matched your search

+76
View File
@@ -0,0 +1,76 @@
"""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())