Files
WGSecure/app/core/log.py
T
tuxgyverandClaude Sonnet 5 6a3e8700c3 chore(release): v0.7.6
Ajoute un fichier log texte rotatif (wgsecure.log) dans le dossier
applicatif, en complément du journal JSON interne, pour diagnostiquer
un échec (ex. split-DNS) sans dépendre de l'UI. Corrige le panneau
Journal qui coupait les messages longs sans moyen de les lire en
entier (défilement horizontal réactivé + infobulle).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 15:25:01 +02:00

87 lines
2.3 KiB
Python

"""Journal des événements de connexion WGSecure."""
import os
import json
import logging
from datetime import datetime
from logging.handlers import RotatingFileHandler
from app.utils.platform_utils import get_config_dir
_FILE = "events.json"
_MAX_ENTRIES = 200
_LOG_FILE = "wgsecure.log"
_LOG_LEVELS = {
"error": logging.ERROR,
"warning": logging.WARNING,
}
_file_logger: logging.Logger | None = None
def _path() -> str:
return os.path.join(get_config_dir(), _FILE)
def _get_file_logger() -> logging.Logger:
"""Logger fichier rotatif : trace texte des opérations, lisible sans
passer par l'UI (diagnostic d'un échec quand le panneau Journal ne
suffit pas)."""
global _file_logger
if _file_logger is None:
logger = logging.getLogger("wgsecure")
logger.setLevel(logging.INFO)
handler = RotatingFileHandler(
os.path.join(get_config_dir(), _LOG_FILE),
maxBytes=1_000_000, backupCount=3, encoding="utf-8",
)
handler.setFormatter(logging.Formatter(
"%(asctime)s [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S",
))
logger.addHandler(handler)
logger.propagate = False
_file_logger = logger
return _file_logger
def log_event(msg: str, kind: str = "info") -> None:
"""Ajoute un événement horodaté au journal."""
events = _load()
events.append({
"ts": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"kind": kind, # info | success | error | warning
"msg": msg,
})
_save(events[-_MAX_ENTRIES:])
# Une ligne = un événement, même si msg contient des retours à la ligne
# (ex. message de succès de connexion suivi d'un avertissement).
_get_file_logger().log(
_LOG_LEVELS.get(kind, logging.INFO), msg.replace("\n", " | ")
)
def get_events(n: int = 50) -> list[dict]:
return _load()[-n:]
def clear() -> None:
_save([])
def _load() -> list[dict]:
p = _path()
if not os.path.exists(p):
return []
try:
with open(p, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return []
def _save(events: list[dict]) -> None:
try:
with open(_path(), "w", encoding="utf-8") as f:
json.dump(events, f, ensure_ascii=False)
except Exception:
pass