Monitoring Spring Application using ELK and AspectJ — Part 2

Ramiz Mehran
lazypay-techblog
Published in
4 min readApr 14, 2018

Hey guys, for those of you who have not read the first part of this article here is the link. Check it out, that should help you get a basic understanding of what we are trying to accomplish here.

Time for the Spring project. A little overview on what we shall be doing here:

  1. Get a starter Spring project from here!
  2. Do basic configurations.
  3. Implement custom annotation, to be added to controllers/services that need monitoring.
  4. Use AspectJ to dynamically wrap those components with our implementation logic.
  5. Sending the logs to a logging handler.

II. Developing Spring-Based Monitoring Interface

The Spring Framework is an fast application development framework. It employs inversion of control container as its key defining feature. We’ll be taking the advantage of its ease of configuration to develop our monitoring interface. Let’s get started:

First, go here, and get yourself a project with the following configurations:

Group: com.ramizmehran

Artifact: monitoringInterface

Dependencies: Web, Aspects

Spring Boot Version: 1.5.* (Not Snapshot)

Let other details be the default.

Generate the project, extract and import in your favorite editor!

2. Configuring the Project

You will have a file by the name MonitoringInterfaceApplication.java, which acts as the starting point for a spring application. This class is not of much use to us, as our project is meant to be used as a dependency, and not a standalone project.

We will start by creating a configuration file , that shall be picked by the main application that we intend to add monitoring on. Create a class LoggingConfiguration.java at com.ramizmehran.monitoringInterface.configs package. To this class add the following annotations: @Configuration and @EnableAspectJAutoProxy.

This is to ensure, the application has AspectJ proxies enabled, as that is required for our implementation to work.

3. Custom Annotation — @Metered

Custom annotations are user defined annotations, used to define certain set of properties or values for an entity. That entity can be anything ranging from a class to a bean.

Let’s make an @interface file as described below:

This creates an annotation by the name Metered. This annotation has three properties:

  1. A String variable — value,
  2. A String array — logRequestBodyParamNames , and
  3. Another String array — logHeaderParamNames.

All three properties are nullable, as they have default empty values hence, it is not compulsory to pass these values with the annotation. An example on how to use the annotation is here:

4. AspectJ Wrapper

AspectJ is an aspect-oriented programming extension. Aspect-oriented programming is about dynamically weaving code into the existing source code, without having the alter it. To know more about it, try AspectJ In Action good book for beginners.

We’ll make an aspect named MeteredLoggingAspect. This aspect will look for all the controller methods that have the above annotation, and wrap them around with our code. The code for it is below:

Too much code!!! :D Don’t worry, I will give a gist of what I am doing here.

  1. We take the request parameters of the function being called.
  2. We initialize of logging request object with these parameters.
  3. Then, we let the function execution process by calling, joinPoint.proceed()
  4. After the function is executed, we take in the response as well to be logged
  5. We initiate an async hit to the logging service, and forget about it.
  6. Finally, we return the function’s return object back to the caller.

@Around method handles the case of a normal execution. But, in case of an exception the control will jump from joinPoint.proceed() to @AfterThrowing method. The logAfterThrowingAllMethods handles the exception scenarios, and thus help us log the error cases as well.

5. Log Polling Service

The service layer of our application will be responsible for accumulating all the data and then sending it forward. We will make a LoggingService, for this job. The code for it is below:

What it does:

  1. First initialize request is the one we called from the aspect, to get our request parameters ready.
  2. Then sendMeterLog function, polls the log for a happy scenario.
  3. While, sendExceptionLog function, polls log for exception cases.

Each function is quite simple, and does a small but specific job.

Finally, you might ask why am I storing the initial meterRequest in the httpRequest object. The reason for this is again exceptions. In case of an exception, I need the initial details to be sent forward. Hence, when stored in the httpRequest object I can easily fetch the attribute.

Conclusion

Now, you have a project that can be built into a jar, and then added as dependency to any project. The full project code is here, you can take it as a reference but I would strongly urge you not to, and try it out yourself.

For the people new to Spring, I will be posting a series of tutorial articles for that soon. Those articles will surely clear some of the doubts that you might have about the above application as a beginner.

The next article will have details about the application which shall take in requests and poll it to Logstash.

--

--

Ramiz Mehran
lazypay-techblog

The best version of pro-geek (Professional Geek :P). Likes to read, and experiment with latest trends. A knack for critical thinking and love for anything tech.