#14 — Structured logging - app/core/logging_config.py: configure_logging() sets stdout handler with timestamped format; called at import time in main.py - Global FastAPI exception_handler logs 500s with full traceback - opportunities.py: logger added; create/approve/mark-posted/dismiss each emit an info line so failures are traceable #15 — Frontend error handling - frontend/src/composables/useToast.ts: shared toast composable (error/success/info, auto-dismiss, module-level singleton) - frontend/src/components/ToastList.vue: fixed-position overlay, theme-aware, accessible (role=alert, aria-live=polite) - OpportunitiesView: all 6 async actions have catch + toast.error() - CampaignDetail: onMounted + all 6 mutation functions wrapped #16 — Aggregate stats - app/api/endpoints/stats.py: GET /api/v1/stats — single DB pass via GROUP BY; returns posts totals, 7-day count, top communities, platform breakdown, and opportunity queue counts - frontend/src/components/StatsBar.vue: slim header bar above router-view; chips for posts ok/failed/week, queue pending/approved/ posted, top community; hides gracefully on API error
32 lines
1.1 KiB
Python
32 lines
1.1 KiB
Python
"""
|
|
Logging configuration for Magpie.
|
|
|
|
Call configure_logging() once at app startup (in lifespan).
|
|
Writes to stdout — uvicorn captures stdout to $LOG_API via manage.sh.
|
|
Format: timestamp [LEVEL] module: message
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import sys
|
|
|
|
|
|
def configure_logging(level: str = "INFO") -> None:
|
|
"""Apply a consistent log format across all loggers."""
|
|
fmt = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
|
|
datefmt = "%Y-%m-%d %H:%M:%S"
|
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt))
|
|
|
|
root = logging.getLogger()
|
|
# Avoid double-adding if called more than once (e.g. --reload)
|
|
if not root.handlers:
|
|
root.addHandler(handler)
|
|
root.setLevel(getattr(logging, level.upper(), logging.INFO))
|
|
|
|
# Quiet noisy third-party loggers
|
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
|
logging.getLogger("apscheduler").setLevel(logging.WARNING)
|
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|