"""Structured stdout/stderr logging (Chapter 02 factor 11 / Chapter 12). Writes structured (key=value) lines to stdout so the host's log capture picks them up, per 12-factor logs. Falls back to a size-capped rotating file only if LOG_FALLBACK_FILE is explicitly set (Ch12: "if stdout capture is unavailable on the specific hosting setup"). """ from __future__ import annotations import logging import os import sys from logging.handlers import RotatingFileHandler from flask import Flask _FORMAT = "%(asctime)s level=%(levelname)s logger=%(name)s msg=%(message)s" def configure_logging(app: Flask) -> None: formatter = logging.Formatter(_FORMAT) stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setFormatter(formatter) app.logger.handlers = [stdout_handler] app.logger.setLevel(logging.INFO if not app.debug else logging.DEBUG) app.logger.propagate = False fallback_path = os.environ.get("LOG_FALLBACK_FILE") if fallback_path: file_handler = RotatingFileHandler(fallback_path, maxBytes=5 * 1024 * 1024, backupCount=3) file_handler.setFormatter(formatter) app.logger.addHandler(file_handler)