Logging: Automatische Log-Bereinigung nach 7 Tagen implementiert
This commit is contained in:
15
LOGGING.md
15
LOGGING.md
@@ -7,7 +7,8 @@ Das Wordle-Helper Logging-System protokolliert Seitenaufrufe und Suchanfragen oh
|
|||||||
- **Verzeichnis:** `logs/`
|
- **Verzeichnis:** `logs/`
|
||||||
- **Datei:** `logs/app.log`
|
- **Datei:** `logs/app.log`
|
||||||
- **Format:** UTF-8
|
- **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
|
- **Verzeichnis:** Wird automatisch erstellt, falls es nicht existiert
|
||||||
|
|
||||||
## Protokollierte Ereignisse
|
## Protokollierte Ereignisse
|
||||||
@@ -50,12 +51,22 @@ logging.basicConfig(
|
|||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format='%(asctime)s - %(levelname)s - %(message)s',
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||||
handlers=[
|
handlers=[
|
||||||
logging.FileHandler('app.log', encoding='utf-8'),
|
logging.FileHandler(logs_dir / 'app.log', encoding='utf-8'),
|
||||||
logging.StreamHandler()
|
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
|
## Log-Analyse
|
||||||
|
|
||||||
Die Log-Datei kann mit Standard-Tools analysiert werden:
|
Die Log-Datei kann mit Standard-Tools analysiert werden:
|
||||||
|
38
app.py
38
app.py
@@ -1,7 +1,8 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
import os
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from typing import Tuple, Dict, List
|
from typing import Tuple, Dict, List
|
||||||
from flask import Flask, render_template, request, send_from_directory
|
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}")
|
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]]]:
|
def load_words() -> Tuple[List[str], Dict[str, List[str]]]:
|
||||||
data_dir = Path(__file__).parent / "data"
|
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"])
|
@app.route("/", methods=["GET", "POST"])
|
||||||
def index():
|
def index():
|
||||||
|
# Log-Bereinigung bei jedem Seitenaufruf prüfen (nur alle 24h)
|
||||||
|
cleanup_old_logs()
|
||||||
|
|
||||||
# Seitenaufruf protokollieren
|
# Seitenaufruf protokollieren
|
||||||
log_page_view("index", request.headers.get('User-Agent'))
|
log_page_view("index", request.headers.get('User-Agent'))
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user