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:
@@ -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()))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user