feat(logging): add setup_logging() to core.py, wire into app startup

- Add logging import and setup_logging() that reads LOG_LEVEL env var
  (defaults DEBUG in dev, INFO in prod), sets format with timestamp +
  level + logger name, silences hypercorn/asyncio noise
- Add module-level logger to core.py
- Convert 3 [EMAIL] print() calls to logger.info / logger.error
- Call setup_logging() from app.py at import time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-24 10:50:10 +01:00
parent a35036807e
commit b4b486e908
2 changed files with 23 additions and 4 deletions

View File

@@ -7,7 +7,9 @@ from pathlib import Path
from quart import Quart, Response, abort, g, redirect, request, session, url_for
from .analytics import close_analytics_db, open_analytics_db
from .core import close_db, config, get_csrf_token, init_db, is_flag_enabled, setup_request_id
from .core import close_db, config, get_csrf_token, init_db, is_flag_enabled, setup_logging, setup_request_id
setup_logging()
from .i18n import LANG_BLUEPRINTS, SUPPORTED_LANGS, get_translations
_ASSET_VERSION = str(int(time.time()))

View File

@@ -4,6 +4,7 @@ Core infrastructure: database, config, email, and shared utilities.
import hashlib
import hmac
import logging
import os
import random
import re
@@ -88,6 +89,22 @@ class Config:
config = Config()
def setup_logging() -> None:
"""Configure root logger. Call once from each entry point (app, worker, scripts)."""
level_name = os.environ.get("LOG_LEVEL", "DEBUG" if config.DEBUG else "INFO")
level = getattr(logging, level_name.upper(), logging.INFO)
logging.basicConfig(
level=level,
format="%(asctime)s %(levelname)-8s %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logging.getLogger("hypercorn").setLevel(logging.WARNING)
logging.getLogger("asyncio").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
# =============================================================================
# Database
# =============================================================================
@@ -364,7 +381,7 @@ async def send_email(
resend_id = None
if not config.RESEND_API_KEY:
print(f"[EMAIL] Would send to {to}: {subject}")
logger.info("Would send to %s: %s", to, subject)
resend_id = "dev"
else:
resend.api_key = config.RESEND_API_KEY
@@ -380,7 +397,7 @@ async def send_email(
)
resend_id = result.get("id") if isinstance(result, dict) else getattr(result, "id", None)
except Exception as e:
print(f"[EMAIL] Error sending to {to}: {e}")
logger.error("Error sending to %s: %s", to, e)
return None
# Log to email_log (best-effort, never fail the send)
@@ -391,7 +408,7 @@ async def send_email(
(resend_id, sender, to, subject, email_type),
)
except Exception as e:
print(f"[EMAIL] Failed to log email: {e}")
logger.error("Failed to log email: %s", e)
return resend_id