import json import logging import traceback from typing import Optional, Dict, Any from db.database import get_db_pool from core.metrics import ERRORS_TOTAL logger = logging.getLogger("copykar.errors") async def log_exception(service_name: str, error: Exception, context: Optional[Dict[str, Any]] = None): """Log an exception to Database, Prometheus metrics, and Python logs.""" error_type = type(error).__name__ error_msg = str(error) tb_str = traceback.format_exc() ctx_json = json.dumps(context or {}, default=str) # 1. Prometheus Metric try: ERRORS_TOTAL.labels(service=service_name, error_type=error_type).inc() except Exception as e: logger.debug(f"Failed to increment error metric: {e}") # 2. Python standard logger logger.error(f"[{service_name}] {error_type}: {error_msg}\nContext: {ctx_json}\n{tb_str}") # 3. PostgreSQL Database try: pool = await get_db_pool() async with pool.acquire() as conn: await conn.execute( """ INSERT INTO error_logs (service_name, error_type, error_message, traceback, context) VALUES ($1, $2, $3, $4, $5::jsonb); """, service_name, error_type, error_msg, tb_str, ctx_json ) except Exception as db_err: logger.critical(f"Failed to write error to database: {db_err}")