0

Im developing a RESTful application. One of the application task is to return 10 last business oriented REST calls made to the application with request information and time. What is the best way for doing this? I read about Interceptors and Filters. But Im not sure whether it is good idea... Any other ideas or information how to implemment this?

EDIT: I used Actuator. my solution after your responses:

@Service
public class ActuatorTraceService {

    private JsonParser jsonParser = new JsonParser();
    private List<String> listWithInformationFromTrace = new ArrayList<>();
    private JSONArray jsonArrayFromString;
    private JSONArray listWithoutRequestAndTracePath;

    public void takeInformationFromActuatorTrace() {
        jsonArrayFromString = new JSONArray("[{}]");
        String urlAddressForTrace = "http://localhost:8080/trace";
        jsonArrayFromString = new JSONArray(jsonParser.takeJsonAsAStringFromUrl(urlAddressForTrace));
    }

    public String createPathForCheck(int i) {
        String pathForCheck = jsonArrayFromString
                .getJSONObject(i)
                .getJSONObject("info")
                .get("path")
                .toString();
        return pathForCheck;
    }

    public void createListWithoutRequestAndTracePath() {
        listWithInformationFromTrace.clear();
        takeInformationFromActuatorTrace();
        listWithoutRequestAndTracePath = new JSONArray();

        for (int i = 0; i < jsonArrayFromString.length(); i++) {
            if (!createPathForCheck(i).equals("/request") &&
                    !createPathForCheck(i).equals("/trace")) {
                listWithoutRequestAndTracePath.put(jsonArrayFromString.get(i));
            }
        }
    }

    public List<String> createListWithInformationsFromTrace(){
        createListWithoutRequestAndTracePath();

        for (int i=0; i<listWithoutRequestAndTracePath.length(); i++){
            String timestampAndRequestInformation = takeTimestampFromTrace(i) + "\n" + takeRequestInformationFromTrace(i) + "\n";
            listWithInformationFromTrace.add(timestampAndRequestInformation);
        }
        return listWithInformationFromTrace;
    }

    public String takeRequestInformationFromTrace(int i) {
        return listWithoutRequestAndTracePath
                .getJSONObject(i)
                .getJSONObject("info")
                .getJSONObject("headers")
                .get("request")
                .toString()
                + "\n";
    }

    public String takeTimestampFromTrace(int i) {
        return jsonArrayFromString.getJSONObject(i).get("timestamp").toString() + "\n";
    }

    public String printLastTenRequestInformationFromTrace() {
        StringBuilder stringToPrint = new StringBuilder();
        createListWithInformationsFromTrace();

        if (listWithInformationFromTrace.size() > 10) {
            for (int i = 0; i < StaticValues.NUMBER_POSITION_TO_PRINT; i++) {
                stringToPrint.append(listWithInformationFromTrace.get(i));
            }
        } else {
            for (int i = 0; i < listWithInformationFromTrace.size(); i++) {
                stringToPrint.append(listWithInformationFromTrace.get(i));
            }
        }

        return stringToPrint.toString();
    }
}

Probably it could be a little bit more readable and pretty print should be implemented at the end, but just for now it works.

przemekost
  • 91
  • 2
  • 14
  • 1
    There are so many ways to do that.. from the simple "in every rest method, add a record to a static (synchronized) list" to a more interesting "ingest your access logs into ELK and query it using its REST API" – Erwin Bolwidt Jul 15 '17 at 14:55
  • I would also suggest the same way @erwin push your access logs into ELK or splunk and then query it to get your desired non-functional requirement. – Rishikesh Darandale Jul 15 '17 at 17:36
  • This may be irrelevant since you did not mentioned spring-boot anywhere. But if you are using spring boot actuator its /trace endpoint gives you the details you are looking for. Else there is spring AOP which you can use as mentioned in one of the answer below. – ravinikam Jul 16 '17 at 01:33

3 Answers3

1

There are lot way how you can do it.If you need persisted information (after server restarting all historical information should be used) you store it in :

1) create separate table for rest request information and use this table

2) use Logstash here is example

3)use some in-memory db to store rest call info

which of them use dependent on your requirements , I prefer Logstash as you can use it not only for particular rest call but reuse it for other parts of log logic.

JUST ANOTHER VARIANT If you don't want to persiste all historical information and you can work with fresh information after server restart you can keep it in memory (if you enought memeory for this) , you can srote in local collection but it's bad variant - you should keep a lot of redundant information and you do some soring to find top 10. IT'S NOT RECOMMENDATION , it's just possible variant , very bad variant.

To get information about rest call you can : use Interceptors ,Filters ,Logging aspect in RESTful web service using spring aop (log requests/responses) AOP.

xyz
  • 5,228
  • 2
  • 26
  • 35
0

One simplest way to achieve this is as following: 1. store the calls using loggers in the code for business rest calls 2. you store the calls by using rolling/circular buffer buffer 3. create a REST api request/response which sends the data from rolling/circular buffer.

0

If you can use Spring Boot then it would be easy to get HTTP request traces using Actuator

Official Documentation

Zico
  • 2,349
  • 2
  • 22
  • 25