Skip to content

Conversation

faizakram
Copy link
Owner

Overview

This PR introduces application-wide logging using Spring AOP to track method executions within the com.app package. The implementation ensures better visibility into method calls, arguments, and return values.

Changes Introduced

  • ✅ Added @Aspect-based logging in ApplicationLogging class.
  • ✅ Implemented @Pointcut to capture method executions across the application while excluding configuration classes.
  • ✅ Used @Before and @AfterReturning to log method entry and exit.
  • ✅ Integrated Lombok's @Log4j2 for structured logging.

Why this is needed?

  • Improves observability by providing logs for method calls and returned values.
  • Helps with debugging and monitoring application behavior in real-time.

How to Test?

  1. Run the Spring Boot application.
  2. Invoke any method in the com.app package.
  3. Check the application logs for structured method execution details.

@faizakram faizakram added documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers labels Feb 18, 2025
@@ -0,0 +1,35 @@
package com.app.config;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we used it through Annotation if we don't want to log entry exit for all methods then annotation also works better at that time just annotate a particular method.

annotation implementation
@aspect
@component
@order(1)
@slf4j
@SuppressWarnings("PMD.AvoidCatchingGenericException")
public class LoggingInterceptor
{

/**
 * StringBuilder message buffer init size.
 */
public static final int INIT_CAPACITY = 100;

/**
 * Interceptor method for methods.
 *
 * @param joinPoint The join point for the intercepted method.
 * @return Object
 * @throws Throwable Exceptions thrown by the intercepted method.
 */
@Around("@within(LogEntryAndExit) || @annotation(LogEntryAndExit)")
public Object intercept(final ProceedingJoinPoint joinPoint) throws Throwable
{
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Method method = signature.getMethod();
    String methodName = method.getName();
    String className = method.getDeclaringClass().getSimpleName();
    String parameters = getParameters(method);
    log.info("Entering {}:{}({})", className, methodName, parameters);
    Object out;

    try
    {
        out = joinPoint.proceed();
    } catch (Exception t)
    {
        logExceptions(t, method);
        throw t;
    } finally
    {
        log.info("Exiting {}:{}", className, methodName);
    }

    return out;
}

/**
 * Logging exceptions.
 *
 * @param t Exception to be logged.
 * @param method Method to me logged.
 */
private void logExceptions(final Throwable t, final Method method)
{
    String exceptionName = t.getClass().getSimpleName();
    String methodName = method.getName();
    String className = method.getDeclaringClass().getSimpleName();
    String parameters = getParameters(method);
    String message = String.format("\n%s thrown from %s:%s(%s)\n%s", exceptionName, className, methodName,
            parameters, t.getMessage());

    if (log.isDebugEnabled())
    {
        log.error(message, t);
    }
    else
    {
        log.error(message);
    }
}

/**
 * Get method parameters.
 *
 * @param method Method to be logged.
 * @return String
 */
private String getParameters(final Method method)
{
    StringBuilder sb = new StringBuilder(INIT_CAPACITY);

    Parameter[] params = method.getParameters();
    if (params.length > 0)
    {
        for (Parameter param : params)
        {
            if (param != null)
            {
                sb.append(param.getType().getSimpleName()).append(' ').append(param.getName()).append(", ");
            }
        }

        // remove trailing parameter separator
        sb.delete(sb.length() - 2, sb.length());
    }

    return sb.toString();
}

}
annotation code:-
@documented
@retention(RetentionPolicy.RUNTIME)
@target({ElementType.METHOD, ElementType.TYPE })
public @interface LogEntryAndExit
{

}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LogEntryAndExit will work now on methods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants