chore(vwb): hygiène (B4+B6+B7)

- B4 : supprime le double logging dans backend/app.py.
  app.py est importé 2 fois (une fois comme __main__ via `python app.py`,
  une fois comme module `app` via `from app import socketio` dans
  api/websocket_handlers.py). Le RotatingFileHandler était donc ajouté
  2× au root logger → chaque ligne loguée dupliquée. Fix : garde
  idempotente qui vérifie si un handler vers vwb.log existe déjà.
- B6 : supprime les fichiers .pid résiduels (.backend.pid,
  .frontend.pid, .frontend_v4.pid) et les ajoute au .gitignore
  (avec *.lock, *.orig, *.bak).
- B7 : ajoute launch.sh (wrapper → run_v4.sh par défaut, legacy
  → run.sh), clarifie en tête de run.sh et run_v4.sh la distinction
  frontend/ (legacy v3) vs frontend_v4/ (actif), et rectifie le
  README.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-04-16 08:37:12 +02:00
parent 7f2bc6fe97
commit 4fb84b1090
6 changed files with 89 additions and 21 deletions

View File

@@ -23,23 +23,35 @@ load_dotenv()
app = Flask(__name__)
# ============================================================
# Logging — fichier rotatif + console
# Logging — fichier rotatif + console (idempotent)
# ============================================================
# ATTENTION : ce module peut être importé 2 fois (une fois comme __main__
# via `python app.py`, puis comme module `app` via `from app import socketio`
# dans api/websocket_handlers.py). Sans garde idempotente, le RotatingFileHandler
# est ajouté 2× au root logger → chaque ligne loguée apparaît en double.
_log_dir = os.path.join(os.path.dirname(__file__), 'logs')
os.makedirs(_log_dir, exist_ok=True)
_LOG_FILE_PATH = os.path.abspath(os.path.join(_log_dir, 'vwb.log'))
_file_handler = RotatingFileHandler(
os.path.join(_log_dir, 'vwb.log'),
maxBytes=5 * 1024 * 1024, # 5 MB
backupCount=3
_root_logger = logging.getLogger()
_already_configured = any(
isinstance(h, RotatingFileHandler)
and os.path.abspath(getattr(h, 'baseFilename', '')) == _LOG_FILE_PATH
for h in _root_logger.handlers
)
_file_handler.setLevel(logging.INFO)
_file_handler.setFormatter(logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s: %(message)s'
))
logging.getLogger().addHandler(_file_handler)
logging.getLogger().setLevel(logging.INFO)
if not _already_configured:
_file_handler = RotatingFileHandler(
_LOG_FILE_PATH,
maxBytes=5 * 1024 * 1024, # 5 MB
backupCount=3
)
_file_handler.setLevel(logging.INFO)
_file_handler.setFormatter(logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s: %(message)s'
))
_root_logger.addHandler(_file_handler)
_root_logger.setLevel(logging.INFO)
# Configuration
import secrets as _secrets