Server: Reduce rate limit log spam - periodic summary only
- Instead of logging every rate limit warning, now logs summary every 60s - Shows: IP_blocked=X, rate_limited=Y
This commit is contained in:
+25
-2
@@ -55,6 +55,11 @@ _ip_request_counts: dict[str, list[float]] = defaultdict(list)
|
|||||||
# IP blocking config (set from main.py)
|
# IP blocking config (set from main.py)
|
||||||
BLOCKED_IPS: set[str] = set()
|
BLOCKED_IPS: set[str] = set()
|
||||||
|
|
||||||
|
# Request stats (for summary logging)
|
||||||
|
_stats = {"blocked": 0, "rate_limited": 0, "total": 0}
|
||||||
|
_stats_last_log = time.time()
|
||||||
|
STATS_LOG_INTERVAL = 60 # Log stats every 60 seconds
|
||||||
|
|
||||||
# Suspicious paths that indicate bot scanning
|
# Suspicious paths that indicate bot scanning
|
||||||
SUSPICIOUS_PATHS = {
|
SUSPICIOUS_PATHS = {
|
||||||
".env", ".env.local", ".env.production", ".env.development", ".env.bak",
|
".env", ".env.local", ".env.production", ".env.development", ".env.bak",
|
||||||
@@ -140,15 +145,22 @@ def set_ip_config(blocked: Optional[set[str]] = None):
|
|||||||
class LoggingMiddleware(BaseHTTPMiddleware):
|
class LoggingMiddleware(BaseHTTPMiddleware):
|
||||||
async def dispatch(self, request: Request, call_next):
|
async def dispatch(self, request: Request, call_next):
|
||||||
request_id = str(uuid.uuid4())[:8]
|
request_id = str(uuid.uuid4())[:8]
|
||||||
|
global _stats, _stats_last_log
|
||||||
|
|
||||||
client_ip = get_client_ip(request)
|
client_ip = get_client_ip(request)
|
||||||
|
|
||||||
# Check if IP is blocked
|
# Check if IP is blocked (silent)
|
||||||
if is_ip_blocked(client_ip):
|
if is_ip_blocked(client_ip):
|
||||||
|
_stats["blocked"] += 1
|
||||||
return Response(status_code=404, content="")
|
return Response(status_code=404, content="")
|
||||||
|
|
||||||
# Check rate limit
|
# Check rate limit
|
||||||
if not check_rate_limit(client_ip):
|
if not check_rate_limit(client_ip):
|
||||||
logger.warning(f"Rate limited: {client_ip} ({request.url.path})")
|
_stats["rate_limited"] += 1
|
||||||
|
# Periodic stats logging instead of every warning
|
||||||
|
if time.time() - _stats_last_log > STATS_LOG_INTERVAL:
|
||||||
|
logger.warning(f"Stats: {_stats}")
|
||||||
|
_stats_last_log = time.time()
|
||||||
return Response(status_code=429, content="Too many requests")
|
return Response(status_code=429, content="Too many requests")
|
||||||
|
|
||||||
# Check suspicious path (silent 404 for bots)
|
# Check suspicious path (silent 404 for bots)
|
||||||
@@ -160,6 +172,9 @@ class LoggingMiddleware(BaseHTTPMiddleware):
|
|||||||
# Skip logging for large file downloads (don't spam logs)
|
# Skip logging for large file downloads (don't spam logs)
|
||||||
is_file_download = path.startswith("/pack/") and "/file/" in path
|
is_file_download = path.startswith("/pack/") and "/file/" in path
|
||||||
|
|
||||||
|
# Track total requests for stats
|
||||||
|
_stats["total"] += 1
|
||||||
|
|
||||||
# Log legitimate requests (except file downloads)
|
# Log legitimate requests (except file downloads)
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
@@ -173,6 +188,14 @@ class LoggingMiddleware(BaseHTTPMiddleware):
|
|||||||
if not is_file_download:
|
if not is_file_download:
|
||||||
logger.info(f"← {request.method} {path} → {response.status_code} ({duration:.0f}ms) [ID: {request_id}]")
|
logger.info(f"← {request.method} {path} → {response.status_code} ({duration:.0f}ms) [ID: {request_id}]")
|
||||||
|
|
||||||
|
# Periodic stats logging (only log if there were blocked/rate-limited)
|
||||||
|
now = time.time()
|
||||||
|
if now - _stats_last_log > STATS_LOG_INTERVAL:
|
||||||
|
if _stats["blocked"] > 0 or _stats["rate_limited"] > 0:
|
||||||
|
logger.warning(f"Blocked requests: IP_blocked={_stats['blocked']}, rate_limited={_stats['rate_limited']}")
|
||||||
|
_stats = {"blocked": 0, "rate_limited": 0, "total": 0}
|
||||||
|
_stats_last_log = now
|
||||||
|
|
||||||
response.headers["X-Request-ID"] = request_id
|
response.headers["X-Request-ID"] = request_id
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user