Elshan Akberov
Elshan Akberov

Reputation: 83

Spring Boot Logging HTTP request and response and write logs to an SQL database

I have developed simple REST JSON wrapper for public SOAP web service. The web service is for a simple calculator with 4 methods: Add, Divide, Multiply and Subtract.

REST wrapper works fine. My next goal is to log each request and response between REST wrapper and SOAP web service then write log entries to an SQL database.

I have two main problems for completing the task.

  1. I don't know how to intercept request and response between wrapper and web service to generate logs.

  2. For testing purpose have tried to generate and write log entries to an SQL database with DBAppender but DBAppender generates 3 tables. But I want to write logs to custom tables.

Upvotes: 0

Views: 2527

Answers (2)

saurabh.in
saurabh.in

Reputation: 409

In addition to Klaus' answer, I would like to add that you could get to the pointcut (method (s) you want to intercept) by using a custom annotation.

So you could define your annotation like this:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogCallToDB {
}

Then you could define the aspect around this annotation:

@Aspect
@Component
@Slf4j
public class LoggingToDBAspect {

@Around("@annotation(com.myltdcompany.myproject.infra.utils.LogCallToDB)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {

    Object proceed = joinPoint.proceed();

    final Signature signature = joinPoint.getSignature();
    Object[] args = joinPoint.getArgs();

    // write to DB using some wrapper like CallLoggingRepository

    return proceed;
}

And then you could simply use the annotation @LogCallToDB on top of any method for which you want to log an entry to DB. Example:

@LogCallToDB
public doubl add(double a, double b) {
  return a+b;
}

Upvotes: 0

Klaus
Klaus

Reputation: 1731

A popular approach for logging requests and responses is to use spring-aop. However, it is recommended not to do performance intensive operations on spring-aop. This is an example of using spring-aop in your use case. However, rather than querying the DB everytime for request or response log it is better if you could find a way to process the logs in batches to avoid DB access overhead.

Add the spring-boot-starter-aop dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Enable AspectJAutoproxy for the spring application

@SpringBootApplication( )
@EnableAspectJAutoProxy( proxyTargetClass = true )
public class Application
{
    public static void main( String[] args )
    {
        SpringApplication.run( Application.class, args );
    }
}

Add the aspect class

@Aspect
@Component
public class CalculatorAspect
{
    private Logger LOGGER = Logger.getLogger( getClass().getName() );

    @Around( "execution(* com.example.Calculator.add(..))" ) // Add method
    public Object logInfoAboutAddOperation( ProceedingJoinPoint joinPoint ) throws Throwable
    {
        // Log here for request using joinPoint variable information
        // and add the necessary entries to DB
        Object proceed = joinPoint.proceed(); // This instructs the target to proceed with method execution which is the add() method
        // Log here for response and add the necessary info to DB

        return proceed; // This is mandatory and this contains the result of add() method. You can even change the actual result here
    }
}

There are various ways this can be done to suit your requirement. Please have a look at this link for more information about spring-aop. By using the relevant Advice you can log request and responses at Controller layer too.

Upvotes: 1

Related Questions