Logging Handler
Definición
Section titled “Definición”Los logs son registros de eventos que ocurren en tu aplicación. Son como un “diario” que te permite:
- Rastrear qué está pasando en tu sistema
- Debuggear problemas
- Monitorear el comportamiento
- Cumplir auditorías
Niveles de logging
Section titled “Niveles de logging”// Configuración típica en logback.xml o application.propertieslogger.trace("Información muy detallada para debugging");logger.debug("Información útil para desarrolladores");logger.info("Información general del flujo de la aplicación");logger.warn("Algo inusual pero no crítico");logger.error("Error que requiere atención");
Orden de severidad: TRACE
< DEBUG
< INFO
< WARN
< ERROR
Cuándo usar cada nivel
Section titled “Cuándo usar cada nivel”TRACE/DEBUG
Section titled “TRACE/DEBUG”- Cuando usar:
- Validaciones paso a paso
- Estados internos
- Llamadas a servicios externos
- Parámetros de entrada y salida
- SQL queries o operaciones de base de datos
public User findUser(Long id) { logger.debug("Buscando usuario con ID: {}", id); User user = userRepository.findById(id); logger.debug("Usuario encontrado: {}", user != null ? user.getEmail() : "null"); return user;}
- Cuando usar:
- Inicio y fin de operaciones importantes
- Cambios de estado importantes
- Operaciones de negocio clave
- Configuración y startup de aplicación
- Métricas de negocio importantes
- Integraciones externas exitosas
- Cuando no usar:
- Detalles internos o debugging
- Operaciones muy frecuentes
@PostMapping("/orders")public ResponseEntity<Order> createOrder(@RequestBody OrderRequest request) { logger.info("Creando nueva orden para usuario: {}", request.getUserEmail()); Order order = orderService.processOrder(request); logger.info("Orden creada exitosamente con ID: {}", order.getId()); return ResponseEntity.ok(order);}
- Cuando usar:
- Situaciones sospechosas pero válidas
- Reintentos
- Configuración subóptima
- Datos faltantes o incompletos
- Fallbacks o comportamientos degradados
- Límites alcanzados
public void processPayment(Payment payment) { if (payment.getAmount() > MAX_AMOUNT) { logger.warn("Pago por monto alto detectado: {} para usuario: {}", payment.getAmount(), payment.getUserId()); }
if (isWeekend()) { logger.warn("Procesando pago en fin de semana, puede tener retrasos"); }}
- Cuando usar:
- Error externo crítico
- Error de infraestructura
- Error inesperado
- Problemas de conectividad
- Problemas de configuración
- Inconsistencias de datos críticas
public void sendEmail(String email, String message) { try { emailService.send(email, message); } catch (EmailException e) { logger.error("Error enviando email a: {}, mensaje: {}", email, message, e); throw new NotificationException("No se pudo enviar email", e); }}
Logging con manejo de excepciones
Section titled “Logging con manejo de excepciones”Log y Re-throw (capa inferior)
Section titled “Log y Re-throw (capa inferior)”@Servicepublic class PaymentService {
public void processPayment(PaymentRequest request) { try { // lógica de pago paymentGateway.charge(request); logger.info("Pago procesado exitosamente para usuario: {}", request.getUserId());
} catch (PaymentGatewayException e) { // Log con contexto y re-throw logger.error("Error en gateway de pago para usuario: {}, monto: {}", request.getUserId(), request.getAmount(), e); throw new PaymentProcessingException("Error procesando pago", e); } }}
Log y Handle (capa superior)
Section titled “Log y Handle (capa superior)”@RestControllerpublic class OrderController {
@PostMapping("/orders") public ResponseEntity<?> createOrder(@RequestBody OrderRequest request) { try { Order order = orderService.processOrder(request); return ResponseEntity.ok(order);
} catch (PaymentProcessingException e) { // Log final y respuesta al usuario logger.warn("Orden rechazada por fallo en pago para usuario: {}", request.getUserEmail()); return ResponseEntity.badRequest() .body(new ErrorResponse("No se pudo procesar el pago"));
} catch (Exception e) { // Error inesperado logger.error("Error inesperado procesando orden para usuario: {}", request.getUserEmail(), e); return ResponseEntity.status(500) .body(new ErrorResponse("Error interno del servidor")); } }}
Mejores prácticas
Section titled “Mejores prácticas”Usa placeholders, no concatenación
Section titled “Usa placeholders, no concatenación”// ❌ Malologger.info("Usuario " + user.getName() + " realizó compra por " + amount);
// ✅ Buenologger.info("Usuario {} realizó compra por {}", user.getName(), amount);
Incluye contexto relevante
Section titled “Incluye contexto relevante”// ❌ Poco útillogger.error("Error en base de datos", e);
// ✅ Útillogger.error("Error ejecutando query para usuario ID: {}, tabla: users", userId, e);
No loggees información sensible
Section titled “No loggees información sensible”// ❌ Peligrosologger.info("Usuario autenticado: {}, password: {}", username, password);
// ✅ Segurologger.info("Usuario autenticado: {}", username);
Estructura consistente
Section titled “Estructura consistente”public class OrderService { private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
public Order processOrder(OrderRequest request) { String correlationId = UUID.randomUUID().toString();
logger.info("[{}] Iniciando procesamiento de orden para usuario: {}", correlationId, request.getUserEmail());
try { // validaciones validateOrder(request); logger.debug("[{}] Validaciones completadas", correlationId);
// procesar pago processPayment(request); logger.debug("[{}] Pago procesado", correlationId);
// crear orden Order order = createOrder(request); logger.info("[{}] Orden creada exitosamente con ID: {}", correlationId, order.getId());
return order;
} catch (ValidationException e) { logger.warn("[{}] Validación fallida para usuario: {}, error: {}", correlationId, request.getUserEmail(), e.getMessage()); throw e;
} catch (Exception e) { logger.error("[{}] Error inesperado procesando orden para usuario: {}", correlationId, request.getUserEmail(), e); throw new OrderProcessingException("Error procesando orden", e); } }}
Configuración
Section titled “Configuración”# Nivel raízlogging.level.root=INFO
# Tu aplicación en DEBUGlogging.level.com.tuempresa.tuapp=DEBUG
# Librerías externas en WARNlogging.level.org.springframework=WARNlogging.level.org.hibernate=WARN
# Archivo de logslogging.file.name=logs/application.loglogging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n