From fcbcb07e76c453d944a8884596175ed8e7cdf4e3 Mon Sep 17 00:00:00 2001 From: elpatron Date: Wed, 20 Aug 2025 08:56:07 +0200 Subject: [PATCH] Logging: Automatische Log-Bereinigung nach 7 Tagen implementiert --- LOGGING.md | 15 +++++++++++++-- app.py | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/LOGGING.md b/LOGGING.md index 832a178..d9b0ddc 100644 --- a/LOGGING.md +++ b/LOGGING.md @@ -7,7 +7,8 @@ Das Wordle-Helper Logging-System protokolliert Seitenaufrufe und Suchanfragen oh - **Verzeichnis:** `logs/` - **Datei:** `logs/app.log` - **Format:** UTF-8 -- **Rotation:** Keine automatische Rotation (manuell oder über externe Tools) +- **Rotation:** Automatische Rotation nach 7 Tagen +- **Backup:** Komprimierte Backup-Dateien (30 Tage aufbewahrt) - **Verzeichnis:** Wird automatisch erstellt, falls es nicht existiert ## Protokollierte Ereignisse @@ -50,12 +51,22 @@ logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ - logging.FileHandler('app.log', encoding='utf-8'), + logging.FileHandler(logs_dir / 'app.log', encoding='utf-8'), logging.StreamHandler() ] ) ``` +## Automatische Log-Bereinigung + +Das System bereinigt automatisch alte Log-Dateien: + +- **Rotation:** Nach 7 Tagen wird die aktuelle Log-Datei komprimiert +- **Backup:** Komprimierte Dateien werden 30 Tage aufbewahrt +- **Format:** Backup-Dateien: `app_YYYYMMDD_HHMMSS.log.gz` +- **Trigger:** Bereinigung wird bei jedem Seitenaufruf geprüft +- **Fehlerbehandlung:** Fehler bei der Bereinigung werden geloggt + ## Log-Analyse Die Log-Datei kann mit Standard-Tools analysiert werden: diff --git a/app.py b/app.py index 718b49c..77b9239 100644 --- a/app.py +++ b/app.py @@ -1,7 +1,8 @@ from pathlib import Path import json import logging -from datetime import datetime +import os +from datetime import datetime, timedelta from typing import Tuple, Dict, List from flask import Flask, render_template, request, send_from_directory @@ -47,6 +48,38 @@ def log_search_query(search_params: dict, user_agent: str = None): logger.info(f"SEARCH: pos='{pos_str}' includes='{includes}' excludes='{excludes}' sources={sources} | User-Agent: {user_agent_clean}") +def cleanup_old_logs(): + """Bereinigt Log-Dateien älter als 7 Tage""" + try: + log_file = logs_dir / 'app.log' + if log_file.exists(): + # Prüfe Datei-Alter + file_age = datetime.now() - datetime.fromtimestamp(log_file.stat().st_mtime) + if file_age > timedelta(days=7): + # Log-Datei komprimieren und umbenennen + backup_name = f"app_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log.gz" + backup_path = logs_dir / backup_name + + # Komprimiere mit gzip (falls verfügbar) + import gzip + with open(log_file, 'rb') as f_in: + with gzip.open(backup_path, 'wb') as f_out: + f_out.writelines(f_in) + + # Lösche alte Log-Datei + log_file.unlink() + logger.info(f"Log-Datei komprimiert und gesichert: {backup_name}") + + # Lösche alte Backup-Dateien (älter als 30 Tage) + for backup_file in logs_dir.glob("app_*.log.gz"): + backup_age = datetime.now() - datetime.fromtimestamp(backup_file.stat().st_mtime) + if backup_age > timedelta(days=30): + backup_file.unlink() + logger.info(f"Alte Backup-Datei gelöscht: {backup_file.name}") + + except Exception as e: + logger.error(f"Fehler bei der Log-Bereinigung: {e}") + def load_words() -> Tuple[List[str], Dict[str, List[str]]]: data_dir = Path(__file__).parent / "data" @@ -92,6 +125,9 @@ def filter_words(words: List[str], position_letters: List[str], includes_text: s @app.route("/", methods=["GET", "POST"]) def index(): + # Log-Bereinigung bei jedem Seitenaufruf prüfen (nur alle 24h) + cleanup_old_logs() + # Seitenaufruf protokollieren log_page_view("index", request.headers.get('User-Agent'))