Configuración de Aspectos y Logging en Spring Boot

Para integrar el registro de logs y la interceptación de métodos en un proyecto Spring Boot, es necesario configurar AspectJ (AOP) junto con Logback. A continuación, se detallen los pasos para implementar esta arquitectura de manera eficiente y limpia.

  1. Incorporación de dependencias en Maven

Primero, es fundamental añadir el iniciador de AOP de Spring Boot al archivo pom.xml. Esto habilitará el procesamiento de aspectos y las anotaciones relacionadas en el contexto de la aplicación.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. Configuración personalizada de Logback

En lugar de utilizar la configuración por defecto, crearemos un archivo logback-spring.xml dentro del directorio estándar de recursos (src/main/resources). Este archivo definirá las políticas de salida tanto para la consola como para archivos rotativos, optimizando el almacenamiento y la legibilidad.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property name="APP_LOG_DIR" value="/var/log/myapp" />
    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} | %highlight(%-5level) | %cyan(%logger{36}) - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${APP_LOG_DIR}/application.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${APP_LOG_DIR}/archived/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>15</maxHistory>
            <totalSizeCap>1GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="org.hibernate.SQL" level="DEBUG"/>
    <logger name="org.springframework.jdbc" level="DEBUG"/>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ROLLING_FILE" />
    </root>
</configuration>
  1. Implementación de la clase Aspecto

Para interceptar las llamadas a los métodos y registrar su comportamiento, definiremos una clase de aspecto. En lugar de usar la salida estándar del sistema (System.out), utilizaremos la API de SLF4J para aprovechar la configuración de Logback previamente definida, asegurando que los logs se dirijan a los appenders correctos.

package com.example.app.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MethodExecutionLogger {

    private static final Logger log = LoggerFactory.getLogger(MethodExecutionLogger.class);

    @Pointcut("execution(* com.example.app.service.impl.*.*(..))")
    private void serviceLayerExecution() {}

    @Pointcut("execution(* com.example.app.repository.*.*(..))")
    private void repositoryLayerExecution() {}

    @Before("serviceLayerExecution()")
    public void logMethodEntry(JoinPoint joinPoint) {
        log.info("Iniciando ejecución del método: {}", joinPoint.getSignature().toShortString());
    }

    @AfterReturning(pointcut = "serviceLayerExecution()", returning = "result")
    public void logMethodExit(JoinPoint joinPoint, Object result) {
        log.info("Método {} finalizado exitosamente.", joinPoint.getSignature().toShortString());
    }

    @AfterThrowing(pointcut = "serviceLayerExecution()", throwing = "ex")
    public void logMethodException(JoinPoint joinPoint, Throwable ex) {
        log.error("Error en el método {}: {}", joinPoint.getSignature().toShortString(), ex.getMessage());
    }

    @Around("repositoryLayerExecution()")
    public Object measureExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object response = pjp.proceed();
        long endTime = System.currentTimeMillis();
        log.debug("Tiempo de ejecución de {}: {} ms", pjp.getSignature().toShortString(), (endTime - startTime));
        return response;
    }
}

Etiquetas: Spring Boot AOP logback AspectJ java

Publicado el 7-14 08:22