Logging
Patron Obligatorio
from {PACKAGE_NAME}.infrastructure.logging import get_logger
logger = get_logger(__name__)
NUNCA: logging.getLogger(), print() para debugging, logger.exception() fuera de except.
Niveles
| Nivel |
Cuando usar |
Ejemplo |
DEBUG |
Detalle tecnico para investigar |
logger.debug("Query: %s params: %s", sql, params) |
INFO |
Eventos de negocio relevantes |
logger.info("Documento procesado: %s", doc_id) |
WARNING |
Situacion inesperada pero recuperable |
logger.warning("Timeout reintentando: %s", url) |
ERROR |
Error que afecta funcionalidad |
logger.error("Fallo procesamiento", exc_info=True) |
Que Loguear por Componente
| Componente |
INFO |
WARNING |
ERROR |
| Use Cases |
Inicio/fin operacion |
Fallback activado |
Fallo en operacion |
| Repository |
— |
Query lenta (>1s) |
Error conexion BD |
| API/GUI |
Request recibido |
Rate limit alcanzado |
Error no manejado |
| Infrastructure |
Servicio inicializado |
Dependencia lenta |
Dependencia caida |
Patron para Clases ABC
class BaseProcessor(ABC):
def __init__(self) -> None:
self._logger = get_logger(
f"{__name__}.{self.__class__.__name__}"
)
Configuracion
# Ejemplo de logger_config.py minimo
import logging
from pathlib import Path
LOG_DIR = Path("logs")
LOG_DIR.mkdir(exist_ok=True)
def get_logger(name: str) -> logging.Logger:
logger = logging.getLogger(f"ProjectName.{name}")
if not logger.handlers:
handler = logging.FileHandler(LOG_DIR / "app.log")
handler.setFormatter(
logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
return logger
Ubicacion de Archivos de Log
logs/
├── app.log # Log general de la aplicacion
└── YYYY-MM-DD.log # Rotacion diaria (si aplica)