Decisión
log_action() es best-effort — cualquier fallo en escribir el log de auditoría nunca rompe la request del usuario. Las excepciones se capturan, se loguean internamente, y se ignoran.
Status: Adoptado (2026-06-07, PR #71)
Contexto
Problema
Las mutaciones en ITSM/alertas/wireless/UPS son críticas y deben completarse incluso si la capa de auditoría falla:
- Un operador elimina una alerta falsa-positiva → la alerta debe desaparecer ahora mismo
- Si
SystemLogestá lento o la BD saturada, no podemos dejar la alerta activa - Un fallo de auditoría es mejor que un fallo de negocio
Alternativas consideradas
-
Síncrono + fail-fast:
log_action()lanza si hay error- ❌ Riesgo: Un problema de BD bloquea todas las mutaciones
- ❌ UX: Usuario ve error en request de negocio puro (ej: “delete failed — logging error”)
-
Asincrónico (Celery): Encolamos el log en background
- ✅ No bloquea request
- ⚠️ Complejidad: Celery broker + workers + retry logic
- ⚠️ Pérdida eventual: Si worker falla persistentemente, log se pierde silenciosamente
- ❌ Overhead: Para ~20 mutaciones/min, no justifica Celery
-
Best-effort (elegido):
- ✅ Síncrono pero aislado en try-except
- ✅ Request nunca se afecta
- ✅ Fallos registrados en logger para debugging
- ✅ Simplicidad: una función, sin deps externas
Decisión
Best-effort: log_action() intenta escribir SystemLog, pero si falla por cualquier razón, la excepción se captura y se loguea a logging.getLogger("core"). La función retorna None siempre, nunca lanza.
def log_action(request, category: str, action: str, details: str = "", level: str = "INFO") -> None:
try:
# ... resolve org, user, create SystemLog ...
except Exception:
logger.exception("log_action failed (category=%s action=%s)", category, action)
# NCA: nunca re-raise
Implicaciones
Positivas
- ✅ Garantía: Mutación completa incluso si auditoría falla
- ✅ Resiliencia: Problema de logging ≠ problema de negocio
- ✅ Simplicidad: Sin Celery, sin broker, sin retry logic
- ✅ Monitoreo: Fallo se registra → alertar si tasa de “log_action failed” > 0.1%
Negativas (aceptadas)
- ❌ Posible pérdida de logs: Si excepción persistente, algunos eventos no se auditan
- ❌ Debugging difícil: Sin logs de auditoría, investigar cambios inesperados toma más tiempo
- ⚠️ Compliance: Pérdida de trazabilidad en un % pequeño de mutaciones (trade-off)
Monitoreo recomendado
ALERT log_action_failure_rate > 0.1%
IF increase(log_action_failures_total[5m]) / increase(mutations_total[5m]) > 0.001
Alternativa futura: Celery + queue fallback
Si la tasa de pérdida de logs crece o compliance requiere 100% trazabilidad:
- Cambiar a
log_action_async(request, ...)con Celery - Implementar fallback local: encolar en SQLite si broker no disponible
- Worker consume localmente cuando broker recupera
Costo: +2-3 días de dev + mantenimiento de broker.
Referencias
- Principio de solidez: Una feature auxiliar (auditoría) no debe romper la feature principal (mutación)
- Fail-open vs fail-closed: Aquí elegimos fail-open (auditoría ausente es tolerable)
- Observabilidad: Logger + métricas compensan la garantía débil
Véase también
- [[entity—core—service—log-action]]
- [[entity—core—model—systemlog]]
- [[feature—monitoring—audit-logs-mutaciones-sa4-sa5]]
- [[concept—saas—observability]]