fix(slice-2): surface ecomm.* INFO logs so the one-time code reaches the dev log
uvicorn configures only its own loggers, so the LogMailer INFO line — PUC-10's local dev channel (the code in the backend log) — was swallowed. Add an idempotent dedicated handler for the 'ecomm' logger (propagate=False) in create_app so dev.sh/uvicorn runs show the code. Caught by the SLICE-2 end-to-end walk; unit tests read the in-memory outbox and didn't. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,8 @@ storefronts domain (SLICE-3) replaces the _storefront_for seam.
|
|||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -47,6 +49,23 @@ def _storefront_for(conn: psycopg.Connection, account: accounts.Account) -> dict
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_app_logging() -> None:
|
||||||
|
"""Surface the app's own `ecomm.*` INFO logs on stderr (idempotent).
|
||||||
|
|
||||||
|
uvicorn configures only its own loggers, leaving the root with no INFO handler — so
|
||||||
|
without this the `ecomm.mailer` line (PUC-10's local dev channel: the one-time code in
|
||||||
|
the backend log) would be swallowed. A dedicated handler with propagate=False keeps it
|
||||||
|
out of uvicorn's stream and avoids double-logging.
|
||||||
|
"""
|
||||||
|
lg = logging.getLogger("ecomm")
|
||||||
|
if not lg.handlers:
|
||||||
|
handler = logging.StreamHandler(sys.stderr)
|
||||||
|
handler.setFormatter(logging.Formatter("%(levelname)s:%(name)s: %(message)s"))
|
||||||
|
lg.addHandler(handler)
|
||||||
|
lg.setLevel(logging.INFO)
|
||||||
|
lg.propagate = False
|
||||||
|
|
||||||
|
|
||||||
def _set_session_cookie(response: Response, account: accounts.Account) -> None:
|
def _set_session_cookie(response: Response, account: accounts.Account) -> None:
|
||||||
token = session_mod.sign({"account_id": account.id, "email": account.email}, config.session_secret())
|
token = session_mod.sign({"account_id": account.id, "email": account.email}, config.session_secret())
|
||||||
response.set_cookie(
|
response.set_cookie(
|
||||||
@@ -60,6 +79,7 @@ def _set_session_cookie(response: Response, account: accounts.Account) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def create_app(database_url: str | None = None) -> FastAPI:
|
def create_app(database_url: str | None = None) -> FastAPI:
|
||||||
|
_ensure_app_logging()
|
||||||
dsn = database_url or config.database_url()
|
dsn = database_url or config.database_url()
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
|
|||||||
Reference in New Issue
Block a user