import json import logging import sys from datetime import datetime, timezone from typing import Any, Dict, Optional class StructuredJsonFormatter(logging.Formatter): """ JSON log formatter emitting structured log records with standard telecom pipeline fields: - timestamp (ISO 8601 UTC) - level (INFO, WARN, ERROR, DEBUG) - service (service name) - raw_id (record identifier or None) - event (message string) """ def __init__(self, service_name: str): super().__init__() self.service_name = service_name def format(self, record: logging.LogRecord) -> str: log_entry: Dict[str, Any] = { "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), "level": record.levelname, "service": getattr(record, "service", self.service_name), "raw_id": getattr(record, "raw_id", None), "event": getattr(record, "event", record.getMessage()), "message": record.getMessage(), } # Include exception info if present if record.exc_info: log_entry["exception"] = self.formatException(record.exc_info) # Include additional extra context fields if present for key, value in record.__dict__.items(): if key not in { "name", "msg", "args", "levelname", "levelno", "pathname", "filename", "module", "exc_info", "exc_text", "stack_info", "lineno", "funcName", "created", "msecs", "relativeCreated", "thread", "threadName", "processName", "process", "raw_id", "service", }: log_entry[key] = value return json.dumps(log_entry, default=str) def setup_logger( service_name: str, level: Optional[str] = None ) -> logging.Logger: """ Configures and returns a logger configured with StructuredJsonFormatter on stdout. """ if level is None: from app.common.config import config level = config.log_level logger = logging.getLogger(service_name) logger.setLevel(getattr(logging, level.upper(), logging.INFO)) logger.propagate = False # Avoid duplicate handlers if setup is called multiple times if not logger.handlers: handler = logging.StreamHandler(sys.stdout) handler.setFormatter(StructuredJsonFormatter(service_name=service_name)) logger.addHandler(handler) return logger